[PATCH v5 2/4] winevulkan: Add instance funcs stubs.
Józef Kucia
jkucia at codeweavers.com
Thu Mar 1 09:37:04 CST 2018
From: Roderick Colenbrander <thunderbird2k at gmail.com>
Signed-off-by: Roderick Colenbrander <thunderbird2k at gmail.com>
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
dlls/winevulkan/Makefile.in | 3 +-
dlls/winevulkan/make_vulkan | 194 ++++++++++++++++++++++++++++++++++++++-
dlls/winevulkan/vulkan.c | 13 +--
dlls/winevulkan/vulkan_private.h | 12 +++
dlls/winevulkan/vulkan_thunks.c | 106 +++++++++++++++++++++
dlls/winevulkan/vulkan_thunks.h | 9 ++
6 files changed, 322 insertions(+), 15 deletions(-)
create mode 100644 dlls/winevulkan/vulkan_thunks.c
create mode 100644 dlls/winevulkan/vulkan_thunks.h
diff --git a/dlls/winevulkan/Makefile.in b/dlls/winevulkan/Makefile.in
index 859c731c6e4c..a3c40bd39864 100644
--- a/dlls/winevulkan/Makefile.in
+++ b/dlls/winevulkan/Makefile.in
@@ -2,6 +2,7 @@ MODULE = winevulkan.dll
IMPORTS = user32 gdi32
C_SRCS = \
- vulkan.c
+ vulkan.c \
+ vulkan_thunks.c
RC_SRCS = version.rc
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index fd2fd7bd779b..c22619af1bf6 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -65,6 +65,8 @@ LOGGER.addHandler(logging.StreamHandler())
# Filenames to create.
WINE_VULKAN_H = "../../include/wine/vulkan.h"
WINE_VULKAN_DRIVER_H = "../../include/wine/vulkan_driver.h"
+WINE_VULKAN_THUNKS_C = "vulkan_thunks.c"
+WINE_VULKAN_THUNKS_H = "vulkan_thunks.h"
# Functions part of our winevulkan graphics driver interface.
@@ -76,15 +78,18 @@ DRIVER_VERSION = 1
# This are regular device / instance functions for which we need
# to more work compared to a regular thunk or because they are
# part of the driver interface.
+# - dispatch set whether we need a function pointer in the device
+# / instance dispatch table.
# - driver sets whether the api is part of the driver interface.
+# - thunk sets whether to create a thunk in vulkan_thunks.c.
FUNCTION_OVERRIDES = {
# Global functions
- "vkCreateInstance" : {"driver" : True},
- "vkEnumerateInstanceExtensionProperties" : {"driver" : True},
- "vkGetInstanceProcAddr": {"driver" : True},
+ "vkCreateInstance" : {"dispatch" : False, "driver" : True, "thunk" : False},
+ "vkEnumerateInstanceExtensionProperties" : {"dispatch" : False, "driver" : True, "thunk" : False},
+ "vkGetInstanceProcAddr": {"dispatch" : False, "driver" : True, "thunk" : False},
# Instance functions
- "vkDestroyInstance" : {"driver" : True},
+ "vkDestroyInstance" : {"dispatch" : True, "driver" : True, "thunk" : True },
}
@@ -256,7 +261,9 @@ class VkFunction(object):
# For some functions we need some extra metadata from FUNCTION_OVERRIDES.
func_info = FUNCTION_OVERRIDES.get(self.name, None)
+ self.dispatch = func_info["dispatch"] if func_info is not None else True
self.driver = func_info["driver"] if func_info is not None else False
+ self.thunk_needed = func_info["thunk"] if func_info is not None else True
# Required is set while parsing which APIs and types are required
# and is used by the code generation.
@@ -303,6 +310,12 @@ class VkFunction(object):
def is_required(self):
return self.required
+ def needs_dispatch(self):
+ return self.dispatch
+
+ def needs_thunk(self):
+ return self.thunk_needed
+
def pfn(self, call_conv=None, conv=False):
""" Create function pointer. """
@@ -359,6 +372,48 @@ class VkFunction(object):
return proto
+ def stub(self, call_conv=None, prefix=None):
+ stub = self.prototype(call_conv=call_conv, prefix=prefix)
+ stub += "\n{\n"
+ stub += " {0}".format(self.trace(message="stub: ", trace_func="FIXME"))
+
+ if self.type == "VkResult":
+ stub += " return VK_ERROR_OUT_OF_HOST_MEMORY;\n"
+ elif self.type == "VkBool32":
+ stub += " return VK_FALSE;\n"
+
+ stub += "}\n\n"
+ return stub
+
+ def trace(self, message=None, trace_func=None):
+ """ Create a trace string including all parameters.
+
+ Args:
+ message (str, optional): text to print at start of trace message e.g. 'stub: '
+ trace_func (str, optional): used to override trace function e.g. FIXME, printf, etcetera.
+ """
+ if trace_func is not None:
+ trace = "{0}(\"".format(trace_func)
+ else:
+ trace = "TRACE(\""
+
+ if message is not None:
+ trace += message
+
+ # First loop is for all the format strings.
+ trace += ", ".join([p.format_string() for p in self.params])
+ trace += "\\n\""
+
+ # Second loop for parameter names and optional conversions.
+ for param in self.params:
+ if param.format_conv is not None:
+ trace += ", " + param.format_conv.format(param.name)
+ else:
+ trace += ", {0}".format(param.name)
+ trace += ");\n"
+
+ return trace
+
class VkFunctionPointer(object):
def __init__(self, _type, name, members):
@@ -628,6 +683,8 @@ class VkParam(object):
self.handle = type_info["data"] if type_info["category"] == "handle" else None
self.struct = type_info["data"] if type_info["category"] == "struct" else None
+ self._set_format_string()
+
def __repr__(self):
return "{0} {1} {2} {3} {4}".format(self.const, self.type, self.pointer, self.name, self.array_len, self.dyn_array_len)
@@ -663,6 +720,49 @@ class VkParam(object):
return VkParam(type_info, const=const, pointer=pointer, name=name, array_len=array_len, dyn_array_len=dyn_array_len)
+ def _set_format_string(self):
+ """ Internal helper function to be used by constructor to set format string. """
+
+ # Determine a format string used by code generation for traces.
+ # 64-bit types need a conversion function.
+ self.format_conv = None
+ if self.is_static_array() or self.is_pointer():
+ self.format_str = "%p"
+ else:
+ if self.type_info["category"] == "bitmask":
+ self.format_str = "%#x"
+ elif self.type_info["category"] == "enum":
+ self.format_str = "%d"
+ elif self.is_handle():
+ # We use uint64_t for non-dispatchable handles as opposed to pointers
+ # for dispatchable handles.
+ if self.handle.is_dispatchable():
+ self.format_str = "%p"
+ else:
+ self.format_str = "0x%s"
+ self.format_conv = "wine_dbgstr_longlong({0})"
+ elif self.type == "float":
+ self.format_str = "%f"
+ elif self.type == "int":
+ self.format_str = "%d"
+ elif self.type == "int32_t":
+ self.format_str = "%d"
+ elif self.type == "size_t":
+ self.format_str = "0x%s"
+ self.format_conv = "wine_dbgstr_longlong({0})"
+ elif self.type in ["uint32_t", "VkBool32"]:
+ self.format_str = "%u"
+ elif self.type in ["uint64_t", "VkDeviceSize"]:
+ self.format_str = "0x%s"
+ self.format_conv = "wine_dbgstr_longlong({0})"
+ elif self.type == "HANDLE":
+ self.format_str = "%p"
+ elif self.type in ["VisualID", "xcb_visualid_t", "RROutput"]:
+ # Don't care about Linux specific types.
+ self.format_str = ""
+ else:
+ LOGGER.warn("Unhandled type: {0}".format(self.type_info))
+
def definition(self, postfix=None):
""" Return prototype for the parameter. E.g. 'const char *foo' """
@@ -687,6 +787,17 @@ class VkParam(object):
return proto
+ def direction(self):
+ """ Returns parameter direction: input, output, input_output.
+
+ Parameter direction in Vulkan is not straight-forward, which this function determines.
+ """
+
+ return self._direction
+
+ def format_string(self):
+ return self.format_str
+
def is_const(self):
return self.const is not None
@@ -854,6 +965,75 @@ class VkGenerator(object):
def __init__(self, registry):
self.registry = registry
+ def generate_thunks_c(self, f, prefix):
+ f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
+
+ f.write("#include \"config.h\"\n")
+ f.write("#include \"wine/port.h\"\n\n")
+
+ f.write("#include \"wine/debug.h\"\n")
+ f.write("#include \"wine/vulkan.h\"\n")
+ f.write("#include \"wine/vulkan_driver.h\"\n")
+ f.write("#include \"vulkan_private.h\"\n\n")
+
+ f.write("WINE_DEFAULT_DEBUG_CHANNEL(vulkan);\n\n")
+
+ # Create thunks for instance functions.
+ # Global functions don't go through the thunks.
+ for vk_func in self.registry.funcs.values():
+ if not vk_func.is_required():
+ continue
+
+ if vk_func.is_global_func():
+ continue
+
+ # We don't support device functions yet as other plumbing
+ # is needed first.
+ if vk_func.is_device_func():
+ continue
+
+ if not vk_func.needs_thunk():
+ continue
+
+ f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI"))
+
+ 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():
+ continue
+
+ if not vk_func.needs_dispatch():
+ LOGGER.debug("skipping {0} in instance dispatch table".format(vk_func.name))
+ continue
+
+ f.write(" {{\"{0}\", &{1}{0}}},\n".format(vk_func.name, prefix))
+ 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")
+ f.write(" for (i = 0; i < ARRAY_SIZE(vk_instance_dispatch_table); i++)\n")
+ f.write(" {\n")
+ f.write(" if (strcmp(vk_instance_dispatch_table[i].name, name) == 0)\n")
+ f.write(" {\n")
+ f.write(" TRACE(\"Found pName=%s in instance table\\n\", name);\n")
+ f.write(" return vk_instance_dispatch_table[i].func;\n")
+ f.write(" }\n")
+ f.write(" }\n")
+ f.write(" return NULL;\n")
+ f.write("}\n")
+
+ def generate_thunks_h(self, f, prefix):
+ f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
+
+ f.write("#ifndef __WINE_VULKAN_THUNKS_H\n")
+ f.write("#define __WINE_VULKAN_THUNKS_H\n\n")
+
+ f.write("/* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */\n")
+ f.write("void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;\n\n")
+
+ f.write("#endif /* __WINE_VULKAN_THUNKS_H */\n")
+
def generate_vulkan_h(self, f):
f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
f.write("#ifndef __WINE_VULKAN_H\n")
@@ -1245,5 +1425,11 @@ def main():
with open(WINE_VULKAN_DRIVER_H, "w") as f:
generator.generate_vulkan_driver_h(f)
+ with open(WINE_VULKAN_THUNKS_H, "w") as f:
+ generator.generate_thunks_h(f, "wine_")
+
+ with open(WINE_VULKAN_THUNKS_C, "w") as f:
+ generator.generate_thunks_c(f, "wine_")
+
if __name__ == "__main__":
main()
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index 2152cb15fefe..9d2cdd2fa483 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -38,16 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
*/
#define WINE_VULKAN_ICD_VERSION 4
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
-#endif
-
-struct vulkan_func
-{
- const char *name;
- void *func;
-};
-
static void *wine_vk_get_global_proc_addr(const char *name);
static const struct vulkan_funcs *vk_funcs = NULL;
@@ -148,6 +138,9 @@ static PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance,
return NULL;
}
+ func = wine_vk_get_instance_proc_addr(name);
+ if (func) return func;
+
FIXME("Unsupported device or instance function: '%s'\n", debugstr_a(name));
return NULL;
}
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h
index 6b83e875a299..56881378332f 100644
--- a/dlls/winevulkan/vulkan_private.h
+++ b/dlls/winevulkan/vulkan_private.h
@@ -20,9 +20,21 @@
#ifndef __WINE_VULKAN_PRIVATE_H
#define __WINE_VULKAN_PRIVATE_H
+#include "vulkan_thunks.h"
+
/* Magic value defined by Vulkan ICD / Loader spec */
#define VULKAN_ICD_MAGIC_VALUE 0x01CDC0DE
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+#endif
+
+struct vulkan_func
+{
+ const char *name;
+ void *func;
+};
+
/* Base 'class' for our Vulkan dispatchable objects such as VkDevice and VkInstance.
* This structure MUST be the first element of a dispatchable object as the ICD
* loader depends on it. For now only contains loader_magic, but over time more common
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c
new file mode 100644
index 000000000000..57d4f3549b25
--- /dev/null
+++ b/dlls/winevulkan/vulkan_thunks.c
@@ -0,0 +1,106 @@
+/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "wine/debug.h"
+#include "wine/vulkan.h"
+#include "wine/vulkan_driver.h"
+#include "vulkan_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+
+static VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
+{
+ FIXME("stub: %p, %p, %p, %p\n", physicalDevice, pCreateInfo, pAllocator, pDevice);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+static void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator)
+{
+ FIXME("stub: %p, %p\n", instance, pAllocator);
+}
+
+static VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties)
+{
+ FIXME("stub: %p, %p, %p, %p\n", physicalDevice, pLayerName, pPropertyCount, pProperties);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+static VkResult WINAPI wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties)
+{
+ FIXME("stub: %p, %p, %p\n", physicalDevice, pPropertyCount, pProperties);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+static VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices)
+{
+ FIXME("stub: %p, %p, %p\n", instance, pPhysicalDeviceCount, pPhysicalDevices);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+static void WINAPI wine_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures)
+{
+ FIXME("stub: %p, %p\n", physicalDevice, pFeatures);
+}
+
+static void WINAPI wine_vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties)
+{
+ FIXME("stub: %p, %d, %p\n", physicalDevice, format, pFormatProperties);
+}
+
+static VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties *pImageFormatProperties)
+{
+ FIXME("stub: %p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+}
+
+static void WINAPI wine_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties)
+{
+ FIXME("stub: %p, %p\n", physicalDevice, pMemoryProperties);
+}
+
+static void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties)
+{
+ FIXME("stub: %p, %p\n", physicalDevice, pProperties);
+}
+
+static void WINAPI wine_vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties)
+{
+ FIXME("stub: %p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+static void WINAPI wine_vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties)
+{
+ FIXME("stub: %p, %d, %d, %d, %#x, %d, %p, %p\n", physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
+}
+
+static const struct vulkan_func vk_instance_dispatch_table[] =
+{
+ {"vkCreateDevice", &wine_vkCreateDevice},
+ {"vkDestroyInstance", &wine_vkDestroyInstance},
+ {"vkEnumerateDeviceExtensionProperties", &wine_vkEnumerateDeviceExtensionProperties},
+ {"vkEnumerateDeviceLayerProperties", &wine_vkEnumerateDeviceLayerProperties},
+ {"vkEnumeratePhysicalDevices", &wine_vkEnumeratePhysicalDevices},
+ {"vkGetPhysicalDeviceFeatures", &wine_vkGetPhysicalDeviceFeatures},
+ {"vkGetPhysicalDeviceFormatProperties", &wine_vkGetPhysicalDeviceFormatProperties},
+ {"vkGetPhysicalDeviceImageFormatProperties", &wine_vkGetPhysicalDeviceImageFormatProperties},
+ {"vkGetPhysicalDeviceMemoryProperties", &wine_vkGetPhysicalDeviceMemoryProperties},
+ {"vkGetPhysicalDeviceProperties", &wine_vkGetPhysicalDeviceProperties},
+ {"vkGetPhysicalDeviceQueueFamilyProperties", &wine_vkGetPhysicalDeviceQueueFamilyProperties},
+ {"vkGetPhysicalDeviceSparseImageFormatProperties", &wine_vkGetPhysicalDeviceSparseImageFormatProperties},
+};
+
+void *wine_vk_get_instance_proc_addr(const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(vk_instance_dispatch_table); i++)
+ {
+ if (strcmp(vk_instance_dispatch_table[i].name, name) == 0)
+ {
+ TRACE("Found pName=%s in instance table\n", name);
+ return vk_instance_dispatch_table[i].func;
+ }
+ }
+ return NULL;
+}
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h
new file mode 100644
index 000000000000..dbfd83c1156d
--- /dev/null
+++ b/dlls/winevulkan/vulkan_thunks.h
@@ -0,0 +1,9 @@
+/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */
+
+#ifndef __WINE_VULKAN_THUNKS_H
+#define __WINE_VULKAN_THUNKS_H
+
+/* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */
+void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
+
+#endif /* __WINE_VULKAN_THUNKS_H */
--
2.16.1
More information about the wine-devel
mailing list