Mesa (main): zink: move extension function verification to when it is used

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun Jun 13 19:09:02 UTC 2021


Module: Mesa
Branch: main
Commit: b5d344c3af8190db302fd00f1d491582e2c102c4
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=b5d344c3af8190db302fd00f1d491582e2c102c4

Author: Hoe Hao Cheng <haochengho12907 at gmail.com>
Date:   Sat Jun 12 00:36:32 2021 +0800

zink: move extension function verification to when it is used

Some vulkan functions are not loaded when the corresponding features are
not enabled, but the verifier checks for *all* functions, so make the
verifier more forgiving and use a stub to catch when we actually use a
function that is not loaded.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11328>

---

 src/gallium/drivers/zink/zink_device_info.py | 52 +++++++++++++++++++++---
 src/gallium/drivers/zink/zink_instance.py    | 59 ++++++++++++++++++++++++----
 src/gallium/drivers/zink/zink_screen.c       | 15 +++++--
 src/gallium/drivers/zink/zink_screen.h       |  3 ++
 4 files changed, 111 insertions(+), 18 deletions(-)

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
+}
+
+#ifndef NDEBUG
+/* generated stub functions */
+## see zink_device_info.py for why this is needed
+<% generated_funcs = set() %>
 
-   return true;
+%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



More information about the mesa-commit mailing list