diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py index 1c34799f562..3c5af02dbdd 100644 --- a/src/gallium/drivers/zink/zink_device_info.py +++ b/src/gallium/drivers/zink/zink_device_info.py @@ -268,9 +268,20 @@ struct zink_device_info { bool zink_get_physical_device_info(struct zink_screen *screen); -bool +void zink_verify_device_extensions(struct zink_screen *screen); +/* stub functions that get inserted into the dispatch table if they are not + * properly loaded. + */ +%for ext in extensions: +%if registry.in_registry(ext.name): +%for cmd in registry.get_registry_entry(ext.name).device_commands: +void zink_stub_${cmd.lstrip("vk")}(void); +%endfor +%endif +%endfor + #endif """ @@ -443,7 +454,7 @@ fail: return false; } -bool +void zink_verify_device_extensions(struct zink_screen *screen) { %for ext in extensions: @@ -451,16 +462,45 @@ zink_verify_device_extensions(struct zink_screen *screen) if (screen->info.have_${ext.name_with_vendor()}) { %for cmd in registry.get_registry_entry(ext.name).device_commands: if (!screen->vk.${cmd.lstrip("vk")}) { - mesa_loge("ZINK: GetDeviceProcAddr failed: ${cmd}\\n"); - return false; +#ifndef NDEBUG + screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")}; +#else + screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded; +#endif } %endfor } %endif %endfor - - return true; } + +#ifndef NDEBUG +/* generated stub functions */ +## remember the stub functions that are already generated +<% generated_funcs = set() %> + +%for ext in extensions: +%if registry.in_registry(ext.name): +%for cmd in registry.get_registry_entry(ext.name).device_commands: +## +## some functions are added by multiple extensions, which creates duplication +## and thus redefinition of stubs (eg. vkCmdPushDescriptorSetWithTemplateKHR) +## +%if cmd in generated_funcs: + <% continue %> +%else: + <% generated_funcs.add(cmd) %> +%endif +void +zink_stub_${cmd.lstrip("vk")}() +{ + mesa_loge("ZINK: ${cmd} is not loaded properly!"); + abort(); +} +%endfor +%endif +%endfor +#endif """ @@ -531,7 +571,7 @@ if __name__ == "__main__": lookup.put_string("helpers", include_template) with open(header_path, "w") as header_file: - header = Template(header_code, lookup=lookup).render(extensions=extensions, versions=versions).strip() + header = Template(header_code, lookup=lookup).render(extensions=extensions, versions=versions, registry=registry).strip() header = replace_code(header, replacement) print(header, file=header_file) diff --git a/src/gallium/drivers/zink/zink_instance.py b/src/gallium/drivers/zink/zink_instance.py index 5d5a683a849..9431a20d1bb 100644 --- a/src/gallium/drivers/zink/zink_instance.py +++ b/src/gallium/drivers/zink/zink_instance.py @@ -87,9 +87,23 @@ struct zink_instance_info { VkInstance zink_create_instance(struct zink_instance_info *instance_info); -bool +void zink_verify_instance_extensions(struct zink_screen *screen); +/* stub functions that get inserted into the dispatch table if they are not + * properly loaded. + */ +%for ext in extensions: +%if registry.in_registry(ext.name): +%for cmd in registry.get_registry_entry(ext.name).instance_commands: +void zink_stub_${cmd.lstrip("vk")}(void); +%endfor +%for cmd in registry.get_registry_entry(ext.name).pdevice_commands: +void zink_stub_${cmd.lstrip("vk")}(void); +%endfor +%endif +%endfor + #endif """ @@ -218,7 +232,7 @@ zink_create_instance(struct zink_instance_info *instance_info) return instance; } -bool +void zink_verify_instance_extensions(struct zink_screen *screen) { %for ext in extensions: @@ -226,22 +240,51 @@ zink_verify_instance_extensions(struct zink_screen *screen) if (screen->instance_info.have_${ext.name_with_vendor()}) { %for cmd in registry.get_registry_entry(ext.name).instance_commands: if (!screen->vk.${cmd.lstrip("vk")}) { - mesa_loge("ZINK: GetInstanceProcAddr failed: ${cmd}\\n"); - return false; +#ifndef NDEBUG + screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")}; +#else + screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded; +#endif } %endfor %for cmd in registry.get_registry_entry(ext.name).pdevice_commands: if (!screen->vk.${cmd.lstrip("vk")}) { - mesa_loge("ZINK: GetInstanceProcAddr failed: ${cmd}\\n"); - return false; +#ifndef NDEBUG + screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")}; +#else + screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded; +#endif } %endfor } %endif %endfor - - return true; } + +#ifndef NDEBUG +/* generated stub functions */ +## see zink_device_info.py for why this is needed +<% generated_funcs = set() %> + +%for ext in extensions: +%if registry.in_registry(ext.name): +%for cmd in registry.get_registry_entry(ext.name).instance_commands + registry.get_registry_entry(ext.name).pdevice_commands: +%if cmd in generated_funcs: + <% continue %> +%else: + <% generated_funcs.add(cmd) %> +%endif +void +zink_stub_${cmd.lstrip("vk")}() +{ + mesa_loge("ZINK: ${cmd} is not loaded properly!"); + abort(); +} +%endfor +%endif +%endfor + +#endif """ @@ -298,7 +341,7 @@ if __name__ == "__main__": exit(1) with open(header_path, "w") as header_file: - header = Template(header_code).render(extensions=extensions, layers=layers).strip() + header = Template(header_code).render(extensions=extensions, layers=layers, registry=registry).strip() header = replace_code(header, replacement) print(header, file=header_file) diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index f6a21595f7d..abbdaaf4f08 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -1586,8 +1586,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config) vk_instance_dispatch_table_load(&screen->vk.instance, &vkGetInstanceProcAddr, screen->instance); vk_physical_device_dispatch_table_load(&screen->vk.physical_device, &vkGetInstanceProcAddr, screen->instance); - if (!zink_verify_instance_extensions(screen)) - goto fail; + zink_verify_instance_extensions(screen); if (screen->instance_info.have_EXT_debug_utils && (zink_debug & ZINK_DEBUG_VALIDATION) && !create_debug(screen)) @@ -1628,8 +1627,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config) vk_device_dispatch_table_load(&screen->vk.device, &vkGetDeviceProcAddr, screen->dev); - if (!zink_verify_device_extensions(screen)) - goto fail; + zink_verify_device_extensions(screen); if (screen->info.have_EXT_calibrated_timestamps && !check_have_device_time(screen)) goto fail; @@ -1775,3 +1773,12 @@ zink_drm_create_screen(int fd, const struct pipe_screen_config *config) return &ret->base; } + +void zink_stub_function_not_loaded() +{ + /* this will be used by the zink_verify_*_extensions() functions on a + * release build + */ + mesa_loge("ZINK: a Vulkan function was called without being loaded"); + abort(); +} diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h index d03bb9dd3c2..8008b39f5d4 100644 --- a/src/gallium/drivers/zink/zink_screen.h +++ b/src/gallium/drivers/zink/zink_screen.h @@ -265,4 +265,7 @@ zink_screen_update_pipeline_cache(struct zink_screen *screen); void zink_screen_init_descriptor_funcs(struct zink_screen *screen, bool fallback); + +void +zink_stub_function_not_loaded(void); #endif