[PATCH v2 1/2] winevulkan: Generate a separate physical device dispatch table.

Georg Lehmann dadschoorse at gmail.com
Tue Mar 23 12:42:46 CDT 2021


Signed-off-by: Georg Lehmann <dadschoorse at gmail.com>
---
 dlls/winevulkan/make_vulkan      | 47 +++++++++++++++++++++++++++-----
 dlls/winevulkan/vulkan.c         |  6 +++-
 dlls/winevulkan/vulkan_private.h |  1 +
 3 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 3ad210e4701..a4c4d16eaaa 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -584,7 +584,7 @@ class VkFunction(object):
 
     def is_device_func(self):
         # If none of the other, it must be a device function
-        return not self.is_global_func() and not self.is_instance_func()
+        return not self.is_global_func() and not self.is_instance_func() and not self.is_phys_dev_func()
 
     def is_driver_func(self):
         """ Returns if function is part of Wine driver interface. """
@@ -601,8 +601,14 @@ class VkFunction(object):
         return True
 
     def is_instance_func(self):
-        # Instance functions are passed VkInstance or VkPhysicalDevice.
-        if self.params[0].type in ["VkInstance", "VkPhysicalDevice"]:
+        # Instance functions are passed VkInstance.
+        if self.params[0].type == "VkInstance":
+            return True
+        return False
+
+    def is_phys_dev_func(self):
+        # Physical device functions are passed VkPhysicalDevice.
+        if self.params[0].type == "VkPhysicalDevice":
             return True
         return False
 
@@ -2270,6 +2276,14 @@ class VkGenerator(object):
             f.write("    {{\"{0}\", &{1}{0}}},\n".format(vk_func.name, prefix))
         f.write("};\n\n")
 
+        f.write("static const struct vulkan_func vk_phys_dev_dispatch_table[] =\n{\n")
+        for vk_func in self.registry.phys_dev_funcs:
+            if not vk_func.is_required():
+                continue
+
+            f.write("    {{\"{0}\", &{1}{0}}},\n".format(vk_func.name, prefix))
+        f.write("};\n\n")
+
         f.write("static const struct vulkan_func vk_instance_dispatch_table[] =\n{\n")
         for vk_func in self.registry.instance_funcs:
             if not vk_func.is_required():
@@ -2292,6 +2306,20 @@ class VkGenerator(object):
         f.write("    return NULL;\n")
         f.write("}\n\n")
 
+        f.write("void *wine_vk_get_phys_dev_proc_addr(const char *name)\n")
+        f.write("{\n")
+        f.write("    unsigned int i;\n")
+        f.write("    for (i = 0; i < ARRAY_SIZE(vk_phys_dev_dispatch_table); i++)\n")
+        f.write("    {\n")
+        f.write("        if (strcmp(vk_phys_dev_dispatch_table[i].name, name) == 0)\n")
+        f.write("        {\n")
+        f.write("            TRACE(\"Found name=%s in physical device table\\n\", debugstr_a(name));\n")
+        f.write("            return vk_phys_dev_dispatch_table[i].func;\n")
+        f.write("        }\n")
+        f.write("    }\n")
+        f.write("    return NULL;\n")
+        f.write("}\n\n")
+
         f.write("void *wine_vk_get_instance_proc_addr(const char *name)\n")
         f.write("{\n")
         f.write("    unsigned int i;\n")
@@ -2434,7 +2462,7 @@ class VkGenerator(object):
 
         f.write("/* For use by vkInstance and children */\n")
         f.write("struct vulkan_instance_funcs\n{\n")
-        for vk_func in self.registry.instance_funcs:
+        for vk_func in self.registry.instance_funcs + self.registry.phys_dev_funcs:
             if not vk_func.is_required():
                 continue
 
@@ -2471,7 +2499,7 @@ class VkGenerator(object):
 
         f.write("#define ALL_VK_INSTANCE_FUNCS() \\\n")
         first = True
-        for vk_func in self.registry.instance_funcs:
+        for vk_func in self.registry.instance_funcs + self.registry.phys_dev_funcs:
             if not vk_func.is_required():
                 continue
 
@@ -2635,7 +2663,7 @@ class VkGenerator(object):
         f.write("\n")
         f.write("    if (!instance) return NULL;\n\n")
         for vk_func in self.registry.funcs.values():
-            if vk_func.is_driver_func() and vk_func.is_instance_func():
+            if vk_func.is_driver_func() and (vk_func.is_instance_func() or vk_func.is_phys_dev_func()):
                 f.write('    if (!strcmp(name, "{0}"))\n'.format(vk_func.name[2:]))
                 f.write('        return vulkan_funcs->p_{0};\n'.format(vk_func.name))
         f.write("\n")
@@ -2836,21 +2864,26 @@ class VkRegistry(object):
             funcs[func.name] = func
 
         # To make life easy for the code generation, separate all function
-        # calls out in the 3 types of Vulkan functions: device, global and instance.
+        # calls out in the 4 types of Vulkan functions:
+        # device, global, physical device and instance.
         device_funcs = []
         global_funcs = []
+        phys_dev_funcs = []
         instance_funcs = []
         for func in funcs.values():
             if func.is_device_func():
                 device_funcs.append(func)
             elif func.is_global_func():
                 global_funcs.append(func)
+            elif func.is_phys_dev_func():
+                phys_dev_funcs.append(func)
             else:
                 instance_funcs.append(func)
 
         # Sort function lists by name and store them.
         self.device_funcs = sorted(device_funcs, key=lambda func: func.name)
         self.global_funcs = sorted(global_funcs, key=lambda func: func.name)
+        self.phys_dev_funcs = sorted(phys_dev_funcs, key=lambda func: func.name)
         self.instance_funcs = sorted(instance_funcs, key=lambda func: func.name)
 
         # The funcs dictionary is used as a convenient way to lookup function
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index 971394eb9dd..87cbc3b0e4c 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -1156,7 +1156,8 @@ PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *
      * https://github.com/KhronosGroup/Vulkan-Docs/issues/655
      */
     if (device->quirks & WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
-            && (func = wine_vk_get_instance_proc_addr(name)))
+            && ((func = wine_vk_get_instance_proc_addr(name))
+             || (func = wine_vk_get_phys_dev_proc_addr(name))))
     {
         WARN("Returning instance function %s.\n", debugstr_a(name));
         return func;
@@ -1219,6 +1220,9 @@ PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance, const
     func = wine_vk_get_instance_proc_addr(name);
     if (func) return func;
 
+    func = wine_vk_get_phys_dev_proc_addr(name);
+    if (func) return func;
+
     /* vkGetInstanceProcAddr also loads any children of instance, so device functions as well. */
     func = wine_vk_get_device_proc_addr(name);
     if (func) return func;
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h
index 4a41a15461e..322d27079ea 100644
--- a/dlls/winevulkan/vulkan_private.h
+++ b/dlls/winevulkan/vulkan_private.h
@@ -232,6 +232,7 @@ static inline VkSurfaceKHR wine_surface_to_handle(struct wine_surface *surface)
 }
 
 void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;
+void *wine_vk_get_phys_dev_proc_addr(const char *name) DECLSPEC_HIDDEN;
 void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
 
 BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN;
-- 
2.31.0




More information about the wine-devel mailing list