Hi all,
This patch series introduces more changes, which will allow us to hit our first milestone as vulkaninfo.exe now functions.
The first patch introduces some awful code structure conversion code, which Vulkan requires. Vulkan loves to pass structures to functions, but for many the alignment differs between 32-bit Windows and Linux and thus require conversion. The script understands which structures need to be converted. It is quite complex as sometimes it are even child structures which need conversion and sometimes structures are arrays (static or dynamic).
The last four patches of the series are fairly straightforward.
Thanks, Roderick
Roderick Colenbrander (5): winevulkan: Implement physical device core functions. winevulkan: Load device functions from vkGetInstanceProcAddr. winevulkan: Implement vkCreateDevice. winevulkan: Implement vkGetDeviceProcAddr. winevulkan: Implement vkDestroyDevice.
dlls/winevulkan/make_vulkan | 805 ++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan.c | 104 ++++ dlls/winevulkan/vulkan_private.h | 8 + dlls/winevulkan/vulkan_thunks.c | 996 ++++++++++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_thunks.h | 415 ++++++++++++++++ dlls/winex11.drv/vulkan.c | 9 + include/wine/vulkan_driver.h | 3 +- 7 files changed, 2319 insertions(+), 21 deletions(-)
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com --- dlls/winevulkan/make_vulkan | 734 +++++++++++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_thunks.c | 220 +++++++++++- dlls/winevulkan/vulkan_thunks.h | 164 +++++++++ 3 files changed, 1105 insertions(+), 13 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 7499cf7011..2aec101723 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -68,7 +68,6 @@ 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. # DRIVER_VERSION should be bumped on any change to driver interface # in FUNCTION_OVERRIDES @@ -95,6 +94,13 @@ FUNCTION_OVERRIDES = { }
+class Direction(Enum): + """ Parameter direction: input, output, input_output. """ + INPUT = 1 + OUTPUT = 2 + INPUT_OUTPUT = 3 + + class VkBaseType(object): def __init__(self, name, _type, requires=None): """ Vulkan base type class. @@ -285,6 +291,21 @@ class VkFunction(object):
return VkFunction(_type=func_type, name=func_name, params=params)
+ def get_conversions(self): + """ Get a list of conversion functions required for this function if any. + Parameters which are structures may require conversion between win32 + and the host platform. This function returns a list of conversions + required. + """ + + conversions = [] + for param in self.params: + convs = param.get_conversions() + if convs is not None: + conversions.extend(convs) + + return conversions + 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() @@ -312,9 +333,32 @@ class VkFunction(object): def is_required(self): return self.required
+ def needs_conversion(self): + """ Check if the function needs any input/output type conversion. + Funcsions need input/output conversion if struct parameters have + alignment differences between Win32 and Linux 32-bit. + """ + + for p in self.params: + if p.needs_conversion(): + LOGGER.debug("Parameter {0} to {1} requires conversion".format(p.name, self.name)) + return True + + return False + def needs_dispatch(self): return self.dispatch
+ def needs_stub(self): + """ Temporary function to limit script hacks until more code is implemented. """ + if self.name == "vkCreateDevice": + return True + + if self.params[0].type != "VkPhysicalDevice": + return True + + return False + def needs_thunk(self): return self.thunk_needed
@@ -374,6 +418,77 @@ class VkFunction(object):
return proto
+ def body(self): + body = " {0}".format(self.trace()) + + params = ", ".join([p.variable(conv=False) for p in self.params]) + + # Call the native Vulkan function. + if self.type == "void": + body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + else: + body += " return {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + + return body + + def body_conversion(self): + body = "" + + # Declare a variable to hold the result for non-void functions. + if self.type != "void": + body += " {0} result;\n".format(self.type) + + # Declare any tmp parameters for conversion. + for p in self.params: + if not p.needs_conversion(): + continue + + if p.is_dynamic_array(): + body += " {0}_host *{1}_host;\n".format(p.type, p.name) + else: + body += " {0}_host {1}_host;\n".format(p.type, p.name) + + body += " {0}\n".format(self.trace()) + + # Call any win_to_host conversion calls. + for p in self.params: + if not p.needs_input_conversion(): + continue + + body += p.copy(Direction.INPUT) + + # Build list of parameters containing converted and non-converted parameters. + # The param itself knows if conversion is needed and applies it when we set conv=True. + params = ", ".join([p.variable(conv=True) for p in self.params]) + + # Call the native Vulkan function. + if self.type == "void": + body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + else: + body += " result = {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params) + + body += "\n" + + # Call any host_to_win conversion calls. + for p in self.params: + if not p.needs_output_conversion(): + continue + + body += p.copy(Direction.OUTPUT) + + # Perform any required cleanups. Most of these are for array functions. + for p in self.params: + if not p.needs_free(): + continue + + body += p.free() + + # Finally return the result. + if self.type != "void": + body += " return result;\n" + + return body + def stub(self, call_conv=None, prefix=None): stub = self.prototype(call_conv=call_conv, prefix=prefix) stub += "\n{\n" @@ -387,6 +502,22 @@ class VkFunction(object): stub += "}\n\n" return stub
+ def thunk(self, call_conv=None, prefix=None): + thunk = self.prototype(call_conv=call_conv, prefix=prefix) + thunk += "\n{\n" + + if self.needs_conversion(): + thunk += "#if defined(USE_STRUCT_CONVERSION)\n" + thunk += self.body_conversion() + thunk += "#else\n" + thunk += self.body() + thunk += "#endif\n" + else: + thunk += self.body() + + thunk += "}\n\n" + return thunk + def trace(self, message=None, trace_func=None): """ Create a trace string including all parameters.
@@ -492,6 +623,23 @@ class VkHandle(object): parent = handle.attrib.get("parent") # Most objects have a parent e.g. VkQueue has VkDevice. return VkHandle(name, _type, parent)
+ def dispatch_table(self): + if not self.is_dispatchable(): + return None + + if self.parent is None: + # Should only happen for VkInstance + return "funcs" + elif self.name == "VkDevice": + # VkDevice has VkInstance as a parent, but has its own dispatch table. + return "funcs" + elif self.parent in ["VkInstance", "VkPhysicalDevice"]: + return "instance->funcs" + elif self.parent in ["VkDevice", "VkCommandPool"]: + return "device->funcs" + else: + LOGGER.error("Unhandled dispatchable parent: {0}".format(self.parent)) + def definition(self): """ Generates handle definition e.g. VK_DEFINE_HANDLE(vkInstance) """ return "{0}({1})\n".format(self.type, self.name) @@ -502,6 +650,28 @@ class VkHandle(object): """ return self.type == "VK_DEFINE_HANDLE"
+ def native_handle(self): + """ Provide access to the native handle of a dispatchable object. + + Dispatchable objects wrap an underlaying 'native' object. + This method provides access to the native object. + """ + if not self.is_dispatchable(): + return None + + if self.name == "VkCommandBuffer": + return "command_buffer" + elif self.name == "VkDevice": + return "device" + elif self.name == "VkInstance": + return "instance" + elif self.name == "VkPhysicalDevice": + return "phys_dev" + elif self.name == "VkQueue": + return "queue" + else: + LOGGER.error("Unhandled native handle for: {0}".format(self.name)) +
class VkMember(object): def __init__(self, const=None, _type=None, pointer=None, name=None, array_len=None, dyn_array_len=None, optional=False, @@ -582,6 +752,36 @@ class VkMember(object): return VkMember(const=const, _type=member_type, pointer=pointer, name=name_elem.text, array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, extension_structs=extension_structs)
+ def copy(self, input, output, direction): + """ Helper method for use by conversion logic to generate a C-code statement to copy this member. """ + + if self.needs_conversion(): + if self.is_dynamic_array(): + if direction == Direction.OUTPUT: + LOGGER.warn("TODO: implement copying of returnedonly dynamic array for {0}.{1}".format(self.type, self.name)) + else: + # Array length is either a variable name (string) or an int. + count = self.dyn_array_len if isinstance(self.dyn_array_len, int) else "{0}{1}".format(input, self.dyn_array_len) + return "{0}{1} = convert_{2}_array_win_to_host({3}{1}, {4});\n".format(output, self.name, self.type, input, count) + elif self.is_static_array(): + count = self.array_len + if direction == Direction.OUTPUT: + # Needed by VkMemoryHeap.memoryHeaps + return "convert_{0}_static_array_host_to_win({2}{1}, {3}{1}, {4});\n".format(self.type, self.name, input, output, count) + else: + # Nothing needed this yet. + LOGGER.warn("TODO: implement copying of static array for {0}.{1}".format(self.type, self.name)) + else: + if direction == Direction.OUTPUT: + return "convert_{0}_host_to_win(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output) + else: + return "convert_{0}_win_to_host(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output) + elif self.is_static_array(): + bytes_count = "{0} * sizeof({1})".format(self.array_len, self.type) + return "memcpy({0}{1}, {2}{1}, {3});\n".format(output, self.name, input, bytes_count) + else: + return "{0}{1} = {2}{1};\n".format(output, self.name, input) + def definition(self, align=False, conv=False): """ Generate prototype for given function.
@@ -612,6 +812,36 @@ class VkMember(object):
return text
+ def get_conversions(self): + """ Return any conversion description for this member and its children when conversion is needed. """ + + # Check if we need conversion either for this member itself or for any child members + # in case member represents a struct. + if not self.needs_conversion(): + return None + + conversions = [] + + # Collect any conversion for any member structs. + struct = self.type_info["data"] + for m in struct: + if m.needs_conversion(): + conversions.extend(m.get_conversions()) + + struct = self.type_info["data"] + direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT + if self.is_dynamic_array(): + conversions.append(ConversionFunction(False, True, direction, struct)) + elif self.is_static_array(): + conversions.append(ConversionFunction(True, False, direction, struct)) + else: + conversions.append(ConversionFunction(False, False, direction, struct)) + + if self.needs_free(): + conversions.append(FreeFunction(self.is_dynamic_array(), struct)) + + return conversions + def is_const(self): return self.const is not None
@@ -663,6 +893,26 @@ class VkMember(object): return False if handle.is_dispatchable() else True return False
+ def needs_conversion(self): + """ Structures requiring alignment, need conversion between win32 and host. """ + + if not self.is_struct(): + return False + + struct = self.type_info["data"] + return struct.needs_conversion() + + def needs_free(self): + if not self.needs_conversion(): + return False + + if self.is_dynamic_array(): + return True + + # TODO: some non-pointer structs and optional pointer structs may need freeing, + # though none of this type have been encountered yet. + return False + def set_type_info(self, type_info): """ Helper function to set type information from the type registry. This is needed, because not all type data is available at time of @@ -685,7 +935,9 @@ 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_direction() self._set_format_string() + self._set_conversions()
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) @@ -722,6 +974,59 @@ 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_conversions(self): + """ Internal helper function to configure any needed conversion functions. """ + + self.free_func = None + self.input_conv = None + self.output_conv = None + if not self.needs_conversion(): + return + + # Input functions require win to host conversion. + if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]: + self.input_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.INPUT, self.struct) + + # Output functions require host to win conversion. + if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]: + self.output_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.OUTPUT, self.struct) + + # Dynamic arrays, but also some normal structs (e.g. VkCommandBufferBeginInfo) need memory + # allocation and thus some cleanup. + if self.is_dynamic_array() or self.struct.needs_free(): + self.free_func = FreeFunction(self.is_dynamic_array(), self.struct) + + def _set_direction(self): + """ Internal helper function to set parameter direction (input/output/input_output). """ + + # The parameter direction needs to be determined from hints in vk.xml like returnedonly, + # parameter constness and other heuristics. + # For now we need to get this right for structures as we need to convert these, we may have + # missed a few other edge cases (e.g. count variables). + # See also https://github.com/KhronosGroup/Vulkan-Docs/issues/610 + + if not self.is_pointer(): + self._direction = Direction.INPUT + elif self.is_const() and self.is_pointer(): + self._direction = Direction.INPUT + elif self.is_struct(): + if not self.struct.returnedonly: + self._direction = Direction.INPUT + return + + # Returnedonly hints towards output, however in some cases + # it is inputoutput. In particular if pNext / sType exist, + # which are used to link in other structures without having + # to introduce new APIs. E.g. vkGetPhysicalDeviceProperties2KHR. + if "pNext" in self.struct: + self._direction = Direction.INPUT_OUTPUT + return + + self._direction = Direction.OUTPUT + else: + # This should mostly be right. Count variables can be inout, but we don't care about these yet. + self._direction = Direction.OUTPUT + def _set_format_string(self): """ Internal helper function to be used by constructor to set format string. """
@@ -765,6 +1070,18 @@ class VkParam(object): else: LOGGER.warn("Unhandled type: {0}".format(self.type_info))
+ def copy(self, direction): + if direction == Direction.INPUT: + if self.is_dynamic_array(): + return " {0}_host = convert_{1}_array_win_to_host({0}, {2});\n".format(self.name, self.type, self.dyn_array_len) + else: + return " convert_{0}_win_to_host({1}, &{1}_host);\n".format(self.type, self.name) + else: + if self.is_dynamic_array(): + LOGGER.error("Unimplemented output conversion for: {0}".format(self.name)) + else: + return " convert_{0}_host_to_win(&{1}_host, {1});\n".format(self.type, self.name) + def definition(self, postfix=None): """ Return prototype for the parameter. E.g. 'const char *foo' """
@@ -800,6 +1117,68 @@ class VkParam(object): def format_string(self): return self.format_str
+ def dispatch_table(self): + """ Return functions dispatch table pointer for dispatchable objects. """ + + if not self.is_dispatchable(): + return None + + return "{0}->{1}".format(self.name, self.handle.dispatch_table()) + + def format_string(self): + return self.format_str + + def free(self): + if self.is_dynamic_array(): + if self.struct.returnedonly: + # For returnedonly, counts is stored in a pointer. + return " free_{0}_array({1}_host, *{2});\n".format(self.type, self.name, self.dyn_array_len) + else: + return " free_{0}_array({1}_host, {2});\n".format(self.type, self.name, self.dyn_array_len) + else: + # We are operating on a single structure. Some structs (very rare) contain dynamic members, + # which would need freeing. + if self.struct.needs_free(): + return " free_{0}(&{1}_host);\n".format(self.type, self.name) + return "" + + def get_conversions(self): + """ Get a list of conversions required for this parameter if any. + Parameters which are structures may require conversion between win32 + and the host platform. This function returns a list of conversions + required. + """ + + if not self.is_struct(): + return None + + if not self.needs_conversion(): + return None + + conversions = [] + + # Collect any member conversions first, so we can guarantee + # those functions will be defined prior to usage by the + # 'parent' param requiring conversion. + for m in self.struct: + if not m.is_struct(): + continue + + if not m.needs_conversion(): + continue + + conversions.extend(m.get_conversions()) + + # Conversion requirements for the 'parent' parameter. + if self.input_conv is not None: + conversions.append(self.input_conv) + if self.output_conv is not None: + conversions.append(self.output_conv) + if self.free_func is not None: + conversions.append(self.free_func) + + return conversions + def is_const(self): return self.const is not None
@@ -824,6 +1203,62 @@ class VkParam(object): def is_struct(self): return self.struct is not None
+ def needs_conversion(self): + """ Returns if parameter needs conversion between win32 and host. """ + + if not self.is_struct(): + return False + + # VkSparseImageMemoryRequirements is used by vkGetImageSparseMemoryRequirements. + # This function is tricky to wrap, because how to wrap depends on whether + # pSparseMemoryRequirements is NULL or not. Luckily for VkSparseImageMemoryRequirements + # the alignment works out in such a way that no conversion is needed between win32 and Linux. + if self.type == "VkSparseImageMemoryRequirements": + return False + + # If a structure needs alignment changes, it means we need to + # perform parameter conversion between win32 and host. + if self.struct.needs_conversion(): + return True + + return False + + def needs_free(self): + return self.free_func is not None + + def needs_input_conversion(self): + return self.input_conv is not None + + def needs_output_conversion(self): + return self.output_conv is not None + + def variable(self, conv=False): + """ Returns 'glue' code during generation of a function call on how to access the variable. + This function handles various scenarios such as 'unwrapping' if dispatchable objects and + renaming of parameters in case of win32 -> host conversion. + + Args: + conv (bool, optional): Enable conversion if the param needs it. This appends '_host' to the name. + """ + + # Hack until we enable allocation callbacks from ICD to application. These are a joy + # to enable one day, because of calling convention conversion. + if "VkAllocationCallbacks" in self.type: + LOGGER.debug("HACK: setting NULL VkAllocationCallbacks for {0}".format(self.name)) + return "NULL" + + # Dispatchable objects wrap the native handle. For thunk generation we + # need to pass the native handle to the native vulkan calls. + if self.is_dispatchable(): + return "{0}->{1}".format(self.name, self.handle.native_handle()) + elif conv and self.needs_conversion(): + if self.is_dynamic_array(): + return "{0}_host".format(self.name) + else: + return "&{0}_host".format(self.name) + else: + return self.name +
class VkStruct(Sequence): """ Class which represents the type union and struct. """ @@ -953,6 +1388,31 @@ class VkStruct(Sequence): return True return False
+ def needs_conversion(self): + """ Returns if struct members needs conversion between win32 and host. + Structures need conversion if they contain members requiring alignment + or if they include other structures which need alignment. + """ + + if self.needs_alignment(): + return True + + for m in self.members: + if m.needs_conversion(): + return True + return False + + def needs_free(self): + """ Check if any struct member needs some memory freeing.""" + + for m in self.members: + if m.needs_free(): + return True + + continue + + return False + def set_type_info(self, types): """ Helper function to set type information from the type registry. This is needed, because not all type data is available at time of @@ -963,10 +1423,251 @@ class VkStruct(Sequence): m.set_type_info(type_info)
+class ConversionFunction(object): + def __init__(self, array, dyn_array, direction, struct): + self.array = array + self.direction = direction + self.dyn_array = dyn_array + self.struct = struct + self.type = struct.name + + self._set_name() + + def __eq__(self, other): + if self.name != other.name: + return False + + return True + + def _generate_array_conversion_func(self): + """ Helper function for generating a conversion function for array structs. """ + + if self.direction == Direction.OUTPUT: + params = ["const {0}_host *in".format(self.type), "uint32_t count"] + return_type = self.type + else: + params = ["const {0} *in".format(self.type), "uint32_t count"] + return_type = "{0}_host".format(self.type) + + # Generate function prototype. + body = "static inline {0} * {1}(".format(return_type, self.name) + body += ", ".join(p for p in params) + body += ")\n{\n" + + body += " {0} *out;\n".format(return_type) + body += " unsigned int i;\n\n" + body += " if (!in) return NULL;\n\n" + + body += " out = ({0} *)heap_alloc(count * sizeof(*out));\n".format(return_type) + + body += " for (i = 0; i < count; i++)\n" + body += " {\n" + + for m in self.struct: + # TODO: support copying of pNext extension structures! + # Luckily though no extension struct at this point needs conversion. + body += " " + m.copy("in[i].", "out[i].", self.direction) + + body += " }\n\n" + body += " return out;\n" + body += "}\n\n" + return body + + def _generate_conversion_func(self): + """ Helper function for generating a conversion function for non-array structs. """ + + if self.direction == Direction.OUTPUT: + params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type)] + else: + params = ["const {0} *in".format(self.type), "{0}_host *out".format(self.type)] + + body = "static inline void {0}(".format(self.name) + + # Generate parameter list + body += ", ".join(p for p in params) + body += ")\n{\n" + + body += " if (!in) return;\n\n" + + if self.direction == Direction.INPUT and "pNext" in self.struct and self.struct.returnedonly: + # We are dealing with an input_output parameter. For these we only need to copy + # pNext and sType as the other fields are filled in by the host. We do potentially + # have to iterate over pNext and perform conversions based on switch(sType)! + # Luckily though no extension structs at this point need conversion. + # TODO: support copying of pNext extension structures! + body += " out->pNext = in->pNext;\n" + body += " out->sType = in->sType;\n" + else: + for m in self.struct: + # TODO: support copying of pNext extension structures! + body += " " + m.copy("in->", "out->", self.direction) + + body += "}\n\n" + return body + + def _generate_static_array_conversion_func(self): + """ Helper function for generating a conversion function for array structs. """ + + if self.direction == Direction.OUTPUT: + params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type), "uint32_t count"] + return_type = self.type + else: + params = ["const {0} *in".format(self.type), "{0} *out_host".format(self.type), "uint32_t count"] + return_type = "{0}_host".format(self.type) + + # Generate function prototype. + body = "static inline void {0}(".format(self.name) + body += ", ".join(p for p in params) + body += ")\n{\n" + body += " unsigned int i;\n\n" + body += " if (!in) return;\n\n" + body += " for (i = 0; i < count; i++)\n" + body += " {\n" + + for m in self.struct: + # TODO: support copying of pNext extension structures! + body += " " + m.copy("in[i].", "out[i].", self.direction) + + body += " }\n" + body += "}\n\n" + return body + + def _set_name(self): + if self.direction == Direction.INPUT: + if self.array: + name = "convert_{0}_static_array_win_to_host".format(self.type) + elif self.dyn_array: + name = "convert_{0}_array_win_to_host".format(self.type) + else: + name = "convert_{0}_win_to_host".format(self.type) + else: # Direction.OUTPUT + if self.array: + name = "convert_{0}_static_array_host_to_win".format(self.type) + elif self.dyn_array: + name = "convert_{0}_array_host_to_win".format(self.type) + else: + name = "convert_{0}_host_to_win".format(self.type) + + self.name = name + + def definition(self): + if self.array: + return self._generate_static_array_conversion_func() + elif self.dyn_array: + return self._generate_array_conversion_func() + else: + return self._generate_conversion_func() + + +class FreeFunction(object): + def __init__(self, dyn_array, struct): + self.dyn_array = dyn_array + self.struct = struct + self.type = struct.name + + if dyn_array: + self.name = "free_{0}_array".format(self.type) + else: + self.name = "free_{0}".format(self.type) + + def __eq__(self, other): + if self.name == other.name: + return True + + return False + + def _generate_array_free_func(self): + """ Helper function for cleaning up temporary buffers required for array conversions. """ + + # Generate function prototype. + body = "static inline void {0}({1}_host *in, uint32_t count)\n{{\n".format(self.name, self.type) + + # E.g. VkGraphicsPipelineCreateInfo_host needs freeing for pStages. + if self.struct.needs_free(): + body += " unsigned int i;\n\n" + body += " if (!in) return;\n\n" + body += " for (i = 0; i < count; i++)\n" + body += " {\n" + + for m in self.struct: + if m.needs_conversion() and m.is_dynamic_array(): + if m.is_const(): + # Add a cast to ignore const on conversion structs we allocated ourselves. + body += " free_{0}_array(({0}_host *)in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len) + else: + body += " free_{0}_array(in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len) + elif m.needs_conversion(): + LOGGER.error("Unhandled conversion for {0}".format(m.name)) + body += " }\n" + else: + body += " if (!in) return;\n\n" + + body += " heap_free(in);\n" + + body += "}\n\n" + return body + + def _generate_free_func(self): + # E.g. VkCommandBufferBeginInfo.pInheritanceInfo needs freeing. + if not self.struct.needs_free(): + return "" + + # Generate function prototype. + body = "static inline void {0}({1}_host *in)\n{{\n".format(self.name, self.type) + + for m in self.struct: + if m.needs_conversion() and m.is_dynamic_array(): + count = m.dyn_array_len if isinstance(m.dyn_array_len, int) else "in->{0}".format(m.dyn_array_len) + if m.is_const(): + # Add a cast to ignore const on conversion structs we allocated ourselves. + body += " free_{0}_array(({0}_host *)in->{1}, {2});\n".format(m.type, m.name, count) + else: + body += " free_{0}_array(in->{1}, {2});\n".format(m.type, m.name, count) + + body += "}\n\n" + return body + + def definition(self): + if self.dyn_array: + return self._generate_array_free_func() + else: + # Some structures need freeing too if they contain dynamic arrays. + # E.g. VkCommandBufferBeginInfo + return self._generate_free_func() + + class VkGenerator(object): def __init__(self, registry): self.registry = registry
+ # Build a list conversion functions for struct conversion. + self.conversions = [] + self.host_structs = [] + for func in self.registry.funcs.values(): + if not func.is_required(): + continue + + # Temporary filter. + if func.needs_stub(): + continue + + if not func.needs_conversion(): + continue + + conversions = func.get_conversions() + for conv in conversions: + # Pull in any conversions for vulkan_thunks.c. Driver conversions we + # handle manually in vulkan.c if needed. + if not func.is_driver_func(): + # Append if we don't already have this conversion. + if not any(c == conv for c in self.conversions): + self.conversions.append(conv) + + # Structs can be used in different ways by different conversions + # e.g. array vs non-array. Just make sure we pull in each struct once. + if not any(s.name == conv.struct.name for s in self.host_structs): + self.host_structs.append(conv.struct) + def generate_thunks_c(self, f, prefix): f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
@@ -974,12 +1675,19 @@ class VkGenerator(object): f.write("#include "wine/port.h"\n\n")
f.write("#include "wine/debug.h"\n") + f.write("#include "wine/heap.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")
+ # Generate any conversion helper functions. + f.write("#if defined(USE_STRUCT_CONVERSION)\n") + for conv in self.conversions: + f.write(conv.definition()) + f.write("#endif /* USE_STRUCT_CONVERSION */\n\n") + # Create thunks for instance functions. # Global functions don't go through the thunks. for vk_func in self.registry.funcs.values(): @@ -997,7 +1705,11 @@ class VkGenerator(object): if not vk_func.needs_thunk(): continue
- f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI")) + # Temporary filter. + if vk_func.needs_stub(): + f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI")) + else: + f.write("static " + vk_func.thunk(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: @@ -1031,6 +1743,11 @@ class VkGenerator(object): f.write("#ifndef __WINE_VULKAN_THUNKS_H\n") f.write("#define __WINE_VULKAN_THUNKS_H\n\n")
+ f.write("/* Perform vulkan struct conversion on 32-bit platforms. */\n") + f.write("#if (defined(__i386__) || defined(__arm__))\n") + f.write(" #define USE_STRUCT_CONVERSION\n") + f.write("#endif\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")
@@ -1043,6 +1760,10 @@ class VkGenerator(object): f.write("{0};\n".format(vk_func.prototype("WINAPI", prefix="wine_", postfix="DECLSPEC_HIDDEN"))) f.write("\n")
+ for struct in self.host_structs: + f.write(struct.definition(align=False, conv=True, postfix="_host")) + f.write("\n") + 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: @@ -1053,7 +1774,14 @@ class VkGenerator(object): LOGGER.debug("skipping {0} in vulkan_instance_funcs".format(vk_func.name)) continue
- f.write(" {0};\n".format(vk_func.pfn(conv=False))) + if vk_func.needs_conversion(): + f.write("#if defined(USE_STRUCT_CONVERSION)\n") + f.write(" {0};\n".format(vk_func.pfn(conv=True))) + f.write("#else\n") + f.write(" {0};\n".format(vk_func.pfn(conv=False))) + f.write("#endif\n") + else: + f.write(" {0};\n".format(vk_func.pfn(conv=False))) f.write("};\n\n")
f.write("#define ALL_VK_INSTANCE_FUNCS() \\n") diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 2e1b62d23c..daab898522 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -4,12 +4,177 @@ #include "wine/port.h"
#include "wine/debug.h" +#include "wine/heap.h" #include "wine/vulkan.h" #include "wine/vulkan_driver.h" #include "vulkan_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkImageFormatProperties_host_to_win(const VkImageFormatProperties_host *in, VkImageFormatProperties *out) +{ + if (!in) return; + + out->maxExtent = in->maxExtent; + out->maxMipLevels = in->maxMipLevels; + out->maxArrayLayers = in->maxArrayLayers; + out->sampleCounts = in->sampleCounts; + out->maxResourceSize = in->maxResourceSize; +} + +static inline void convert_VkMemoryHeap_static_array_host_to_win(const VkMemoryHeap_host *in, VkMemoryHeap *out, uint32_t count) +{ + unsigned int i; + + if (!in) return; + + for (i = 0; i < count; i++) + { + out[i].size = in[i].size; + out[i].flags = in[i].flags; + } +} + +static inline void convert_VkPhysicalDeviceMemoryProperties_host_to_win(const VkPhysicalDeviceMemoryProperties_host *in, VkPhysicalDeviceMemoryProperties *out) +{ + if (!in) return; + + out->memoryTypeCount = in->memoryTypeCount; + memcpy(out->memoryTypes, in->memoryTypes, VK_MAX_MEMORY_TYPES * sizeof(VkMemoryType)); + out->memoryHeapCount = in->memoryHeapCount; + convert_VkMemoryHeap_static_array_host_to_win(in->memoryHeaps, out->memoryHeaps, VK_MAX_MEMORY_HEAPS); +} + +static inline void convert_VkPhysicalDeviceLimits_host_to_win(const VkPhysicalDeviceLimits_host *in, VkPhysicalDeviceLimits *out) +{ + if (!in) return; + + out->maxImageDimension1D = in->maxImageDimension1D; + out->maxImageDimension2D = in->maxImageDimension2D; + out->maxImageDimension3D = in->maxImageDimension3D; + out->maxImageDimensionCube = in->maxImageDimensionCube; + out->maxImageArrayLayers = in->maxImageArrayLayers; + out->maxTexelBufferElements = in->maxTexelBufferElements; + out->maxUniformBufferRange = in->maxUniformBufferRange; + out->maxStorageBufferRange = in->maxStorageBufferRange; + out->maxPushConstantsSize = in->maxPushConstantsSize; + out->maxMemoryAllocationCount = in->maxMemoryAllocationCount; + out->maxSamplerAllocationCount = in->maxSamplerAllocationCount; + out->bufferImageGranularity = in->bufferImageGranularity; + out->sparseAddressSpaceSize = in->sparseAddressSpaceSize; + out->maxBoundDescriptorSets = in->maxBoundDescriptorSets; + out->maxPerStageDescriptorSamplers = in->maxPerStageDescriptorSamplers; + out->maxPerStageDescriptorUniformBuffers = in->maxPerStageDescriptorUniformBuffers; + out->maxPerStageDescriptorStorageBuffers = in->maxPerStageDescriptorStorageBuffers; + out->maxPerStageDescriptorSampledImages = in->maxPerStageDescriptorSampledImages; + out->maxPerStageDescriptorStorageImages = in->maxPerStageDescriptorStorageImages; + out->maxPerStageDescriptorInputAttachments = in->maxPerStageDescriptorInputAttachments; + out->maxPerStageResources = in->maxPerStageResources; + out->maxDescriptorSetSamplers = in->maxDescriptorSetSamplers; + out->maxDescriptorSetUniformBuffers = in->maxDescriptorSetUniformBuffers; + out->maxDescriptorSetUniformBuffersDynamic = in->maxDescriptorSetUniformBuffersDynamic; + out->maxDescriptorSetStorageBuffers = in->maxDescriptorSetStorageBuffers; + out->maxDescriptorSetStorageBuffersDynamic = in->maxDescriptorSetStorageBuffersDynamic; + out->maxDescriptorSetSampledImages = in->maxDescriptorSetSampledImages; + out->maxDescriptorSetStorageImages = in->maxDescriptorSetStorageImages; + out->maxDescriptorSetInputAttachments = in->maxDescriptorSetInputAttachments; + out->maxVertexInputAttributes = in->maxVertexInputAttributes; + out->maxVertexInputBindings = in->maxVertexInputBindings; + out->maxVertexInputAttributeOffset = in->maxVertexInputAttributeOffset; + out->maxVertexInputBindingStride = in->maxVertexInputBindingStride; + out->maxVertexOutputComponents = in->maxVertexOutputComponents; + out->maxTessellationGenerationLevel = in->maxTessellationGenerationLevel; + out->maxTessellationPatchSize = in->maxTessellationPatchSize; + out->maxTessellationControlPerVertexInputComponents = in->maxTessellationControlPerVertexInputComponents; + out->maxTessellationControlPerVertexOutputComponents = in->maxTessellationControlPerVertexOutputComponents; + out->maxTessellationControlPerPatchOutputComponents = in->maxTessellationControlPerPatchOutputComponents; + out->maxTessellationControlTotalOutputComponents = in->maxTessellationControlTotalOutputComponents; + out->maxTessellationEvaluationInputComponents = in->maxTessellationEvaluationInputComponents; + out->maxTessellationEvaluationOutputComponents = in->maxTessellationEvaluationOutputComponents; + out->maxGeometryShaderInvocations = in->maxGeometryShaderInvocations; + out->maxGeometryInputComponents = in->maxGeometryInputComponents; + out->maxGeometryOutputComponents = in->maxGeometryOutputComponents; + out->maxGeometryOutputVertices = in->maxGeometryOutputVertices; + out->maxGeometryTotalOutputComponents = in->maxGeometryTotalOutputComponents; + out->maxFragmentInputComponents = in->maxFragmentInputComponents; + out->maxFragmentOutputAttachments = in->maxFragmentOutputAttachments; + out->maxFragmentDualSrcAttachments = in->maxFragmentDualSrcAttachments; + out->maxFragmentCombinedOutputResources = in->maxFragmentCombinedOutputResources; + out->maxComputeSharedMemorySize = in->maxComputeSharedMemorySize; + memcpy(out->maxComputeWorkGroupCount, in->maxComputeWorkGroupCount, 3 * sizeof(uint32_t)); + out->maxComputeWorkGroupInvocations = in->maxComputeWorkGroupInvocations; + memcpy(out->maxComputeWorkGroupSize, in->maxComputeWorkGroupSize, 3 * sizeof(uint32_t)); + out->subPixelPrecisionBits = in->subPixelPrecisionBits; + out->subTexelPrecisionBits = in->subTexelPrecisionBits; + out->mipmapPrecisionBits = in->mipmapPrecisionBits; + out->maxDrawIndexedIndexValue = in->maxDrawIndexedIndexValue; + out->maxDrawIndirectCount = in->maxDrawIndirectCount; + out->maxSamplerLodBias = in->maxSamplerLodBias; + out->maxSamplerAnisotropy = in->maxSamplerAnisotropy; + out->maxViewports = in->maxViewports; + memcpy(out->maxViewportDimensions, in->maxViewportDimensions, 2 * sizeof(uint32_t)); + memcpy(out->viewportBoundsRange, in->viewportBoundsRange, 2 * sizeof(float)); + out->viewportSubPixelBits = in->viewportSubPixelBits; + out->minMemoryMapAlignment = in->minMemoryMapAlignment; + out->minTexelBufferOffsetAlignment = in->minTexelBufferOffsetAlignment; + out->minUniformBufferOffsetAlignment = in->minUniformBufferOffsetAlignment; + out->minStorageBufferOffsetAlignment = in->minStorageBufferOffsetAlignment; + out->minTexelOffset = in->minTexelOffset; + out->maxTexelOffset = in->maxTexelOffset; + out->minTexelGatherOffset = in->minTexelGatherOffset; + out->maxTexelGatherOffset = in->maxTexelGatherOffset; + out->minInterpolationOffset = in->minInterpolationOffset; + out->maxInterpolationOffset = in->maxInterpolationOffset; + out->subPixelInterpolationOffsetBits = in->subPixelInterpolationOffsetBits; + out->maxFramebufferWidth = in->maxFramebufferWidth; + out->maxFramebufferHeight = in->maxFramebufferHeight; + out->maxFramebufferLayers = in->maxFramebufferLayers; + out->framebufferColorSampleCounts = in->framebufferColorSampleCounts; + out->framebufferDepthSampleCounts = in->framebufferDepthSampleCounts; + out->framebufferStencilSampleCounts = in->framebufferStencilSampleCounts; + out->framebufferNoAttachmentsSampleCounts = in->framebufferNoAttachmentsSampleCounts; + out->maxColorAttachments = in->maxColorAttachments; + out->sampledImageColorSampleCounts = in->sampledImageColorSampleCounts; + out->sampledImageIntegerSampleCounts = in->sampledImageIntegerSampleCounts; + out->sampledImageDepthSampleCounts = in->sampledImageDepthSampleCounts; + out->sampledImageStencilSampleCounts = in->sampledImageStencilSampleCounts; + out->storageImageSampleCounts = in->storageImageSampleCounts; + out->maxSampleMaskWords = in->maxSampleMaskWords; + out->timestampComputeAndGraphics = in->timestampComputeAndGraphics; + out->timestampPeriod = in->timestampPeriod; + out->maxClipDistances = in->maxClipDistances; + out->maxCullDistances = in->maxCullDistances; + out->maxCombinedClipAndCullDistances = in->maxCombinedClipAndCullDistances; + out->discreteQueuePriorities = in->discreteQueuePriorities; + memcpy(out->pointSizeRange, in->pointSizeRange, 2 * sizeof(float)); + memcpy(out->lineWidthRange, in->lineWidthRange, 2 * sizeof(float)); + out->pointSizeGranularity = in->pointSizeGranularity; + out->lineWidthGranularity = in->lineWidthGranularity; + out->strictLines = in->strictLines; + out->standardSampleLocations = in->standardSampleLocations; + out->optimalBufferCopyOffsetAlignment = in->optimalBufferCopyOffsetAlignment; + out->optimalBufferCopyRowPitchAlignment = in->optimalBufferCopyRowPitchAlignment; + out->nonCoherentAtomSize = in->nonCoherentAtomSize; +} + +static inline void convert_VkPhysicalDeviceProperties_host_to_win(const VkPhysicalDeviceProperties_host *in, VkPhysicalDeviceProperties *out) +{ + if (!in) return; + + out->apiVersion = in->apiVersion; + out->driverVersion = in->driverVersion; + out->vendorID = in->vendorID; + out->deviceID = in->deviceID; + out->deviceType = in->deviceType; + memcpy(out->deviceName, in->deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE * sizeof(char)); + memcpy(out->pipelineCacheUUID, in->pipelineCacheUUID, VK_UUID_SIZE * sizeof(uint8_t)); + convert_VkPhysicalDeviceLimits_host_to_win(&in->limits, &out->limits); + out->sparseProperties = in->sparseProperties; +} + +#endif /* USE_STRUCT_CONVERSION */ + 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); @@ -18,44 +183,79 @@ static VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, cons
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; + TRACE("%p, %p, %p\n", physicalDevice, pPropertyCount, pProperties); + return physicalDevice->instance->funcs.p_vkEnumerateDeviceLayerProperties(physicalDevice->phys_dev, pPropertyCount, pProperties); }
static void WINAPI wine_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) { - FIXME("stub: %p, %p\n", physicalDevice, pFeatures); + TRACE("%p, %p\n", physicalDevice, pFeatures); + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceFeatures(physicalDevice->phys_dev, pFeatures); }
static void WINAPI wine_vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) { - FIXME("stub: %p, %d, %p\n", physicalDevice, format, pFormatProperties); + TRACE("%p, %d, %p\n", physicalDevice, format, pFormatProperties); + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceFormatProperties(physicalDevice->phys_dev, 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; +#if defined(USE_STRUCT_CONVERSION) + VkResult result; + VkImageFormatProperties_host pImageFormatProperties_host; + TRACE("%p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties); + + result = physicalDevice->instance->funcs.p_vkGetPhysicalDeviceImageFormatProperties(physicalDevice->phys_dev, format, type, tiling, usage, flags, &pImageFormatProperties_host); + + convert_VkImageFormatProperties_host_to_win(&pImageFormatProperties_host, pImageFormatProperties); + return result; +#else + TRACE("%p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties); + return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceImageFormatProperties(physicalDevice->phys_dev, format, type, tiling, usage, flags, pImageFormatProperties); +#endif }
static void WINAPI wine_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) { - FIXME("stub: %p, %p\n", physicalDevice, pMemoryProperties); +#if defined(USE_STRUCT_CONVERSION) + VkPhysicalDeviceMemoryProperties_host pMemoryProperties_host; + TRACE("%p, %p\n", physicalDevice, pMemoryProperties); + + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(physicalDevice->phys_dev, &pMemoryProperties_host); + + convert_VkPhysicalDeviceMemoryProperties_host_to_win(&pMemoryProperties_host, pMemoryProperties); +#else + TRACE("%p, %p\n", physicalDevice, pMemoryProperties); + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(physicalDevice->phys_dev, pMemoryProperties); +#endif }
static void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) { - FIXME("stub: %p, %p\n", physicalDevice, pProperties); +#if defined(USE_STRUCT_CONVERSION) + VkPhysicalDeviceProperties_host pProperties_host; + TRACE("%p, %p\n", physicalDevice, pProperties); + + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties(physicalDevice->phys_dev, &pProperties_host); + + convert_VkPhysicalDeviceProperties_host_to_win(&pProperties_host, pProperties); +#else + TRACE("%p, %p\n", physicalDevice, pProperties); + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties(physicalDevice->phys_dev, pProperties); +#endif }
static void WINAPI wine_vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties) { - FIXME("stub: %p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties); + TRACE("%p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties); + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice->phys_dev, 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); + TRACE("%p, %d, %d, %d, %#x, %d, %p, %p\n", physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties); + physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice->phys_dev, format, type, samples, usage, tiling, pPropertyCount, pProperties); }
static const struct vulkan_func vk_instance_dispatch_table[] = diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index b8d2bbdb0f..b673ba502f 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -3,6 +3,11 @@ #ifndef __WINE_VULKAN_THUNKS_H #define __WINE_VULKAN_THUNKS_H
+/* Perform vulkan struct conversion on 32-bit platforms. */ +#if (defined(__i386__) || defined(__arm__)) + #define USE_STRUCT_CONVERSION +#endif + /* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */ void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
@@ -11,6 +16,153 @@ void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallba VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN;
+typedef struct VkImageFormatProperties_host +{ + VkExtent3D maxExtent; + uint32_t maxMipLevels; + uint32_t maxArrayLayers; + VkSampleCountFlags sampleCounts; + VkDeviceSize maxResourceSize; +} VkImageFormatProperties_host; + +typedef struct VkMemoryHeap_host +{ + VkDeviceSize size; + VkMemoryHeapFlags flags; +} VkMemoryHeap_host; + +typedef struct VkPhysicalDeviceMemoryProperties_host +{ + uint32_t memoryTypeCount; + VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES]; + uint32_t memoryHeapCount; + VkMemoryHeap_host memoryHeaps[VK_MAX_MEMORY_HEAPS]; +} VkPhysicalDeviceMemoryProperties_host; + +typedef struct VkPhysicalDeviceLimits_host +{ + uint32_t maxImageDimension1D; + uint32_t maxImageDimension2D; + uint32_t maxImageDimension3D; + uint32_t maxImageDimensionCube; + uint32_t maxImageArrayLayers; + uint32_t maxTexelBufferElements; + uint32_t maxUniformBufferRange; + uint32_t maxStorageBufferRange; + uint32_t maxPushConstantsSize; + uint32_t maxMemoryAllocationCount; + uint32_t maxSamplerAllocationCount; + VkDeviceSize bufferImageGranularity; + VkDeviceSize sparseAddressSpaceSize; + uint32_t maxBoundDescriptorSets; + uint32_t maxPerStageDescriptorSamplers; + uint32_t maxPerStageDescriptorUniformBuffers; + uint32_t maxPerStageDescriptorStorageBuffers; + uint32_t maxPerStageDescriptorSampledImages; + uint32_t maxPerStageDescriptorStorageImages; + uint32_t maxPerStageDescriptorInputAttachments; + uint32_t maxPerStageResources; + uint32_t maxDescriptorSetSamplers; + uint32_t maxDescriptorSetUniformBuffers; + uint32_t maxDescriptorSetUniformBuffersDynamic; + uint32_t maxDescriptorSetStorageBuffers; + uint32_t maxDescriptorSetStorageBuffersDynamic; + uint32_t maxDescriptorSetSampledImages; + uint32_t maxDescriptorSetStorageImages; + uint32_t maxDescriptorSetInputAttachments; + uint32_t maxVertexInputAttributes; + uint32_t maxVertexInputBindings; + uint32_t maxVertexInputAttributeOffset; + uint32_t maxVertexInputBindingStride; + uint32_t maxVertexOutputComponents; + uint32_t maxTessellationGenerationLevel; + uint32_t maxTessellationPatchSize; + uint32_t maxTessellationControlPerVertexInputComponents; + uint32_t maxTessellationControlPerVertexOutputComponents; + uint32_t maxTessellationControlPerPatchOutputComponents; + uint32_t maxTessellationControlTotalOutputComponents; + uint32_t maxTessellationEvaluationInputComponents; + uint32_t maxTessellationEvaluationOutputComponents; + uint32_t maxGeometryShaderInvocations; + uint32_t maxGeometryInputComponents; + uint32_t maxGeometryOutputComponents; + uint32_t maxGeometryOutputVertices; + uint32_t maxGeometryTotalOutputComponents; + uint32_t maxFragmentInputComponents; + uint32_t maxFragmentOutputAttachments; + uint32_t maxFragmentDualSrcAttachments; + uint32_t maxFragmentCombinedOutputResources; + uint32_t maxComputeSharedMemorySize; + uint32_t maxComputeWorkGroupCount[3]; + uint32_t maxComputeWorkGroupInvocations; + uint32_t maxComputeWorkGroupSize[3]; + uint32_t subPixelPrecisionBits; + uint32_t subTexelPrecisionBits; + uint32_t mipmapPrecisionBits; + uint32_t maxDrawIndexedIndexValue; + uint32_t maxDrawIndirectCount; + float maxSamplerLodBias; + float maxSamplerAnisotropy; + uint32_t maxViewports; + uint32_t maxViewportDimensions[2]; + float viewportBoundsRange[2]; + uint32_t viewportSubPixelBits; + size_t minMemoryMapAlignment; + VkDeviceSize minTexelBufferOffsetAlignment; + VkDeviceSize minUniformBufferOffsetAlignment; + VkDeviceSize minStorageBufferOffsetAlignment; + int32_t minTexelOffset; + uint32_t maxTexelOffset; + int32_t minTexelGatherOffset; + uint32_t maxTexelGatherOffset; + float minInterpolationOffset; + float maxInterpolationOffset; + uint32_t subPixelInterpolationOffsetBits; + uint32_t maxFramebufferWidth; + uint32_t maxFramebufferHeight; + uint32_t maxFramebufferLayers; + VkSampleCountFlags framebufferColorSampleCounts; + VkSampleCountFlags framebufferDepthSampleCounts; + VkSampleCountFlags framebufferStencilSampleCounts; + VkSampleCountFlags framebufferNoAttachmentsSampleCounts; + uint32_t maxColorAttachments; + VkSampleCountFlags sampledImageColorSampleCounts; + VkSampleCountFlags sampledImageIntegerSampleCounts; + VkSampleCountFlags sampledImageDepthSampleCounts; + VkSampleCountFlags sampledImageStencilSampleCounts; + VkSampleCountFlags storageImageSampleCounts; + uint32_t maxSampleMaskWords; + VkBool32 timestampComputeAndGraphics; + float timestampPeriod; + uint32_t maxClipDistances; + uint32_t maxCullDistances; + uint32_t maxCombinedClipAndCullDistances; + uint32_t discreteQueuePriorities; + float pointSizeRange[2]; + float lineWidthRange[2]; + float pointSizeGranularity; + float lineWidthGranularity; + VkBool32 strictLines; + VkBool32 standardSampleLocations; + VkDeviceSize optimalBufferCopyOffsetAlignment; + VkDeviceSize optimalBufferCopyRowPitchAlignment; + VkDeviceSize nonCoherentAtomSize; +} VkPhysicalDeviceLimits_host; + +typedef struct VkPhysicalDeviceProperties_host +{ + uint32_t apiVersion; + uint32_t driverVersion; + uint32_t vendorID; + uint32_t deviceID; + VkPhysicalDeviceType deviceType; + char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; + uint8_t pipelineCacheUUID[VK_UUID_SIZE]; + VkPhysicalDeviceLimits_host limits; + VkPhysicalDeviceSparseProperties sparseProperties; +} VkPhysicalDeviceProperties_host; + + /* For use by vkInstance and children */ struct vulkan_instance_funcs { @@ -20,9 +172,21 @@ struct vulkan_instance_funcs VkResult (*p_vkEnumeratePhysicalDevices)(VkInstance, uint32_t *, VkPhysicalDevice *); void (*p_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice, VkPhysicalDeviceFeatures *); void (*p_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice, VkFormat, VkFormatProperties *); +#if defined(USE_STRUCT_CONVERSION) + VkResult (*p_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags, VkImageFormatProperties_host *); +#else VkResult (*p_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags, VkImageFormatProperties *); +#endif +#if defined(USE_STRUCT_CONVERSION) + void (*p_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice, VkPhysicalDeviceMemoryProperties_host *); +#else void (*p_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice, VkPhysicalDeviceMemoryProperties *); +#endif +#if defined(USE_STRUCT_CONVERSION) + void (*p_vkGetPhysicalDeviceProperties)(VkPhysicalDevice, VkPhysicalDeviceProperties_host *); +#else void (*p_vkGetPhysicalDeviceProperties)(VkPhysicalDevice, VkPhysicalDeviceProperties *); +#endif void (*p_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice, uint32_t *, VkQueueFamilyProperties *); void (*p_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkSampleCountFlagBits, VkImageUsageFlags, VkImageTiling, uint32_t *, VkSparseImageFormatProperties *); };
The patches look mostly good to me except for a potential issue related to the structure conversion on ARM (see below). Thanks!
On Thu, Mar 8, 2018 at 7:57 AM, Roderick Colenbrander thunderbird2k@gmail.com wrote:
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com
dlls/winevulkan/make_vulkan | 734 +++++++++++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_thunks.c | 220 +++++++++++- dlls/winevulkan/vulkan_thunks.h | 164 +++++++++ 3 files changed, 1105 insertions(+), 13 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 7499cf7011..2aec101723 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -68,7 +68,6 @@ 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. # DRIVER_VERSION should be bumped on any change to driver interface # in FUNCTION_OVERRIDES @@ -95,6 +94,13 @@ FUNCTION_OVERRIDES = { }
+class Direction(Enum):
- """ Parameter direction: input, output, input_output. """
- INPUT = 1
- OUTPUT = 2
- INPUT_OUTPUT = 3
class VkBaseType(object): def __init__(self, name, _type, requires=None): """ Vulkan base type class. @@ -285,6 +291,21 @@ class VkFunction(object):
return VkFunction(_type=func_type, name=func_name, params=params)
- def get_conversions(self):
""" Get a list of conversion functions required for this function if any.
Parameters which are structures may require conversion between win32
and the host platform. This function returns a list of conversions
required.
"""
conversions = []
for param in self.params:
convs = param.get_conversions()
if convs is not None:
conversions.extend(convs)
return conversions
- 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()
@@ -312,9 +333,32 @@ class VkFunction(object): def is_required(self): return self.required
- def needs_conversion(self):
""" Check if the function needs any input/output type conversion.
Funcsions need input/output conversion if struct parameters have
Typo: Funcsions
alignment differences between Win32 and Linux 32-bit.
"""
for p in self.params:
if p.needs_conversion():
LOGGER.debug("Parameter {0} to {1} requires conversion".format(p.name, self.name))
return True
return False
def needs_dispatch(self): return self.dispatch
def needs_stub(self):
""" Temporary function to limit script hacks until more code is implemented. """
if self.name == "vkCreateDevice":
return True
if self.params[0].type != "VkPhysicalDevice":
return True
return False
def needs_thunk(self): return self.thunk_needed
@@ -374,6 +418,77 @@ class VkFunction(object):
return proto
- def body(self):
body = " {0}".format(self.trace())
params = ", ".join([p.variable(conv=False) for p in self.params])
# Call the native Vulkan function.
if self.type == "void":
body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
else:
body += " return {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
return body
- def body_conversion(self):
body = ""
# Declare a variable to hold the result for non-void functions.
if self.type != "void":
body += " {0} result;\n".format(self.type)
# Declare any tmp parameters for conversion.
for p in self.params:
if not p.needs_conversion():
continue
if p.is_dynamic_array():
body += " {0}_host *{1}_host;\n".format(p.type, p.name)
else:
body += " {0}_host {1}_host;\n".format(p.type, p.name)
body += " {0}\n".format(self.trace())
# Call any win_to_host conversion calls.
for p in self.params:
if not p.needs_input_conversion():
continue
body += p.copy(Direction.INPUT)
# Build list of parameters containing converted and non-converted parameters.
# The param itself knows if conversion is needed and applies it when we set conv=True.
params = ", ".join([p.variable(conv=True) for p in self.params])
# Call the native Vulkan function.
if self.type == "void":
body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
else:
body += " result = {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
body += "\n"
# Call any host_to_win conversion calls.
for p in self.params:
if not p.needs_output_conversion():
continue
body += p.copy(Direction.OUTPUT)
# Perform any required cleanups. Most of these are for array functions.
for p in self.params:
if not p.needs_free():
continue
body += p.free()
# Finally return the result.
if self.type != "void":
body += " return result;\n"
return body
- def stub(self, call_conv=None, prefix=None): stub = self.prototype(call_conv=call_conv, prefix=prefix) stub += "\n{\n"
@@ -387,6 +502,22 @@ class VkFunction(object): stub += "}\n\n" return stub
- def thunk(self, call_conv=None, prefix=None):
thunk = self.prototype(call_conv=call_conv, prefix=prefix)
thunk += "\n{\n"
if self.needs_conversion():
thunk += "#if defined(USE_STRUCT_CONVERSION)\n"
thunk += self.body_conversion()
thunk += "#else\n"
thunk += self.body()
thunk += "#endif\n"
else:
thunk += self.body()
thunk += "}\n\n"
return thunk
- def trace(self, message=None, trace_func=None): """ Create a trace string including all parameters.
@@ -492,6 +623,23 @@ class VkHandle(object): parent = handle.attrib.get("parent") # Most objects have a parent e.g. VkQueue has VkDevice. return VkHandle(name, _type, parent)
- def dispatch_table(self):
if not self.is_dispatchable():
return None
if self.parent is None:
# Should only happen for VkInstance
return "funcs"
elif self.name == "VkDevice":
# VkDevice has VkInstance as a parent, but has its own dispatch table.
return "funcs"
elif self.parent in ["VkInstance", "VkPhysicalDevice"]:
return "instance->funcs"
elif self.parent in ["VkDevice", "VkCommandPool"]:
return "device->funcs"
else:
LOGGER.error("Unhandled dispatchable parent: {0}".format(self.parent))
- def definition(self): """ Generates handle definition e.g. VK_DEFINE_HANDLE(vkInstance) """ return "{0}({1})\n".format(self.type, self.name)
@@ -502,6 +650,28 @@ class VkHandle(object): """ return self.type == "VK_DEFINE_HANDLE"
- def native_handle(self):
""" Provide access to the native handle of a dispatchable object.
Dispatchable objects wrap an underlaying 'native' object.
Typo: underlying
This method provides access to the native object.
"""
if not self.is_dispatchable():
return None
if self.name == "VkCommandBuffer":
return "command_buffer"
elif self.name == "VkDevice":
return "device"
elif self.name == "VkInstance":
return "instance"
elif self.name == "VkPhysicalDevice":
return "phys_dev"
elif self.name == "VkQueue":
return "queue"
else:
LOGGER.error("Unhandled native handle for: {0}".format(self.name))
class VkMember(object): def __init__(self, const=None, _type=None, pointer=None, name=None, array_len=None, dyn_array_len=None, optional=False, @@ -582,6 +752,36 @@ class VkMember(object): return VkMember(const=const, _type=member_type, pointer=pointer, name=name_elem.text, array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, extension_structs=extension_structs)
- def copy(self, input, output, direction):
""" Helper method for use by conversion logic to generate a C-code statement to copy this member. """
if self.needs_conversion():
if self.is_dynamic_array():
if direction == Direction.OUTPUT:
LOGGER.warn("TODO: implement copying of returnedonly dynamic array for {0}.{1}".format(self.type, self.name))
else:
# Array length is either a variable name (string) or an int.
count = self.dyn_array_len if isinstance(self.dyn_array_len, int) else "{0}{1}".format(input, self.dyn_array_len)
return "{0}{1} = convert_{2}_array_win_to_host({3}{1}, {4});\n".format(output, self.name, self.type, input, count)
elif self.is_static_array():
count = self.array_len
if direction == Direction.OUTPUT:
# Needed by VkMemoryHeap.memoryHeaps
return "convert_{0}_static_array_host_to_win({2}{1}, {3}{1}, {4});\n".format(self.type, self.name, input, output, count)
else:
# Nothing needed this yet.
LOGGER.warn("TODO: implement copying of static array for {0}.{1}".format(self.type, self.name))
else:
if direction == Direction.OUTPUT:
return "convert_{0}_host_to_win(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output)
else:
return "convert_{0}_win_to_host(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output)
elif self.is_static_array():
bytes_count = "{0} * sizeof({1})".format(self.array_len, self.type)
return "memcpy({0}{1}, {2}{1}, {3});\n".format(output, self.name, input, bytes_count)
else:
return "{0}{1} = {2}{1};\n".format(output, self.name, input)
- def definition(self, align=False, conv=False): """ Generate prototype for given function.
@@ -612,6 +812,36 @@ class VkMember(object):
return text
- def get_conversions(self):
""" Return any conversion description for this member and its children when conversion is needed. """
# Check if we need conversion either for this member itself or for any child members
# in case member represents a struct.
if not self.needs_conversion():
return None
conversions = []
# Collect any conversion for any member structs.
struct = self.type_info["data"]
for m in struct:
if m.needs_conversion():
conversions.extend(m.get_conversions())
struct = self.type_info["data"]
direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT
if self.is_dynamic_array():
conversions.append(ConversionFunction(False, True, direction, struct))
elif self.is_static_array():
conversions.append(ConversionFunction(True, False, direction, struct))
else:
conversions.append(ConversionFunction(False, False, direction, struct))
if self.needs_free():
conversions.append(FreeFunction(self.is_dynamic_array(), struct))
return conversions
- def is_const(self): return self.const is not None
@@ -663,6 +893,26 @@ class VkMember(object): return False if handle.is_dispatchable() else True return False
- def needs_conversion(self):
""" Structures requiring alignment, need conversion between win32 and host. """
if not self.is_struct():
return False
struct = self.type_info["data"]
return struct.needs_conversion()
- def needs_free(self):
if not self.needs_conversion():
return False
if self.is_dynamic_array():
return True
# TODO: some non-pointer structs and optional pointer structs may need freeing,
# though none of this type have been encountered yet.
return False
- def set_type_info(self, type_info): """ Helper function to set type information from the type registry. This is needed, because not all type data is available at time of
@@ -685,7 +935,9 @@ 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_direction() self._set_format_string()
self._set_conversions()
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)
@@ -722,6 +974,59 @@ 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_conversions(self):
""" Internal helper function to configure any needed conversion functions. """
self.free_func = None
self.input_conv = None
self.output_conv = None
if not self.needs_conversion():
return
# Input functions require win to host conversion.
if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]:
self.input_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.INPUT, self.struct)
# Output functions require host to win conversion.
if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]:
self.output_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.OUTPUT, self.struct)
# Dynamic arrays, but also some normal structs (e.g. VkCommandBufferBeginInfo) need memory
# allocation and thus some cleanup.
if self.is_dynamic_array() or self.struct.needs_free():
self.free_func = FreeFunction(self.is_dynamic_array(), self.struct)
- def _set_direction(self):
""" Internal helper function to set parameter direction (input/output/input_output). """
# The parameter direction needs to be determined from hints in vk.xml like returnedonly,
# parameter constness and other heuristics.
# For now we need to get this right for structures as we need to convert these, we may have
# missed a few other edge cases (e.g. count variables).
# See also https://github.com/KhronosGroup/Vulkan-Docs/issues/610
if not self.is_pointer():
self._direction = Direction.INPUT
elif self.is_const() and self.is_pointer():
self._direction = Direction.INPUT
elif self.is_struct():
if not self.struct.returnedonly:
self._direction = Direction.INPUT
return
# Returnedonly hints towards output, however in some cases
# it is inputoutput. In particular if pNext / sType exist,
# which are used to link in other structures without having
# to introduce new APIs. E.g. vkGetPhysicalDeviceProperties2KHR.
if "pNext" in self.struct:
self._direction = Direction.INPUT_OUTPUT
return
self._direction = Direction.OUTPUT
else:
# This should mostly be right. Count variables can be inout, but we don't care about these yet.
self._direction = Direction.OUTPUT
- def _set_format_string(self): """ Internal helper function to be used by constructor to set format string. """
@@ -765,6 +1070,18 @@ class VkParam(object): else: LOGGER.warn("Unhandled type: {0}".format(self.type_info))
- def copy(self, direction):
if direction == Direction.INPUT:
if self.is_dynamic_array():
return " {0}_host = convert_{1}_array_win_to_host({0}, {2});\n".format(self.name, self.type, self.dyn_array_len)
else:
return " convert_{0}_win_to_host({1}, &{1}_host);\n".format(self.type, self.name)
else:
if self.is_dynamic_array():
LOGGER.error("Unimplemented output conversion for: {0}".format(self.name))
else:
return " convert_{0}_host_to_win(&{1}_host, {1});\n".format(self.type, self.name)
- def definition(self, postfix=None): """ Return prototype for the parameter. E.g. 'const char *foo' """
@@ -800,6 +1117,68 @@ class VkParam(object): def format_string(self): return self.format_str
- def dispatch_table(self):
""" Return functions dispatch table pointer for dispatchable objects. """
if not self.is_dispatchable():
return None
return "{0}->{1}".format(self.name, self.handle.dispatch_table())
- def format_string(self):
return self.format_str
- def free(self):
if self.is_dynamic_array():
if self.struct.returnedonly:
# For returnedonly, counts is stored in a pointer.
return " free_{0}_array({1}_host, *{2});\n".format(self.type, self.name, self.dyn_array_len)
else:
return " free_{0}_array({1}_host, {2});\n".format(self.type, self.name, self.dyn_array_len)
else:
# We are operating on a single structure. Some structs (very rare) contain dynamic members,
# which would need freeing.
if self.struct.needs_free():
return " free_{0}(&{1}_host);\n".format(self.type, self.name)
return ""
- def get_conversions(self):
""" Get a list of conversions required for this parameter if any.
Parameters which are structures may require conversion between win32
and the host platform. This function returns a list of conversions
required.
"""
if not self.is_struct():
return None
if not self.needs_conversion():
return None
conversions = []
# Collect any member conversions first, so we can guarantee
# those functions will be defined prior to usage by the
# 'parent' param requiring conversion.
for m in self.struct:
if not m.is_struct():
continue
if not m.needs_conversion():
continue
conversions.extend(m.get_conversions())
# Conversion requirements for the 'parent' parameter.
if self.input_conv is not None:
conversions.append(self.input_conv)
if self.output_conv is not None:
conversions.append(self.output_conv)
if self.free_func is not None:
conversions.append(self.free_func)
return conversions
- def is_const(self): return self.const is not None
@@ -824,6 +1203,62 @@ class VkParam(object): def is_struct(self): return self.struct is not None
- def needs_conversion(self):
""" Returns if parameter needs conversion between win32 and host. """
if not self.is_struct():
return False
# VkSparseImageMemoryRequirements is used by vkGetImageSparseMemoryRequirements.
# This function is tricky to wrap, because how to wrap depends on whether
# pSparseMemoryRequirements is NULL or not. Luckily for VkSparseImageMemoryRequirements
# the alignment works out in such a way that no conversion is needed between win32 and Linux.
if self.type == "VkSparseImageMemoryRequirements":
return False
# If a structure needs alignment changes, it means we need to
# perform parameter conversion between win32 and host.
if self.struct.needs_conversion():
return True
return False
- def needs_free(self):
return self.free_func is not None
- def needs_input_conversion(self):
return self.input_conv is not None
- def needs_output_conversion(self):
return self.output_conv is not None
- def variable(self, conv=False):
""" Returns 'glue' code during generation of a function call on how to access the variable.
This function handles various scenarios such as 'unwrapping' if dispatchable objects and
renaming of parameters in case of win32 -> host conversion.
Args:
conv (bool, optional): Enable conversion if the param needs it. This appends '_host' to the name.
"""
# Hack until we enable allocation callbacks from ICD to application. These are a joy
# to enable one day, because of calling convention conversion.
if "VkAllocationCallbacks" in self.type:
LOGGER.debug("HACK: setting NULL VkAllocationCallbacks for {0}".format(self.name))
return "NULL"
I think it would be better to call it a TODO instead of HACK.
# Dispatchable objects wrap the native handle. For thunk generation we
# need to pass the native handle to the native vulkan calls.
if self.is_dispatchable():
return "{0}->{1}".format(self.name, self.handle.native_handle())
elif conv and self.needs_conversion():
if self.is_dynamic_array():
return "{0}_host".format(self.name)
else:
return "&{0}_host".format(self.name)
else:
return self.name
class VkStruct(Sequence): """ Class which represents the type union and struct. """ @@ -953,6 +1388,31 @@ class VkStruct(Sequence): return True return False
- def needs_conversion(self):
""" Returns if struct members needs conversion between win32 and host.
Structures need conversion if they contain members requiring alignment
or if they include other structures which need alignment.
"""
if self.needs_alignment():
return True
for m in self.members:
if m.needs_conversion():
return True
return False
- def needs_free(self):
""" Check if any struct member needs some memory freeing."""
for m in self.members:
if m.needs_free():
return True
continue
return False
- def set_type_info(self, types): """ Helper function to set type information from the type registry. This is needed, because not all type data is available at time of
@@ -963,10 +1423,251 @@ class VkStruct(Sequence): m.set_type_info(type_info)
+class ConversionFunction(object):
- def __init__(self, array, dyn_array, direction, struct):
self.array = array
self.direction = direction
self.dyn_array = dyn_array
self.struct = struct
self.type = struct.name
self._set_name()
- def __eq__(self, other):
if self.name != other.name:
return False
return True
- def _generate_array_conversion_func(self):
""" Helper function for generating a conversion function for array structs. """
if self.direction == Direction.OUTPUT:
params = ["const {0}_host *in".format(self.type), "uint32_t count"]
return_type = self.type
else:
params = ["const {0} *in".format(self.type), "uint32_t count"]
return_type = "{0}_host".format(self.type)
# Generate function prototype.
body = "static inline {0} * {1}(".format(return_type, self.name)
body += ", ".join(p for p in params)
body += ")\n{\n"
body += " {0} *out;\n".format(return_type)
body += " unsigned int i;\n\n"
body += " if (!in) return NULL;\n\n"
body += " out = ({0} *)heap_alloc(count * sizeof(*out));\n".format(return_type)
body += " for (i = 0; i < count; i++)\n"
body += " {\n"
for m in self.struct:
# TODO: support copying of pNext extension structures!
# Luckily though no extension struct at this point needs conversion.
body += " " + m.copy("in[i].", "out[i].", self.direction)
body += " }\n\n"
body += " return out;\n"
body += "}\n\n"
return body
- def _generate_conversion_func(self):
""" Helper function for generating a conversion function for non-array structs. """
if self.direction == Direction.OUTPUT:
params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type)]
else:
params = ["const {0} *in".format(self.type), "{0}_host *out".format(self.type)]
body = "static inline void {0}(".format(self.name)
# Generate parameter list
body += ", ".join(p for p in params)
body += ")\n{\n"
body += " if (!in) return;\n\n"
if self.direction == Direction.INPUT and "pNext" in self.struct and self.struct.returnedonly:
# We are dealing with an input_output parameter. For these we only need to copy
# pNext and sType as the other fields are filled in by the host. We do potentially
# have to iterate over pNext and perform conversions based on switch(sType)!
# Luckily though no extension structs at this point need conversion.
# TODO: support copying of pNext extension structures!
body += " out->pNext = in->pNext;\n"
body += " out->sType = in->sType;\n"
else:
for m in self.struct:
# TODO: support copying of pNext extension structures!
body += " " + m.copy("in->", "out->", self.direction)
body += "}\n\n"
return body
- def _generate_static_array_conversion_func(self):
""" Helper function for generating a conversion function for array structs. """
if self.direction == Direction.OUTPUT:
params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type), "uint32_t count"]
return_type = self.type
else:
params = ["const {0} *in".format(self.type), "{0} *out_host".format(self.type), "uint32_t count"]
return_type = "{0}_host".format(self.type)
# Generate function prototype.
body = "static inline void {0}(".format(self.name)
body += ", ".join(p for p in params)
body += ")\n{\n"
body += " unsigned int i;\n\n"
body += " if (!in) return;\n\n"
body += " for (i = 0; i < count; i++)\n"
body += " {\n"
for m in self.struct:
# TODO: support copying of pNext extension structures!
body += " " + m.copy("in[i].", "out[i].", self.direction)
body += " }\n"
body += "}\n\n"
return body
- def _set_name(self):
if self.direction == Direction.INPUT:
if self.array:
name = "convert_{0}_static_array_win_to_host".format(self.type)
elif self.dyn_array:
name = "convert_{0}_array_win_to_host".format(self.type)
else:
name = "convert_{0}_win_to_host".format(self.type)
else: # Direction.OUTPUT
if self.array:
name = "convert_{0}_static_array_host_to_win".format(self.type)
elif self.dyn_array:
name = "convert_{0}_array_host_to_win".format(self.type)
else:
name = "convert_{0}_host_to_win".format(self.type)
self.name = name
- def definition(self):
if self.array:
return self._generate_static_array_conversion_func()
elif self.dyn_array:
return self._generate_array_conversion_func()
else:
return self._generate_conversion_func()
+class FreeFunction(object):
- def __init__(self, dyn_array, struct):
self.dyn_array = dyn_array
self.struct = struct
self.type = struct.name
if dyn_array:
self.name = "free_{0}_array".format(self.type)
else:
self.name = "free_{0}".format(self.type)
- def __eq__(self, other):
if self.name == other.name:
return True
return False
- def _generate_array_free_func(self):
""" Helper function for cleaning up temporary buffers required for array conversions. """
# Generate function prototype.
body = "static inline void {0}({1}_host *in, uint32_t count)\n{{\n".format(self.name, self.type)
# E.g. VkGraphicsPipelineCreateInfo_host needs freeing for pStages.
if self.struct.needs_free():
body += " unsigned int i;\n\n"
body += " if (!in) return;\n\n"
body += " for (i = 0; i < count; i++)\n"
body += " {\n"
for m in self.struct:
if m.needs_conversion() and m.is_dynamic_array():
if m.is_const():
# Add a cast to ignore const on conversion structs we allocated ourselves.
body += " free_{0}_array(({0}_host *)in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len)
else:
body += " free_{0}_array(in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len)
elif m.needs_conversion():
LOGGER.error("Unhandled conversion for {0}".format(m.name))
body += " }\n"
else:
body += " if (!in) return;\n\n"
body += " heap_free(in);\n"
body += "}\n\n"
return body
- def _generate_free_func(self):
# E.g. VkCommandBufferBeginInfo.pInheritanceInfo needs freeing.
if not self.struct.needs_free():
return ""
# Generate function prototype.
body = "static inline void {0}({1}_host *in)\n{{\n".format(self.name, self.type)
for m in self.struct:
if m.needs_conversion() and m.is_dynamic_array():
count = m.dyn_array_len if isinstance(m.dyn_array_len, int) else "in->{0}".format(m.dyn_array_len)
if m.is_const():
# Add a cast to ignore const on conversion structs we allocated ourselves.
body += " free_{0}_array(({0}_host *)in->{1}, {2});\n".format(m.type, m.name, count)
else:
body += " free_{0}_array(in->{1}, {2});\n".format(m.type, m.name, count)
body += "}\n\n"
return body
- def definition(self):
if self.dyn_array:
return self._generate_array_free_func()
else:
# Some structures need freeing too if they contain dynamic arrays.
# E.g. VkCommandBufferBeginInfo
return self._generate_free_func()
class VkGenerator(object): def __init__(self, registry): self.registry = registry
# Build a list conversion functions for struct conversion.
self.conversions = []
self.host_structs = []
for func in self.registry.funcs.values():
if not func.is_required():
continue
# Temporary filter.
if func.needs_stub():
continue
if not func.needs_conversion():
continue
conversions = func.get_conversions()
for conv in conversions:
# Pull in any conversions for vulkan_thunks.c. Driver conversions we
# handle manually in vulkan.c if needed.
if not func.is_driver_func():
# Append if we don't already have this conversion.
if not any(c == conv for c in self.conversions):
self.conversions.append(conv)
# Structs can be used in different ways by different conversions
# e.g. array vs non-array. Just make sure we pull in each struct once.
if not any(s.name == conv.struct.name for s in self.host_structs):
self.host_structs.append(conv.struct)
- def generate_thunks_c(self, f, prefix): f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
@@ -974,12 +1675,19 @@ class VkGenerator(object): f.write("#include "wine/port.h"\n\n")
f.write("#include \"wine/debug.h\"\n")
f.write("#include \"wine/heap.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")
# Generate any conversion helper functions.
f.write("#if defined(USE_STRUCT_CONVERSION)\n")
for conv in self.conversions:
f.write(conv.definition())
f.write("#endif /* USE_STRUCT_CONVERSION */\n\n")
# Create thunks for instance functions. # Global functions don't go through the thunks. for vk_func in self.registry.funcs.values():
@@ -997,7 +1705,11 @@ class VkGenerator(object): if not vk_func.needs_thunk(): continue
f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI"))
# Temporary filter.
if vk_func.needs_stub():
f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI"))
else:
f.write("static " + vk_func.thunk(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:
@@ -1031,6 +1743,11 @@ class VkGenerator(object): f.write("#ifndef __WINE_VULKAN_THUNKS_H\n") f.write("#define __WINE_VULKAN_THUNKS_H\n\n")
f.write("/* Perform vulkan struct conversion on 32-bit platforms. */\n")
f.write("#if (defined(__i386__) || defined(__arm__))\n")
f.write(" #define USE_STRUCT_CONVERSION\n")
f.write("#endif\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")
@@ -1043,6 +1760,10 @@ class VkGenerator(object): f.write("{0};\n".format(vk_func.prototype("WINAPI", prefix="wine_", postfix="DECLSPEC_HIDDEN"))) f.write("\n")
for struct in self.host_structs:
f.write(struct.definition(align=False, conv=True, postfix="_host"))
f.write("\n")
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:
@@ -1053,7 +1774,14 @@ class VkGenerator(object): LOGGER.debug("skipping {0} in vulkan_instance_funcs".format(vk_func.name)) continue
f.write(" {0};\n".format(vk_func.pfn(conv=False)))
if vk_func.needs_conversion():
f.write("#if defined(USE_STRUCT_CONVERSION)\n")
f.write(" {0};\n".format(vk_func.pfn(conv=True)))
f.write("#else\n")
f.write(" {0};\n".format(vk_func.pfn(conv=False)))
f.write("#endif\n")
else:
f.write(" {0};\n".format(vk_func.pfn(conv=False))) f.write("};\n\n") f.write("#define ALL_VK_INSTANCE_FUNCS() \\\n")
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 2e1b62d23c..daab898522 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -4,12 +4,177 @@ #include "wine/port.h"
#include "wine/debug.h" +#include "wine/heap.h" #include "wine/vulkan.h" #include "wine/vulkan_driver.h" #include "vulkan_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkImageFormatProperties_host_to_win(const VkImageFormatProperties_host *in, VkImageFormatProperties *out) +{
- if (!in) return;
- out->maxExtent = in->maxExtent;
- out->maxMipLevels = in->maxMipLevels;
- out->maxArrayLayers = in->maxArrayLayers;
- out->sampleCounts = in->sampleCounts;
- out->maxResourceSize = in->maxResourceSize;
+}
+static inline void convert_VkMemoryHeap_static_array_host_to_win(const VkMemoryHeap_host *in, VkMemoryHeap *out, uint32_t count) +{
- unsigned int i;
- if (!in) return;
- for (i = 0; i < count; i++)
- {
out[i].size = in[i].size;
out[i].flags = in[i].flags;
- }
+}
+static inline void convert_VkPhysicalDeviceMemoryProperties_host_to_win(const VkPhysicalDeviceMemoryProperties_host *in, VkPhysicalDeviceMemoryProperties *out) +{
- if (!in) return;
- out->memoryTypeCount = in->memoryTypeCount;
- memcpy(out->memoryTypes, in->memoryTypes, VK_MAX_MEMORY_TYPES * sizeof(VkMemoryType));
- out->memoryHeapCount = in->memoryHeapCount;
- convert_VkMemoryHeap_static_array_host_to_win(in->memoryHeaps, out->memoryHeaps, VK_MAX_MEMORY_HEAPS);
+}
+static inline void convert_VkPhysicalDeviceLimits_host_to_win(const VkPhysicalDeviceLimits_host *in, VkPhysicalDeviceLimits *out) +{
- if (!in) return;
- out->maxImageDimension1D = in->maxImageDimension1D;
- out->maxImageDimension2D = in->maxImageDimension2D;
- out->maxImageDimension3D = in->maxImageDimension3D;
- out->maxImageDimensionCube = in->maxImageDimensionCube;
- out->maxImageArrayLayers = in->maxImageArrayLayers;
- out->maxTexelBufferElements = in->maxTexelBufferElements;
- out->maxUniformBufferRange = in->maxUniformBufferRange;
- out->maxStorageBufferRange = in->maxStorageBufferRange;
- out->maxPushConstantsSize = in->maxPushConstantsSize;
- out->maxMemoryAllocationCount = in->maxMemoryAllocationCount;
- out->maxSamplerAllocationCount = in->maxSamplerAllocationCount;
- out->bufferImageGranularity = in->bufferImageGranularity;
- out->sparseAddressSpaceSize = in->sparseAddressSpaceSize;
- out->maxBoundDescriptorSets = in->maxBoundDescriptorSets;
- out->maxPerStageDescriptorSamplers = in->maxPerStageDescriptorSamplers;
- out->maxPerStageDescriptorUniformBuffers = in->maxPerStageDescriptorUniformBuffers;
- out->maxPerStageDescriptorStorageBuffers = in->maxPerStageDescriptorStorageBuffers;
- out->maxPerStageDescriptorSampledImages = in->maxPerStageDescriptorSampledImages;
- out->maxPerStageDescriptorStorageImages = in->maxPerStageDescriptorStorageImages;
- out->maxPerStageDescriptorInputAttachments = in->maxPerStageDescriptorInputAttachments;
- out->maxPerStageResources = in->maxPerStageResources;
- out->maxDescriptorSetSamplers = in->maxDescriptorSetSamplers;
- out->maxDescriptorSetUniformBuffers = in->maxDescriptorSetUniformBuffers;
- out->maxDescriptorSetUniformBuffersDynamic = in->maxDescriptorSetUniformBuffersDynamic;
- out->maxDescriptorSetStorageBuffers = in->maxDescriptorSetStorageBuffers;
- out->maxDescriptorSetStorageBuffersDynamic = in->maxDescriptorSetStorageBuffersDynamic;
- out->maxDescriptorSetSampledImages = in->maxDescriptorSetSampledImages;
- out->maxDescriptorSetStorageImages = in->maxDescriptorSetStorageImages;
- out->maxDescriptorSetInputAttachments = in->maxDescriptorSetInputAttachments;
- out->maxVertexInputAttributes = in->maxVertexInputAttributes;
- out->maxVertexInputBindings = in->maxVertexInputBindings;
- out->maxVertexInputAttributeOffset = in->maxVertexInputAttributeOffset;
- out->maxVertexInputBindingStride = in->maxVertexInputBindingStride;
- out->maxVertexOutputComponents = in->maxVertexOutputComponents;
- out->maxTessellationGenerationLevel = in->maxTessellationGenerationLevel;
- out->maxTessellationPatchSize = in->maxTessellationPatchSize;
- out->maxTessellationControlPerVertexInputComponents = in->maxTessellationControlPerVertexInputComponents;
- out->maxTessellationControlPerVertexOutputComponents = in->maxTessellationControlPerVertexOutputComponents;
- out->maxTessellationControlPerPatchOutputComponents = in->maxTessellationControlPerPatchOutputComponents;
- out->maxTessellationControlTotalOutputComponents = in->maxTessellationControlTotalOutputComponents;
- out->maxTessellationEvaluationInputComponents = in->maxTessellationEvaluationInputComponents;
- out->maxTessellationEvaluationOutputComponents = in->maxTessellationEvaluationOutputComponents;
- out->maxGeometryShaderInvocations = in->maxGeometryShaderInvocations;
- out->maxGeometryInputComponents = in->maxGeometryInputComponents;
- out->maxGeometryOutputComponents = in->maxGeometryOutputComponents;
- out->maxGeometryOutputVertices = in->maxGeometryOutputVertices;
- out->maxGeometryTotalOutputComponents = in->maxGeometryTotalOutputComponents;
- out->maxFragmentInputComponents = in->maxFragmentInputComponents;
- out->maxFragmentOutputAttachments = in->maxFragmentOutputAttachments;
- out->maxFragmentDualSrcAttachments = in->maxFragmentDualSrcAttachments;
- out->maxFragmentCombinedOutputResources = in->maxFragmentCombinedOutputResources;
- out->maxComputeSharedMemorySize = in->maxComputeSharedMemorySize;
- memcpy(out->maxComputeWorkGroupCount, in->maxComputeWorkGroupCount, 3 * sizeof(uint32_t));
- out->maxComputeWorkGroupInvocations = in->maxComputeWorkGroupInvocations;
- memcpy(out->maxComputeWorkGroupSize, in->maxComputeWorkGroupSize, 3 * sizeof(uint32_t));
- out->subPixelPrecisionBits = in->subPixelPrecisionBits;
- out->subTexelPrecisionBits = in->subTexelPrecisionBits;
- out->mipmapPrecisionBits = in->mipmapPrecisionBits;
- out->maxDrawIndexedIndexValue = in->maxDrawIndexedIndexValue;
- out->maxDrawIndirectCount = in->maxDrawIndirectCount;
- out->maxSamplerLodBias = in->maxSamplerLodBias;
- out->maxSamplerAnisotropy = in->maxSamplerAnisotropy;
- out->maxViewports = in->maxViewports;
- memcpy(out->maxViewportDimensions, in->maxViewportDimensions, 2 * sizeof(uint32_t));
- memcpy(out->viewportBoundsRange, in->viewportBoundsRange, 2 * sizeof(float));
- out->viewportSubPixelBits = in->viewportSubPixelBits;
- out->minMemoryMapAlignment = in->minMemoryMapAlignment;
- out->minTexelBufferOffsetAlignment = in->minTexelBufferOffsetAlignment;
- out->minUniformBufferOffsetAlignment = in->minUniformBufferOffsetAlignment;
- out->minStorageBufferOffsetAlignment = in->minStorageBufferOffsetAlignment;
- out->minTexelOffset = in->minTexelOffset;
- out->maxTexelOffset = in->maxTexelOffset;
- out->minTexelGatherOffset = in->minTexelGatherOffset;
- out->maxTexelGatherOffset = in->maxTexelGatherOffset;
- out->minInterpolationOffset = in->minInterpolationOffset;
- out->maxInterpolationOffset = in->maxInterpolationOffset;
- out->subPixelInterpolationOffsetBits = in->subPixelInterpolationOffsetBits;
- out->maxFramebufferWidth = in->maxFramebufferWidth;
- out->maxFramebufferHeight = in->maxFramebufferHeight;
- out->maxFramebufferLayers = in->maxFramebufferLayers;
- out->framebufferColorSampleCounts = in->framebufferColorSampleCounts;
- out->framebufferDepthSampleCounts = in->framebufferDepthSampleCounts;
- out->framebufferStencilSampleCounts = in->framebufferStencilSampleCounts;
- out->framebufferNoAttachmentsSampleCounts = in->framebufferNoAttachmentsSampleCounts;
- out->maxColorAttachments = in->maxColorAttachments;
- out->sampledImageColorSampleCounts = in->sampledImageColorSampleCounts;
- out->sampledImageIntegerSampleCounts = in->sampledImageIntegerSampleCounts;
- out->sampledImageDepthSampleCounts = in->sampledImageDepthSampleCounts;
- out->sampledImageStencilSampleCounts = in->sampledImageStencilSampleCounts;
- out->storageImageSampleCounts = in->storageImageSampleCounts;
- out->maxSampleMaskWords = in->maxSampleMaskWords;
- out->timestampComputeAndGraphics = in->timestampComputeAndGraphics;
- out->timestampPeriod = in->timestampPeriod;
- out->maxClipDistances = in->maxClipDistances;
- out->maxCullDistances = in->maxCullDistances;
- out->maxCombinedClipAndCullDistances = in->maxCombinedClipAndCullDistances;
- out->discreteQueuePriorities = in->discreteQueuePriorities;
- memcpy(out->pointSizeRange, in->pointSizeRange, 2 * sizeof(float));
- memcpy(out->lineWidthRange, in->lineWidthRange, 2 * sizeof(float));
- out->pointSizeGranularity = in->pointSizeGranularity;
- out->lineWidthGranularity = in->lineWidthGranularity;
- out->strictLines = in->strictLines;
- out->standardSampleLocations = in->standardSampleLocations;
- out->optimalBufferCopyOffsetAlignment = in->optimalBufferCopyOffsetAlignment;
- out->optimalBufferCopyRowPitchAlignment = in->optimalBufferCopyRowPitchAlignment;
- out->nonCoherentAtomSize = in->nonCoherentAtomSize;
+}
+static inline void convert_VkPhysicalDeviceProperties_host_to_win(const VkPhysicalDeviceProperties_host *in, VkPhysicalDeviceProperties *out) +{
- if (!in) return;
- out->apiVersion = in->apiVersion;
- out->driverVersion = in->driverVersion;
- out->vendorID = in->vendorID;
- out->deviceID = in->deviceID;
- out->deviceType = in->deviceType;
- memcpy(out->deviceName, in->deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE * sizeof(char));
- memcpy(out->pipelineCacheUUID, in->pipelineCacheUUID, VK_UUID_SIZE * sizeof(uint8_t));
- convert_VkPhysicalDeviceLimits_host_to_win(&in->limits, &out->limits);
- out->sparseProperties = in->sparseProperties;
+}
+#endif /* USE_STRUCT_CONVERSION */
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); @@ -18,44 +183,79 @@ static VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, cons
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;
- TRACE("%p, %p, %p\n", physicalDevice, pPropertyCount, pProperties);
- return physicalDevice->instance->funcs.p_vkEnumerateDeviceLayerProperties(physicalDevice->phys_dev, pPropertyCount, pProperties);
}
static void WINAPI wine_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) {
- FIXME("stub: %p, %p\n", physicalDevice, pFeatures);
- TRACE("%p, %p\n", physicalDevice, pFeatures);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceFeatures(physicalDevice->phys_dev, pFeatures);
}
static void WINAPI wine_vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
- FIXME("stub: %p, %d, %p\n", physicalDevice, format, pFormatProperties);
- TRACE("%p, %d, %p\n", physicalDevice, format, pFormatProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceFormatProperties(physicalDevice->phys_dev, 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;
+#if defined(USE_STRUCT_CONVERSION)
- VkResult result;
- VkImageFormatProperties_host pImageFormatProperties_host;
- TRACE("%p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
- result = physicalDevice->instance->funcs.p_vkGetPhysicalDeviceImageFormatProperties(physicalDevice->phys_dev, format, type, tiling, usage, flags, &pImageFormatProperties_host);
- convert_VkImageFormatProperties_host_to_win(&pImageFormatProperties_host, pImageFormatProperties);
- return result;
+#else
- TRACE("%p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
- return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceImageFormatProperties(physicalDevice->phys_dev, format, type, tiling, usage, flags, pImageFormatProperties);
+#endif }
static void WINAPI wine_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
- FIXME("stub: %p, %p\n", physicalDevice, pMemoryProperties);
+#if defined(USE_STRUCT_CONVERSION)
- VkPhysicalDeviceMemoryProperties_host pMemoryProperties_host;
- TRACE("%p, %p\n", physicalDevice, pMemoryProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(physicalDevice->phys_dev, &pMemoryProperties_host);
- convert_VkPhysicalDeviceMemoryProperties_host_to_win(&pMemoryProperties_host, pMemoryProperties);
+#else
- TRACE("%p, %p\n", physicalDevice, pMemoryProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(physicalDevice->phys_dev, pMemoryProperties);
+#endif }
static void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
- FIXME("stub: %p, %p\n", physicalDevice, pProperties);
+#if defined(USE_STRUCT_CONVERSION)
- VkPhysicalDeviceProperties_host pProperties_host;
- TRACE("%p, %p\n", physicalDevice, pProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties(physicalDevice->phys_dev, &pProperties_host);
- convert_VkPhysicalDeviceProperties_host_to_win(&pProperties_host, pProperties);
+#else
- TRACE("%p, %p\n", physicalDevice, pProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties(physicalDevice->phys_dev, pProperties);
+#endif }
static void WINAPI wine_vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties) {
- FIXME("stub: %p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
- TRACE("%p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice->phys_dev, 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);
- TRACE("%p, %d, %d, %d, %#x, %d, %p, %p\n", physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice->phys_dev, format, type, samples, usage, tiling, pPropertyCount, pProperties);
}
static const struct vulkan_func vk_instance_dispatch_table[] = diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index b8d2bbdb0f..b673ba502f 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -3,6 +3,11 @@ #ifndef __WINE_VULKAN_THUNKS_H #define __WINE_VULKAN_THUNKS_H
+/* Perform vulkan struct conversion on 32-bit platforms. */ +#if (defined(__i386__) || defined(__arm__))
- #define USE_STRUCT_CONVERSION
+#endif
Are you sure that the above code does the right thing on ARM? Is the structure conversion required on ARM? AFAIK ARM requires 8-byte alignment for 64-bit variables.
/* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */ void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
@@ -11,6 +16,153 @@ void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallba VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN;
+typedef struct VkImageFormatProperties_host +{
- VkExtent3D maxExtent;
- uint32_t maxMipLevels;
- uint32_t maxArrayLayers;
- VkSampleCountFlags sampleCounts;
- VkDeviceSize maxResourceSize;
+} VkImageFormatProperties_host;
+typedef struct VkMemoryHeap_host +{
- VkDeviceSize size;
- VkMemoryHeapFlags flags;
+} VkMemoryHeap_host;
+typedef struct VkPhysicalDeviceMemoryProperties_host +{
- uint32_t memoryTypeCount;
- VkMemoryType memoryTypes[VK_MAX_MEMORY_TYPES];
- uint32_t memoryHeapCount;
- VkMemoryHeap_host memoryHeaps[VK_MAX_MEMORY_HEAPS];
+} VkPhysicalDeviceMemoryProperties_host;
+typedef struct VkPhysicalDeviceLimits_host +{
- uint32_t maxImageDimension1D;
- uint32_t maxImageDimension2D;
- uint32_t maxImageDimension3D;
- uint32_t maxImageDimensionCube;
- uint32_t maxImageArrayLayers;
- uint32_t maxTexelBufferElements;
- uint32_t maxUniformBufferRange;
- uint32_t maxStorageBufferRange;
- uint32_t maxPushConstantsSize;
- uint32_t maxMemoryAllocationCount;
- uint32_t maxSamplerAllocationCount;
- VkDeviceSize bufferImageGranularity;
- VkDeviceSize sparseAddressSpaceSize;
- uint32_t maxBoundDescriptorSets;
- uint32_t maxPerStageDescriptorSamplers;
- uint32_t maxPerStageDescriptorUniformBuffers;
- uint32_t maxPerStageDescriptorStorageBuffers;
- uint32_t maxPerStageDescriptorSampledImages;
- uint32_t maxPerStageDescriptorStorageImages;
- uint32_t maxPerStageDescriptorInputAttachments;
- uint32_t maxPerStageResources;
- uint32_t maxDescriptorSetSamplers;
- uint32_t maxDescriptorSetUniformBuffers;
- uint32_t maxDescriptorSetUniformBuffersDynamic;
- uint32_t maxDescriptorSetStorageBuffers;
- uint32_t maxDescriptorSetStorageBuffersDynamic;
- uint32_t maxDescriptorSetSampledImages;
- uint32_t maxDescriptorSetStorageImages;
- uint32_t maxDescriptorSetInputAttachments;
- uint32_t maxVertexInputAttributes;
- uint32_t maxVertexInputBindings;
- uint32_t maxVertexInputAttributeOffset;
- uint32_t maxVertexInputBindingStride;
- uint32_t maxVertexOutputComponents;
- uint32_t maxTessellationGenerationLevel;
- uint32_t maxTessellationPatchSize;
- uint32_t maxTessellationControlPerVertexInputComponents;
- uint32_t maxTessellationControlPerVertexOutputComponents;
- uint32_t maxTessellationControlPerPatchOutputComponents;
- uint32_t maxTessellationControlTotalOutputComponents;
- uint32_t maxTessellationEvaluationInputComponents;
- uint32_t maxTessellationEvaluationOutputComponents;
- uint32_t maxGeometryShaderInvocations;
- uint32_t maxGeometryInputComponents;
- uint32_t maxGeometryOutputComponents;
- uint32_t maxGeometryOutputVertices;
- uint32_t maxGeometryTotalOutputComponents;
- uint32_t maxFragmentInputComponents;
- uint32_t maxFragmentOutputAttachments;
- uint32_t maxFragmentDualSrcAttachments;
- uint32_t maxFragmentCombinedOutputResources;
- uint32_t maxComputeSharedMemorySize;
- uint32_t maxComputeWorkGroupCount[3];
- uint32_t maxComputeWorkGroupInvocations;
- uint32_t maxComputeWorkGroupSize[3];
- uint32_t subPixelPrecisionBits;
- uint32_t subTexelPrecisionBits;
- uint32_t mipmapPrecisionBits;
- uint32_t maxDrawIndexedIndexValue;
- uint32_t maxDrawIndirectCount;
- float maxSamplerLodBias;
- float maxSamplerAnisotropy;
- uint32_t maxViewports;
- uint32_t maxViewportDimensions[2];
- float viewportBoundsRange[2];
- uint32_t viewportSubPixelBits;
- size_t minMemoryMapAlignment;
- VkDeviceSize minTexelBufferOffsetAlignment;
- VkDeviceSize minUniformBufferOffsetAlignment;
- VkDeviceSize minStorageBufferOffsetAlignment;
- int32_t minTexelOffset;
- uint32_t maxTexelOffset;
- int32_t minTexelGatherOffset;
- uint32_t maxTexelGatherOffset;
- float minInterpolationOffset;
- float maxInterpolationOffset;
- uint32_t subPixelInterpolationOffsetBits;
- uint32_t maxFramebufferWidth;
- uint32_t maxFramebufferHeight;
- uint32_t maxFramebufferLayers;
- VkSampleCountFlags framebufferColorSampleCounts;
- VkSampleCountFlags framebufferDepthSampleCounts;
- VkSampleCountFlags framebufferStencilSampleCounts;
- VkSampleCountFlags framebufferNoAttachmentsSampleCounts;
- uint32_t maxColorAttachments;
- VkSampleCountFlags sampledImageColorSampleCounts;
- VkSampleCountFlags sampledImageIntegerSampleCounts;
- VkSampleCountFlags sampledImageDepthSampleCounts;
- VkSampleCountFlags sampledImageStencilSampleCounts;
- VkSampleCountFlags storageImageSampleCounts;
- uint32_t maxSampleMaskWords;
- VkBool32 timestampComputeAndGraphics;
- float timestampPeriod;
- uint32_t maxClipDistances;
- uint32_t maxCullDistances;
- uint32_t maxCombinedClipAndCullDistances;
- uint32_t discreteQueuePriorities;
- float pointSizeRange[2];
- float lineWidthRange[2];
- float pointSizeGranularity;
- float lineWidthGranularity;
- VkBool32 strictLines;
- VkBool32 standardSampleLocations;
- VkDeviceSize optimalBufferCopyOffsetAlignment;
- VkDeviceSize optimalBufferCopyRowPitchAlignment;
- VkDeviceSize nonCoherentAtomSize;
+} VkPhysicalDeviceLimits_host;
+typedef struct VkPhysicalDeviceProperties_host +{
- uint32_t apiVersion;
- uint32_t driverVersion;
- uint32_t vendorID;
- uint32_t deviceID;
- VkPhysicalDeviceType deviceType;
- char deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
- uint8_t pipelineCacheUUID[VK_UUID_SIZE];
- VkPhysicalDeviceLimits_host limits;
- VkPhysicalDeviceSparseProperties sparseProperties;
+} VkPhysicalDeviceProperties_host;
/* For use by vkInstance and children */ struct vulkan_instance_funcs { @@ -20,9 +172,21 @@ struct vulkan_instance_funcs VkResult (*p_vkEnumeratePhysicalDevices)(VkInstance, uint32_t *, VkPhysicalDevice *); void (*p_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice, VkPhysicalDeviceFeatures *); void (*p_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice, VkFormat, VkFormatProperties *); +#if defined(USE_STRUCT_CONVERSION)
- VkResult (*p_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags, VkImageFormatProperties_host *);
+#else VkResult (*p_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkImageTiling, VkImageUsageFlags, VkImageCreateFlags, VkImageFormatProperties *); +#endif +#if defined(USE_STRUCT_CONVERSION)
- void (*p_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice, VkPhysicalDeviceMemoryProperties_host *);
+#else void (*p_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice, VkPhysicalDeviceMemoryProperties *); +#endif +#if defined(USE_STRUCT_CONVERSION)
- void (*p_vkGetPhysicalDeviceProperties)(VkPhysicalDevice, VkPhysicalDeviceProperties_host *);
+#else void (*p_vkGetPhysicalDeviceProperties)(VkPhysicalDevice, VkPhysicalDeviceProperties *); +#endif void (*p_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice, uint32_t *, VkQueueFamilyProperties *); void (*p_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkSampleCountFlagBits, VkImageUsageFlags, VkImageTiling, uint32_t *, VkSparseImageFormatProperties *); }; -- 2.14.3
On Fri, Mar 9, 2018 at 8:08 AM, Józef Kucia joseph.kucia@gmail.com wrote:
The patches look mostly good to me except for a potential issue related to the structure conversion on ARM (see below). Thanks!
On Thu, Mar 8, 2018 at 7:57 AM, Roderick Colenbrander thunderbird2k@gmail.com wrote:
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com
dlls/winevulkan/make_vulkan | 734 +++++++++++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_thunks.c | 220 +++++++++++- dlls/winevulkan/vulkan_thunks.h | 164 +++++++++ 3 files changed, 1105 insertions(+), 13 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 7499cf7011..2aec101723 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -68,7 +68,6 @@ 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. # DRIVER_VERSION should be bumped on any change to driver interface # in FUNCTION_OVERRIDES @@ -95,6 +94,13 @@ FUNCTION_OVERRIDES = { }
+class Direction(Enum):
- """ Parameter direction: input, output, input_output. """
- INPUT = 1
- OUTPUT = 2
- INPUT_OUTPUT = 3
class VkBaseType(object): def __init__(self, name, _type, requires=None): """ Vulkan base type class. @@ -285,6 +291,21 @@ class VkFunction(object):
return VkFunction(_type=func_type, name=func_name, params=params)
- def get_conversions(self):
""" Get a list of conversion functions required for this function if any.
Parameters which are structures may require conversion between win32
and the host platform. This function returns a list of conversions
required.
"""
conversions = []
for param in self.params:
convs = param.get_conversions()
if convs is not None:
conversions.extend(convs)
return conversions
- 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()
@@ -312,9 +333,32 @@ class VkFunction(object): def is_required(self): return self.required
- def needs_conversion(self):
""" Check if the function needs any input/output type conversion.
Funcsions need input/output conversion if struct parameters have
Typo: Funcsions
alignment differences between Win32 and Linux 32-bit.
"""
for p in self.params:
if p.needs_conversion():
LOGGER.debug("Parameter {0} to {1} requires conversion".format(p.name, self.name))
return True
return False
def needs_dispatch(self): return self.dispatch
def needs_stub(self):
""" Temporary function to limit script hacks until more code is implemented. """
if self.name == "vkCreateDevice":
return True
if self.params[0].type != "VkPhysicalDevice":
return True
return False
def needs_thunk(self): return self.thunk_needed
@@ -374,6 +418,77 @@ class VkFunction(object):
return proto
- def body(self):
body = " {0}".format(self.trace())
params = ", ".join([p.variable(conv=False) for p in self.params])
# Call the native Vulkan function.
if self.type == "void":
body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
else:
body += " return {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
return body
- def body_conversion(self):
body = ""
# Declare a variable to hold the result for non-void functions.
if self.type != "void":
body += " {0} result;\n".format(self.type)
# Declare any tmp parameters for conversion.
for p in self.params:
if not p.needs_conversion():
continue
if p.is_dynamic_array():
body += " {0}_host *{1}_host;\n".format(p.type, p.name)
else:
body += " {0}_host {1}_host;\n".format(p.type, p.name)
body += " {0}\n".format(self.trace())
# Call any win_to_host conversion calls.
for p in self.params:
if not p.needs_input_conversion():
continue
body += p.copy(Direction.INPUT)
# Build list of parameters containing converted and non-converted parameters.
# The param itself knows if conversion is needed and applies it when we set conv=True.
params = ", ".join([p.variable(conv=True) for p in self.params])
# Call the native Vulkan function.
if self.type == "void":
body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
else:
body += " result = {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(), self.name, params)
body += "\n"
# Call any host_to_win conversion calls.
for p in self.params:
if not p.needs_output_conversion():
continue
body += p.copy(Direction.OUTPUT)
# Perform any required cleanups. Most of these are for array functions.
for p in self.params:
if not p.needs_free():
continue
body += p.free()
# Finally return the result.
if self.type != "void":
body += " return result;\n"
return body
- def stub(self, call_conv=None, prefix=None): stub = self.prototype(call_conv=call_conv, prefix=prefix) stub += "\n{\n"
@@ -387,6 +502,22 @@ class VkFunction(object): stub += "}\n\n" return stub
- def thunk(self, call_conv=None, prefix=None):
thunk = self.prototype(call_conv=call_conv, prefix=prefix)
thunk += "\n{\n"
if self.needs_conversion():
thunk += "#if defined(USE_STRUCT_CONVERSION)\n"
thunk += self.body_conversion()
thunk += "#else\n"
thunk += self.body()
thunk += "#endif\n"
else:
thunk += self.body()
thunk += "}\n\n"
return thunk
- def trace(self, message=None, trace_func=None): """ Create a trace string including all parameters.
@@ -492,6 +623,23 @@ class VkHandle(object): parent = handle.attrib.get("parent") # Most objects have a parent e.g. VkQueue has VkDevice. return VkHandle(name, _type, parent)
- def dispatch_table(self):
if not self.is_dispatchable():
return None
if self.parent is None:
# Should only happen for VkInstance
return "funcs"
elif self.name == "VkDevice":
# VkDevice has VkInstance as a parent, but has its own dispatch table.
return "funcs"
elif self.parent in ["VkInstance", "VkPhysicalDevice"]:
return "instance->funcs"
elif self.parent in ["VkDevice", "VkCommandPool"]:
return "device->funcs"
else:
LOGGER.error("Unhandled dispatchable parent: {0}".format(self.parent))
- def definition(self): """ Generates handle definition e.g. VK_DEFINE_HANDLE(vkInstance) """ return "{0}({1})\n".format(self.type, self.name)
@@ -502,6 +650,28 @@ class VkHandle(object): """ return self.type == "VK_DEFINE_HANDLE"
- def native_handle(self):
""" Provide access to the native handle of a dispatchable object.
Dispatchable objects wrap an underlaying 'native' object.
Typo: underlying
This method provides access to the native object.
"""
if not self.is_dispatchable():
return None
if self.name == "VkCommandBuffer":
return "command_buffer"
elif self.name == "VkDevice":
return "device"
elif self.name == "VkInstance":
return "instance"
elif self.name == "VkPhysicalDevice":
return "phys_dev"
elif self.name == "VkQueue":
return "queue"
else:
LOGGER.error("Unhandled native handle for: {0}".format(self.name))
class VkMember(object): def __init__(self, const=None, _type=None, pointer=None, name=None, array_len=None, dyn_array_len=None, optional=False, @@ -582,6 +752,36 @@ class VkMember(object): return VkMember(const=const, _type=member_type, pointer=pointer, name=name_elem.text, array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, extension_structs=extension_structs)
- def copy(self, input, output, direction):
""" Helper method for use by conversion logic to generate a C-code statement to copy this member. """
if self.needs_conversion():
if self.is_dynamic_array():
if direction == Direction.OUTPUT:
LOGGER.warn("TODO: implement copying of returnedonly dynamic array for {0}.{1}".format(self.type, self.name))
else:
# Array length is either a variable name (string) or an int.
count = self.dyn_array_len if isinstance(self.dyn_array_len, int) else "{0}{1}".format(input, self.dyn_array_len)
return "{0}{1} = convert_{2}_array_win_to_host({3}{1}, {4});\n".format(output, self.name, self.type, input, count)
elif self.is_static_array():
count = self.array_len
if direction == Direction.OUTPUT:
# Needed by VkMemoryHeap.memoryHeaps
return "convert_{0}_static_array_host_to_win({2}{1}, {3}{1}, {4});\n".format(self.type, self.name, input, output, count)
else:
# Nothing needed this yet.
LOGGER.warn("TODO: implement copying of static array for {0}.{1}".format(self.type, self.name))
else:
if direction == Direction.OUTPUT:
return "convert_{0}_host_to_win(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output)
else:
return "convert_{0}_win_to_host(&{2}{1}, &{3}{1});\n".format(self.type, self.name, input, output)
elif self.is_static_array():
bytes_count = "{0} * sizeof({1})".format(self.array_len, self.type)
return "memcpy({0}{1}, {2}{1}, {3});\n".format(output, self.name, input, bytes_count)
else:
return "{0}{1} = {2}{1};\n".format(output, self.name, input)
- def definition(self, align=False, conv=False): """ Generate prototype for given function.
@@ -612,6 +812,36 @@ class VkMember(object):
return text
- def get_conversions(self):
""" Return any conversion description for this member and its children when conversion is needed. """
# Check if we need conversion either for this member itself or for any child members
# in case member represents a struct.
if not self.needs_conversion():
return None
conversions = []
# Collect any conversion for any member structs.
struct = self.type_info["data"]
for m in struct:
if m.needs_conversion():
conversions.extend(m.get_conversions())
struct = self.type_info["data"]
direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT
if self.is_dynamic_array():
conversions.append(ConversionFunction(False, True, direction, struct))
elif self.is_static_array():
conversions.append(ConversionFunction(True, False, direction, struct))
else:
conversions.append(ConversionFunction(False, False, direction, struct))
if self.needs_free():
conversions.append(FreeFunction(self.is_dynamic_array(), struct))
return conversions
- def is_const(self): return self.const is not None
@@ -663,6 +893,26 @@ class VkMember(object): return False if handle.is_dispatchable() else True return False
- def needs_conversion(self):
""" Structures requiring alignment, need conversion between win32 and host. """
if not self.is_struct():
return False
struct = self.type_info["data"]
return struct.needs_conversion()
- def needs_free(self):
if not self.needs_conversion():
return False
if self.is_dynamic_array():
return True
# TODO: some non-pointer structs and optional pointer structs may need freeing,
# though none of this type have been encountered yet.
return False
- def set_type_info(self, type_info): """ Helper function to set type information from the type registry. This is needed, because not all type data is available at time of
@@ -685,7 +935,9 @@ 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_direction() self._set_format_string()
self._set_conversions()
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)
@@ -722,6 +974,59 @@ 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_conversions(self):
""" Internal helper function to configure any needed conversion functions. """
self.free_func = None
self.input_conv = None
self.output_conv = None
if not self.needs_conversion():
return
# Input functions require win to host conversion.
if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]:
self.input_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.INPUT, self.struct)
# Output functions require host to win conversion.
if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]:
self.output_conv = ConversionFunction(False, self.is_dynamic_array(), Direction.OUTPUT, self.struct)
# Dynamic arrays, but also some normal structs (e.g. VkCommandBufferBeginInfo) need memory
# allocation and thus some cleanup.
if self.is_dynamic_array() or self.struct.needs_free():
self.free_func = FreeFunction(self.is_dynamic_array(), self.struct)
- def _set_direction(self):
""" Internal helper function to set parameter direction (input/output/input_output). """
# The parameter direction needs to be determined from hints in vk.xml like returnedonly,
# parameter constness and other heuristics.
# For now we need to get this right for structures as we need to convert these, we may have
# missed a few other edge cases (e.g. count variables).
# See also https://github.com/KhronosGroup/Vulkan-Docs/issues/610
if not self.is_pointer():
self._direction = Direction.INPUT
elif self.is_const() and self.is_pointer():
self._direction = Direction.INPUT
elif self.is_struct():
if not self.struct.returnedonly:
self._direction = Direction.INPUT
return
# Returnedonly hints towards output, however in some cases
# it is inputoutput. In particular if pNext / sType exist,
# which are used to link in other structures without having
# to introduce new APIs. E.g. vkGetPhysicalDeviceProperties2KHR.
if "pNext" in self.struct:
self._direction = Direction.INPUT_OUTPUT
return
self._direction = Direction.OUTPUT
else:
# This should mostly be right. Count variables can be inout, but we don't care about these yet.
self._direction = Direction.OUTPUT
- def _set_format_string(self): """ Internal helper function to be used by constructor to set format string. """
@@ -765,6 +1070,18 @@ class VkParam(object): else: LOGGER.warn("Unhandled type: {0}".format(self.type_info))
- def copy(self, direction):
if direction == Direction.INPUT:
if self.is_dynamic_array():
return " {0}_host = convert_{1}_array_win_to_host({0}, {2});\n".format(self.name, self.type, self.dyn_array_len)
else:
return " convert_{0}_win_to_host({1}, &{1}_host);\n".format(self.type, self.name)
else:
if self.is_dynamic_array():
LOGGER.error("Unimplemented output conversion for: {0}".format(self.name))
else:
return " convert_{0}_host_to_win(&{1}_host, {1});\n".format(self.type, self.name)
- def definition(self, postfix=None): """ Return prototype for the parameter. E.g. 'const char *foo' """
@@ -800,6 +1117,68 @@ class VkParam(object): def format_string(self): return self.format_str
- def dispatch_table(self):
""" Return functions dispatch table pointer for dispatchable objects. """
if not self.is_dispatchable():
return None
return "{0}->{1}".format(self.name, self.handle.dispatch_table())
- def format_string(self):
return self.format_str
- def free(self):
if self.is_dynamic_array():
if self.struct.returnedonly:
# For returnedonly, counts is stored in a pointer.
return " free_{0}_array({1}_host, *{2});\n".format(self.type, self.name, self.dyn_array_len)
else:
return " free_{0}_array({1}_host, {2});\n".format(self.type, self.name, self.dyn_array_len)
else:
# We are operating on a single structure. Some structs (very rare) contain dynamic members,
# which would need freeing.
if self.struct.needs_free():
return " free_{0}(&{1}_host);\n".format(self.type, self.name)
return ""
- def get_conversions(self):
""" Get a list of conversions required for this parameter if any.
Parameters which are structures may require conversion between win32
and the host platform. This function returns a list of conversions
required.
"""
if not self.is_struct():
return None
if not self.needs_conversion():
return None
conversions = []
# Collect any member conversions first, so we can guarantee
# those functions will be defined prior to usage by the
# 'parent' param requiring conversion.
for m in self.struct:
if not m.is_struct():
continue
if not m.needs_conversion():
continue
conversions.extend(m.get_conversions())
# Conversion requirements for the 'parent' parameter.
if self.input_conv is not None:
conversions.append(self.input_conv)
if self.output_conv is not None:
conversions.append(self.output_conv)
if self.free_func is not None:
conversions.append(self.free_func)
return conversions
- def is_const(self): return self.const is not None
@@ -824,6 +1203,62 @@ class VkParam(object): def is_struct(self): return self.struct is not None
- def needs_conversion(self):
""" Returns if parameter needs conversion between win32 and host. """
if not self.is_struct():
return False
# VkSparseImageMemoryRequirements is used by vkGetImageSparseMemoryRequirements.
# This function is tricky to wrap, because how to wrap depends on whether
# pSparseMemoryRequirements is NULL or not. Luckily for VkSparseImageMemoryRequirements
# the alignment works out in such a way that no conversion is needed between win32 and Linux.
if self.type == "VkSparseImageMemoryRequirements":
return False
# If a structure needs alignment changes, it means we need to
# perform parameter conversion between win32 and host.
if self.struct.needs_conversion():
return True
return False
- def needs_free(self):
return self.free_func is not None
- def needs_input_conversion(self):
return self.input_conv is not None
- def needs_output_conversion(self):
return self.output_conv is not None
- def variable(self, conv=False):
""" Returns 'glue' code during generation of a function call on how to access the variable.
This function handles various scenarios such as 'unwrapping' if dispatchable objects and
renaming of parameters in case of win32 -> host conversion.
Args:
conv (bool, optional): Enable conversion if the param needs it. This appends '_host' to the name.
"""
# Hack until we enable allocation callbacks from ICD to application. These are a joy
# to enable one day, because of calling convention conversion.
if "VkAllocationCallbacks" in self.type:
LOGGER.debug("HACK: setting NULL VkAllocationCallbacks for {0}".format(self.name))
return "NULL"
I think it would be better to call it a TODO instead of HACK.
# Dispatchable objects wrap the native handle. For thunk generation we
# need to pass the native handle to the native vulkan calls.
if self.is_dispatchable():
return "{0}->{1}".format(self.name, self.handle.native_handle())
elif conv and self.needs_conversion():
if self.is_dynamic_array():
return "{0}_host".format(self.name)
else:
return "&{0}_host".format(self.name)
else:
return self.name
class VkStruct(Sequence): """ Class which represents the type union and struct. """ @@ -953,6 +1388,31 @@ class VkStruct(Sequence): return True return False
- def needs_conversion(self):
""" Returns if struct members needs conversion between win32 and host.
Structures need conversion if they contain members requiring alignment
or if they include other structures which need alignment.
"""
if self.needs_alignment():
return True
for m in self.members:
if m.needs_conversion():
return True
return False
- def needs_free(self):
""" Check if any struct member needs some memory freeing."""
for m in self.members:
if m.needs_free():
return True
continue
return False
- def set_type_info(self, types): """ Helper function to set type information from the type registry. This is needed, because not all type data is available at time of
@@ -963,10 +1423,251 @@ class VkStruct(Sequence): m.set_type_info(type_info)
+class ConversionFunction(object):
- def __init__(self, array, dyn_array, direction, struct):
self.array = array
self.direction = direction
self.dyn_array = dyn_array
self.struct = struct
self.type = struct.name
self._set_name()
- def __eq__(self, other):
if self.name != other.name:
return False
return True
- def _generate_array_conversion_func(self):
""" Helper function for generating a conversion function for array structs. """
if self.direction == Direction.OUTPUT:
params = ["const {0}_host *in".format(self.type), "uint32_t count"]
return_type = self.type
else:
params = ["const {0} *in".format(self.type), "uint32_t count"]
return_type = "{0}_host".format(self.type)
# Generate function prototype.
body = "static inline {0} * {1}(".format(return_type, self.name)
body += ", ".join(p for p in params)
body += ")\n{\n"
body += " {0} *out;\n".format(return_type)
body += " unsigned int i;\n\n"
body += " if (!in) return NULL;\n\n"
body += " out = ({0} *)heap_alloc(count * sizeof(*out));\n".format(return_type)
body += " for (i = 0; i < count; i++)\n"
body += " {\n"
for m in self.struct:
# TODO: support copying of pNext extension structures!
# Luckily though no extension struct at this point needs conversion.
body += " " + m.copy("in[i].", "out[i].", self.direction)
body += " }\n\n"
body += " return out;\n"
body += "}\n\n"
return body
- def _generate_conversion_func(self):
""" Helper function for generating a conversion function for non-array structs. """
if self.direction == Direction.OUTPUT:
params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type)]
else:
params = ["const {0} *in".format(self.type), "{0}_host *out".format(self.type)]
body = "static inline void {0}(".format(self.name)
# Generate parameter list
body += ", ".join(p for p in params)
body += ")\n{\n"
body += " if (!in) return;\n\n"
if self.direction == Direction.INPUT and "pNext" in self.struct and self.struct.returnedonly:
# We are dealing with an input_output parameter. For these we only need to copy
# pNext and sType as the other fields are filled in by the host. We do potentially
# have to iterate over pNext and perform conversions based on switch(sType)!
# Luckily though no extension structs at this point need conversion.
# TODO: support copying of pNext extension structures!
body += " out->pNext = in->pNext;\n"
body += " out->sType = in->sType;\n"
else:
for m in self.struct:
# TODO: support copying of pNext extension structures!
body += " " + m.copy("in->", "out->", self.direction)
body += "}\n\n"
return body
- def _generate_static_array_conversion_func(self):
""" Helper function for generating a conversion function for array structs. """
if self.direction == Direction.OUTPUT:
params = ["const {0}_host *in".format(self.type), "{0} *out".format(self.type), "uint32_t count"]
return_type = self.type
else:
params = ["const {0} *in".format(self.type), "{0} *out_host".format(self.type), "uint32_t count"]
return_type = "{0}_host".format(self.type)
# Generate function prototype.
body = "static inline void {0}(".format(self.name)
body += ", ".join(p for p in params)
body += ")\n{\n"
body += " unsigned int i;\n\n"
body += " if (!in) return;\n\n"
body += " for (i = 0; i < count; i++)\n"
body += " {\n"
for m in self.struct:
# TODO: support copying of pNext extension structures!
body += " " + m.copy("in[i].", "out[i].", self.direction)
body += " }\n"
body += "}\n\n"
return body
- def _set_name(self):
if self.direction == Direction.INPUT:
if self.array:
name = "convert_{0}_static_array_win_to_host".format(self.type)
elif self.dyn_array:
name = "convert_{0}_array_win_to_host".format(self.type)
else:
name = "convert_{0}_win_to_host".format(self.type)
else: # Direction.OUTPUT
if self.array:
name = "convert_{0}_static_array_host_to_win".format(self.type)
elif self.dyn_array:
name = "convert_{0}_array_host_to_win".format(self.type)
else:
name = "convert_{0}_host_to_win".format(self.type)
self.name = name
- def definition(self):
if self.array:
return self._generate_static_array_conversion_func()
elif self.dyn_array:
return self._generate_array_conversion_func()
else:
return self._generate_conversion_func()
+class FreeFunction(object):
- def __init__(self, dyn_array, struct):
self.dyn_array = dyn_array
self.struct = struct
self.type = struct.name
if dyn_array:
self.name = "free_{0}_array".format(self.type)
else:
self.name = "free_{0}".format(self.type)
- def __eq__(self, other):
if self.name == other.name:
return True
return False
- def _generate_array_free_func(self):
""" Helper function for cleaning up temporary buffers required for array conversions. """
# Generate function prototype.
body = "static inline void {0}({1}_host *in, uint32_t count)\n{{\n".format(self.name, self.type)
# E.g. VkGraphicsPipelineCreateInfo_host needs freeing for pStages.
if self.struct.needs_free():
body += " unsigned int i;\n\n"
body += " if (!in) return;\n\n"
body += " for (i = 0; i < count; i++)\n"
body += " {\n"
for m in self.struct:
if m.needs_conversion() and m.is_dynamic_array():
if m.is_const():
# Add a cast to ignore const on conversion structs we allocated ourselves.
body += " free_{0}_array(({0}_host *)in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len)
else:
body += " free_{0}_array(in[i].{1}, in[i].{2});\n".format(m.type, m.name, m.dyn_array_len)
elif m.needs_conversion():
LOGGER.error("Unhandled conversion for {0}".format(m.name))
body += " }\n"
else:
body += " if (!in) return;\n\n"
body += " heap_free(in);\n"
body += "}\n\n"
return body
- def _generate_free_func(self):
# E.g. VkCommandBufferBeginInfo.pInheritanceInfo needs freeing.
if not self.struct.needs_free():
return ""
# Generate function prototype.
body = "static inline void {0}({1}_host *in)\n{{\n".format(self.name, self.type)
for m in self.struct:
if m.needs_conversion() and m.is_dynamic_array():
count = m.dyn_array_len if isinstance(m.dyn_array_len, int) else "in->{0}".format(m.dyn_array_len)
if m.is_const():
# Add a cast to ignore const on conversion structs we allocated ourselves.
body += " free_{0}_array(({0}_host *)in->{1}, {2});\n".format(m.type, m.name, count)
else:
body += " free_{0}_array(in->{1}, {2});\n".format(m.type, m.name, count)
body += "}\n\n"
return body
- def definition(self):
if self.dyn_array:
return self._generate_array_free_func()
else:
# Some structures need freeing too if they contain dynamic arrays.
# E.g. VkCommandBufferBeginInfo
return self._generate_free_func()
class VkGenerator(object): def __init__(self, registry): self.registry = registry
# Build a list conversion functions for struct conversion.
self.conversions = []
self.host_structs = []
for func in self.registry.funcs.values():
if not func.is_required():
continue
# Temporary filter.
if func.needs_stub():
continue
if not func.needs_conversion():
continue
conversions = func.get_conversions()
for conv in conversions:
# Pull in any conversions for vulkan_thunks.c. Driver conversions we
# handle manually in vulkan.c if needed.
if not func.is_driver_func():
# Append if we don't already have this conversion.
if not any(c == conv for c in self.conversions):
self.conversions.append(conv)
# Structs can be used in different ways by different conversions
# e.g. array vs non-array. Just make sure we pull in each struct once.
if not any(s.name == conv.struct.name for s in self.host_structs):
self.host_structs.append(conv.struct)
- def generate_thunks_c(self, f, prefix): f.write("/* Automatically generated from Vulkan vk.xml; DO NOT EDIT! */\n\n")
@@ -974,12 +1675,19 @@ class VkGenerator(object): f.write("#include "wine/port.h"\n\n")
f.write("#include \"wine/debug.h\"\n")
f.write("#include \"wine/heap.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")
# Generate any conversion helper functions.
f.write("#if defined(USE_STRUCT_CONVERSION)\n")
for conv in self.conversions:
f.write(conv.definition())
f.write("#endif /* USE_STRUCT_CONVERSION */\n\n")
# Create thunks for instance functions. # Global functions don't go through the thunks. for vk_func in self.registry.funcs.values():
@@ -997,7 +1705,11 @@ class VkGenerator(object): if not vk_func.needs_thunk(): continue
f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI"))
# Temporary filter.
if vk_func.needs_stub():
f.write("static " + vk_func.stub(prefix=prefix, call_conv="WINAPI"))
else:
f.write("static " + vk_func.thunk(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:
@@ -1031,6 +1743,11 @@ class VkGenerator(object): f.write("#ifndef __WINE_VULKAN_THUNKS_H\n") f.write("#define __WINE_VULKAN_THUNKS_H\n\n")
f.write("/* Perform vulkan struct conversion on 32-bit platforms. */\n")
f.write("#if (defined(__i386__) || defined(__arm__))\n")
f.write(" #define USE_STRUCT_CONVERSION\n")
f.write("#endif\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")
@@ -1043,6 +1760,10 @@ class VkGenerator(object): f.write("{0};\n".format(vk_func.prototype("WINAPI", prefix="wine_", postfix="DECLSPEC_HIDDEN"))) f.write("\n")
for struct in self.host_structs:
f.write(struct.definition(align=False, conv=True, postfix="_host"))
f.write("\n")
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:
@@ -1053,7 +1774,14 @@ class VkGenerator(object): LOGGER.debug("skipping {0} in vulkan_instance_funcs".format(vk_func.name)) continue
f.write(" {0};\n".format(vk_func.pfn(conv=False)))
if vk_func.needs_conversion():
f.write("#if defined(USE_STRUCT_CONVERSION)\n")
f.write(" {0};\n".format(vk_func.pfn(conv=True)))
f.write("#else\n")
f.write(" {0};\n".format(vk_func.pfn(conv=False)))
f.write("#endif\n")
else:
f.write(" {0};\n".format(vk_func.pfn(conv=False))) f.write("};\n\n") f.write("#define ALL_VK_INSTANCE_FUNCS() \\\n")
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 2e1b62d23c..daab898522 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -4,12 +4,177 @@ #include "wine/port.h"
#include "wine/debug.h" +#include "wine/heap.h" #include "wine/vulkan.h" #include "wine/vulkan_driver.h" #include "vulkan_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkImageFormatProperties_host_to_win(const VkImageFormatProperties_host *in, VkImageFormatProperties *out) +{
- if (!in) return;
- out->maxExtent = in->maxExtent;
- out->maxMipLevels = in->maxMipLevels;
- out->maxArrayLayers = in->maxArrayLayers;
- out->sampleCounts = in->sampleCounts;
- out->maxResourceSize = in->maxResourceSize;
+}
+static inline void convert_VkMemoryHeap_static_array_host_to_win(const VkMemoryHeap_host *in, VkMemoryHeap *out, uint32_t count) +{
- unsigned int i;
- if (!in) return;
- for (i = 0; i < count; i++)
- {
out[i].size = in[i].size;
out[i].flags = in[i].flags;
- }
+}
+static inline void convert_VkPhysicalDeviceMemoryProperties_host_to_win(const VkPhysicalDeviceMemoryProperties_host *in, VkPhysicalDeviceMemoryProperties *out) +{
- if (!in) return;
- out->memoryTypeCount = in->memoryTypeCount;
- memcpy(out->memoryTypes, in->memoryTypes, VK_MAX_MEMORY_TYPES * sizeof(VkMemoryType));
- out->memoryHeapCount = in->memoryHeapCount;
- convert_VkMemoryHeap_static_array_host_to_win(in->memoryHeaps, out->memoryHeaps, VK_MAX_MEMORY_HEAPS);
+}
+static inline void convert_VkPhysicalDeviceLimits_host_to_win(const VkPhysicalDeviceLimits_host *in, VkPhysicalDeviceLimits *out) +{
- if (!in) return;
- out->maxImageDimension1D = in->maxImageDimension1D;
- out->maxImageDimension2D = in->maxImageDimension2D;
- out->maxImageDimension3D = in->maxImageDimension3D;
- out->maxImageDimensionCube = in->maxImageDimensionCube;
- out->maxImageArrayLayers = in->maxImageArrayLayers;
- out->maxTexelBufferElements = in->maxTexelBufferElements;
- out->maxUniformBufferRange = in->maxUniformBufferRange;
- out->maxStorageBufferRange = in->maxStorageBufferRange;
- out->maxPushConstantsSize = in->maxPushConstantsSize;
- out->maxMemoryAllocationCount = in->maxMemoryAllocationCount;
- out->maxSamplerAllocationCount = in->maxSamplerAllocationCount;
- out->bufferImageGranularity = in->bufferImageGranularity;
- out->sparseAddressSpaceSize = in->sparseAddressSpaceSize;
- out->maxBoundDescriptorSets = in->maxBoundDescriptorSets;
- out->maxPerStageDescriptorSamplers = in->maxPerStageDescriptorSamplers;
- out->maxPerStageDescriptorUniformBuffers = in->maxPerStageDescriptorUniformBuffers;
- out->maxPerStageDescriptorStorageBuffers = in->maxPerStageDescriptorStorageBuffers;
- out->maxPerStageDescriptorSampledImages = in->maxPerStageDescriptorSampledImages;
- out->maxPerStageDescriptorStorageImages = in->maxPerStageDescriptorStorageImages;
- out->maxPerStageDescriptorInputAttachments = in->maxPerStageDescriptorInputAttachments;
- out->maxPerStageResources = in->maxPerStageResources;
- out->maxDescriptorSetSamplers = in->maxDescriptorSetSamplers;
- out->maxDescriptorSetUniformBuffers = in->maxDescriptorSetUniformBuffers;
- out->maxDescriptorSetUniformBuffersDynamic = in->maxDescriptorSetUniformBuffersDynamic;
- out->maxDescriptorSetStorageBuffers = in->maxDescriptorSetStorageBuffers;
- out->maxDescriptorSetStorageBuffersDynamic = in->maxDescriptorSetStorageBuffersDynamic;
- out->maxDescriptorSetSampledImages = in->maxDescriptorSetSampledImages;
- out->maxDescriptorSetStorageImages = in->maxDescriptorSetStorageImages;
- out->maxDescriptorSetInputAttachments = in->maxDescriptorSetInputAttachments;
- out->maxVertexInputAttributes = in->maxVertexInputAttributes;
- out->maxVertexInputBindings = in->maxVertexInputBindings;
- out->maxVertexInputAttributeOffset = in->maxVertexInputAttributeOffset;
- out->maxVertexInputBindingStride = in->maxVertexInputBindingStride;
- out->maxVertexOutputComponents = in->maxVertexOutputComponents;
- out->maxTessellationGenerationLevel = in->maxTessellationGenerationLevel;
- out->maxTessellationPatchSize = in->maxTessellationPatchSize;
- out->maxTessellationControlPerVertexInputComponents = in->maxTessellationControlPerVertexInputComponents;
- out->maxTessellationControlPerVertexOutputComponents = in->maxTessellationControlPerVertexOutputComponents;
- out->maxTessellationControlPerPatchOutputComponents = in->maxTessellationControlPerPatchOutputComponents;
- out->maxTessellationControlTotalOutputComponents = in->maxTessellationControlTotalOutputComponents;
- out->maxTessellationEvaluationInputComponents = in->maxTessellationEvaluationInputComponents;
- out->maxTessellationEvaluationOutputComponents = in->maxTessellationEvaluationOutputComponents;
- out->maxGeometryShaderInvocations = in->maxGeometryShaderInvocations;
- out->maxGeometryInputComponents = in->maxGeometryInputComponents;
- out->maxGeometryOutputComponents = in->maxGeometryOutputComponents;
- out->maxGeometryOutputVertices = in->maxGeometryOutputVertices;
- out->maxGeometryTotalOutputComponents = in->maxGeometryTotalOutputComponents;
- out->maxFragmentInputComponents = in->maxFragmentInputComponents;
- out->maxFragmentOutputAttachments = in->maxFragmentOutputAttachments;
- out->maxFragmentDualSrcAttachments = in->maxFragmentDualSrcAttachments;
- out->maxFragmentCombinedOutputResources = in->maxFragmentCombinedOutputResources;
- out->maxComputeSharedMemorySize = in->maxComputeSharedMemorySize;
- memcpy(out->maxComputeWorkGroupCount, in->maxComputeWorkGroupCount, 3 * sizeof(uint32_t));
- out->maxComputeWorkGroupInvocations = in->maxComputeWorkGroupInvocations;
- memcpy(out->maxComputeWorkGroupSize, in->maxComputeWorkGroupSize, 3 * sizeof(uint32_t));
- out->subPixelPrecisionBits = in->subPixelPrecisionBits;
- out->subTexelPrecisionBits = in->subTexelPrecisionBits;
- out->mipmapPrecisionBits = in->mipmapPrecisionBits;
- out->maxDrawIndexedIndexValue = in->maxDrawIndexedIndexValue;
- out->maxDrawIndirectCount = in->maxDrawIndirectCount;
- out->maxSamplerLodBias = in->maxSamplerLodBias;
- out->maxSamplerAnisotropy = in->maxSamplerAnisotropy;
- out->maxViewports = in->maxViewports;
- memcpy(out->maxViewportDimensions, in->maxViewportDimensions, 2 * sizeof(uint32_t));
- memcpy(out->viewportBoundsRange, in->viewportBoundsRange, 2 * sizeof(float));
- out->viewportSubPixelBits = in->viewportSubPixelBits;
- out->minMemoryMapAlignment = in->minMemoryMapAlignment;
- out->minTexelBufferOffsetAlignment = in->minTexelBufferOffsetAlignment;
- out->minUniformBufferOffsetAlignment = in->minUniformBufferOffsetAlignment;
- out->minStorageBufferOffsetAlignment = in->minStorageBufferOffsetAlignment;
- out->minTexelOffset = in->minTexelOffset;
- out->maxTexelOffset = in->maxTexelOffset;
- out->minTexelGatherOffset = in->minTexelGatherOffset;
- out->maxTexelGatherOffset = in->maxTexelGatherOffset;
- out->minInterpolationOffset = in->minInterpolationOffset;
- out->maxInterpolationOffset = in->maxInterpolationOffset;
- out->subPixelInterpolationOffsetBits = in->subPixelInterpolationOffsetBits;
- out->maxFramebufferWidth = in->maxFramebufferWidth;
- out->maxFramebufferHeight = in->maxFramebufferHeight;
- out->maxFramebufferLayers = in->maxFramebufferLayers;
- out->framebufferColorSampleCounts = in->framebufferColorSampleCounts;
- out->framebufferDepthSampleCounts = in->framebufferDepthSampleCounts;
- out->framebufferStencilSampleCounts = in->framebufferStencilSampleCounts;
- out->framebufferNoAttachmentsSampleCounts = in->framebufferNoAttachmentsSampleCounts;
- out->maxColorAttachments = in->maxColorAttachments;
- out->sampledImageColorSampleCounts = in->sampledImageColorSampleCounts;
- out->sampledImageIntegerSampleCounts = in->sampledImageIntegerSampleCounts;
- out->sampledImageDepthSampleCounts = in->sampledImageDepthSampleCounts;
- out->sampledImageStencilSampleCounts = in->sampledImageStencilSampleCounts;
- out->storageImageSampleCounts = in->storageImageSampleCounts;
- out->maxSampleMaskWords = in->maxSampleMaskWords;
- out->timestampComputeAndGraphics = in->timestampComputeAndGraphics;
- out->timestampPeriod = in->timestampPeriod;
- out->maxClipDistances = in->maxClipDistances;
- out->maxCullDistances = in->maxCullDistances;
- out->maxCombinedClipAndCullDistances = in->maxCombinedClipAndCullDistances;
- out->discreteQueuePriorities = in->discreteQueuePriorities;
- memcpy(out->pointSizeRange, in->pointSizeRange, 2 * sizeof(float));
- memcpy(out->lineWidthRange, in->lineWidthRange, 2 * sizeof(float));
- out->pointSizeGranularity = in->pointSizeGranularity;
- out->lineWidthGranularity = in->lineWidthGranularity;
- out->strictLines = in->strictLines;
- out->standardSampleLocations = in->standardSampleLocations;
- out->optimalBufferCopyOffsetAlignment = in->optimalBufferCopyOffsetAlignment;
- out->optimalBufferCopyRowPitchAlignment = in->optimalBufferCopyRowPitchAlignment;
- out->nonCoherentAtomSize = in->nonCoherentAtomSize;
+}
+static inline void convert_VkPhysicalDeviceProperties_host_to_win(const VkPhysicalDeviceProperties_host *in, VkPhysicalDeviceProperties *out) +{
- if (!in) return;
- out->apiVersion = in->apiVersion;
- out->driverVersion = in->driverVersion;
- out->vendorID = in->vendorID;
- out->deviceID = in->deviceID;
- out->deviceType = in->deviceType;
- memcpy(out->deviceName, in->deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE * sizeof(char));
- memcpy(out->pipelineCacheUUID, in->pipelineCacheUUID, VK_UUID_SIZE * sizeof(uint8_t));
- convert_VkPhysicalDeviceLimits_host_to_win(&in->limits, &out->limits);
- out->sparseProperties = in->sparseProperties;
+}
+#endif /* USE_STRUCT_CONVERSION */
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); @@ -18,44 +183,79 @@ static VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, cons
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;
- TRACE("%p, %p, %p\n", physicalDevice, pPropertyCount, pProperties);
- return physicalDevice->instance->funcs.p_vkEnumerateDeviceLayerProperties(physicalDevice->phys_dev, pPropertyCount, pProperties);
}
static void WINAPI wine_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) {
- FIXME("stub: %p, %p\n", physicalDevice, pFeatures);
- TRACE("%p, %p\n", physicalDevice, pFeatures);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceFeatures(physicalDevice->phys_dev, pFeatures);
}
static void WINAPI wine_vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
- FIXME("stub: %p, %d, %p\n", physicalDevice, format, pFormatProperties);
- TRACE("%p, %d, %p\n", physicalDevice, format, pFormatProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceFormatProperties(physicalDevice->phys_dev, 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;
+#if defined(USE_STRUCT_CONVERSION)
- VkResult result;
- VkImageFormatProperties_host pImageFormatProperties_host;
- TRACE("%p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
- result = physicalDevice->instance->funcs.p_vkGetPhysicalDeviceImageFormatProperties(physicalDevice->phys_dev, format, type, tiling, usage, flags, &pImageFormatProperties_host);
- convert_VkImageFormatProperties_host_to_win(&pImageFormatProperties_host, pImageFormatProperties);
- return result;
+#else
- TRACE("%p, %d, %d, %d, %#x, %#x, %p\n", physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
- return physicalDevice->instance->funcs.p_vkGetPhysicalDeviceImageFormatProperties(physicalDevice->phys_dev, format, type, tiling, usage, flags, pImageFormatProperties);
+#endif }
static void WINAPI wine_vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
- FIXME("stub: %p, %p\n", physicalDevice, pMemoryProperties);
+#if defined(USE_STRUCT_CONVERSION)
- VkPhysicalDeviceMemoryProperties_host pMemoryProperties_host;
- TRACE("%p, %p\n", physicalDevice, pMemoryProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(physicalDevice->phys_dev, &pMemoryProperties_host);
- convert_VkPhysicalDeviceMemoryProperties_host_to_win(&pMemoryProperties_host, pMemoryProperties);
+#else
- TRACE("%p, %p\n", physicalDevice, pMemoryProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(physicalDevice->phys_dev, pMemoryProperties);
+#endif }
static void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
- FIXME("stub: %p, %p\n", physicalDevice, pProperties);
+#if defined(USE_STRUCT_CONVERSION)
- VkPhysicalDeviceProperties_host pProperties_host;
- TRACE("%p, %p\n", physicalDevice, pProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties(physicalDevice->phys_dev, &pProperties_host);
- convert_VkPhysicalDeviceProperties_host_to_win(&pProperties_host, pProperties);
+#else
- TRACE("%p, %p\n", physicalDevice, pProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties(physicalDevice->phys_dev, pProperties);
+#endif }
static void WINAPI wine_vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties) {
- FIXME("stub: %p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
- TRACE("%p, %p, %p\n", physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice->phys_dev, 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);
- TRACE("%p, %d, %d, %d, %#x, %d, %p, %p\n", physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
- physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice->phys_dev, format, type, samples, usage, tiling, pPropertyCount, pProperties);
}
static const struct vulkan_func vk_instance_dispatch_table[] = diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index b8d2bbdb0f..b673ba502f 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -3,6 +3,11 @@ #ifndef __WINE_VULKAN_THUNKS_H #define __WINE_VULKAN_THUNKS_H
+/* Perform vulkan struct conversion on 32-bit platforms. */ +#if (defined(__i386__) || defined(__arm__))
- #define USE_STRUCT_CONVERSION
+#endif
Are you sure that the above code does the right thing on ARM? Is the structure conversion required on ARM? AFAIK ARM requires 8-byte alignment for 64-bit variables.
Let me take it out, it is likely indeed not be needed due to ARM having much more strict alignment needs.
Thanks for spotting the other little issues.
vkGetInstanceProcAddr can load both instance and device functions. A later to get introduced vkGetDeviceProcAddr only supports device functions, which is why there are 2 different function tables.
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com --- dlls/winevulkan/make_vulkan | 39 +- dlls/winevulkan/vulkan.c | 4 + dlls/winevulkan/vulkan_thunks.c | 791 ++++++++++++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_thunks.h | 1 + 4 files changed, 829 insertions(+), 6 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 2aec101723..fcacd1128f 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -357,6 +357,9 @@ class VkFunction(object): if self.params[0].type != "VkPhysicalDevice": return True
+ if self.is_device_func(): + return True + return False
def needs_thunk(self): @@ -498,6 +501,8 @@ class VkFunction(object): stub += " return VK_ERROR_OUT_OF_HOST_MEMORY;\n" elif self.type == "VkBool32": stub += " return VK_FALSE;\n" + elif self.type == "PFN_vkVoidFunction": + stub += " return NULL;\n"
stub += "}\n\n" return stub @@ -1688,7 +1693,7 @@ class VkGenerator(object): f.write(conv.definition()) f.write("#endif /* USE_STRUCT_CONVERSION */\n\n")
- # Create thunks for instance functions. + # Create thunks for instance and device functions. # Global functions don't go through the thunks. for vk_func in self.registry.funcs.values(): if not vk_func.is_required(): @@ -1697,11 +1702,6 @@ class VkGenerator(object): 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
@@ -1711,6 +1711,18 @@ class VkGenerator(object): else: f.write("static " + vk_func.thunk(prefix=prefix, call_conv="WINAPI"))
+ f.write("static const struct vulkan_func vk_device_dispatch_table[] =\n{\n") + for vk_func in self.registry.device_funcs: + if not vk_func.is_required(): + continue + + if not vk_func.needs_dispatch(): + LOGGER.debug("skipping {0} in device dispatch table".format(vk_func.name)) + 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(): @@ -1723,6 +1735,20 @@ class VkGenerator(object): f.write(" {{"{0}", &{1}{0}}},\n".format(vk_func.name, prefix)) f.write("};\n\n")
+ f.write("void *wine_vk_get_device_proc_addr(const char *name)\n") + f.write("{\n") + f.write(" unsigned int i;\n") + f.write(" for (i = 0; i < ARRAY_SIZE(vk_device_dispatch_table); i++)\n") + f.write(" {\n") + f.write(" if (strcmp(vk_device_dispatch_table[i].name, name) == 0)\n") + f.write(" {\n") + f.write(" TRACE("Found pName=%s in device table\n", name);\n") + f.write(" return vk_device_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") @@ -1749,6 +1775,7 @@ class VkGenerator(object): f.write("#endif\n\n")
f.write("/* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */\n") + f.write("void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN;\n") f.write("void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;\n\n")
# Generate prototypes for device and instance functions requiring a custom implementation. diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 913d14b972..12d56f5b51 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -310,6 +310,10 @@ static PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance, func = wine_vk_get_instance_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; + FIXME("Unsupported device or instance function: '%s'\n", debugstr_a(name)); return NULL; } diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index daab898522..0840f3c5c8 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -175,18 +175,565 @@ static inline void convert_VkPhysicalDeviceProperties_host_to_win(const VkPhysic
#endif /* USE_STRUCT_CONVERSION */
+static VkResult WINAPI wine_vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) +{ + FIXME("stub: %p, %p, %p\n", device, pAllocateInfo, pCommandBuffers); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) +{ + FIXME("stub: %p, %p, %p\n", device, pAllocateInfo, pDescriptorSets); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pAllocateInfo, pAllocator, pMemory); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) +{ + FIXME("stub: %p, %p\n", commandBuffer, pBeginInfo); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) +{ + FIXME("stub: %p, 0x%s, 0x%s, 0x%s\n", device, wine_dbgstr_longlong(buffer), wine_dbgstr_longlong(memory), wine_dbgstr_longlong(memoryOffset)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) +{ + FIXME("stub: %p, 0x%s, 0x%s, 0x%s\n", device, wine_dbgstr_longlong(image), wine_dbgstr_longlong(memory), wine_dbgstr_longlong(memoryOffset)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static void WINAPI wine_vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags) +{ + FIXME("stub: %p, 0x%s, %u, %#x\n", commandBuffer, wine_dbgstr_longlong(queryPool), query, flags); +} + +static void WINAPI wine_vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, VkSubpassContents contents) +{ + FIXME("stub: %p, %p, %d\n", commandBuffer, pRenderPassBegin, contents); +} + +static void WINAPI wine_vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) +{ + FIXME("stub: %p, %d, 0x%s, %u, %u, %p, %u, %p\n", commandBuffer, pipelineBindPoint, wine_dbgstr_longlong(layout), firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); +} + +static void WINAPI wine_vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) +{ + FIXME("stub: %p, 0x%s, 0x%s, %d\n", commandBuffer, wine_dbgstr_longlong(buffer), wine_dbgstr_longlong(offset), indexType); +} + +static void WINAPI wine_vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) +{ + FIXME("stub: %p, %d, 0x%s\n", commandBuffer, pipelineBindPoint, wine_dbgstr_longlong(pipeline)); +} + +static void WINAPI wine_vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) +{ + FIXME("stub: %p, %u, %u, %p, %p\n", commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); +} + +static void WINAPI wine_vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) +{ + FIXME("stub: %p, 0x%s, %d, 0x%s, %d, %u, %p, %d\n", commandBuffer, wine_dbgstr_longlong(srcImage), srcImageLayout, wine_dbgstr_longlong(dstImage), dstImageLayout, regionCount, pRegions, filter); +} + +static void WINAPI wine_vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment *pAttachments, uint32_t rectCount, const VkClearRect *pRects) +{ + FIXME("stub: %p, %u, %p, %u, %p\n", commandBuffer, attachmentCount, pAttachments, rectCount, pRects); +} + +static void WINAPI wine_vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue *pColor, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) +{ + FIXME("stub: %p, 0x%s, %d, %p, %u, %p\n", commandBuffer, wine_dbgstr_longlong(image), imageLayout, pColor, rangeCount, pRanges); +} + +static void WINAPI wine_vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange *pRanges) +{ + FIXME("stub: %p, 0x%s, %d, %p, %u, %p\n", commandBuffer, wine_dbgstr_longlong(image), imageLayout, pDepthStencil, rangeCount, pRanges); +} + +static void WINAPI wine_vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy *pRegions) +{ + FIXME("stub: %p, 0x%s, 0x%s, %u, %p\n", commandBuffer, wine_dbgstr_longlong(srcBuffer), wine_dbgstr_longlong(dstBuffer), regionCount, pRegions); +} + +static void WINAPI wine_vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *pRegions) +{ + FIXME("stub: %p, 0x%s, 0x%s, %d, %u, %p\n", commandBuffer, wine_dbgstr_longlong(srcBuffer), wine_dbgstr_longlong(dstImage), dstImageLayout, regionCount, pRegions); +} + +static void WINAPI wine_vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) +{ + FIXME("stub: %p, 0x%s, %d, 0x%s, %d, %u, %p\n", commandBuffer, wine_dbgstr_longlong(srcImage), srcImageLayout, wine_dbgstr_longlong(dstImage), dstImageLayout, regionCount, pRegions); +} + +static void WINAPI wine_vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) +{ + FIXME("stub: %p, 0x%s, %d, 0x%s, %u, %p\n", commandBuffer, wine_dbgstr_longlong(srcImage), srcImageLayout, wine_dbgstr_longlong(dstBuffer), regionCount, pRegions); +} + +static void WINAPI wine_vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) +{ + FIXME("stub: %p, 0x%s, %u, %u, 0x%s, 0x%s, 0x%s, %#x\n", commandBuffer, wine_dbgstr_longlong(queryPool), firstQuery, queryCount, wine_dbgstr_longlong(dstBuffer), wine_dbgstr_longlong(dstOffset), wine_dbgstr_longlong(stride), flags); +} + +static void WINAPI wine_vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) +{ + FIXME("stub: %p, %u, %u, %u\n", commandBuffer, groupCountX, groupCountY, groupCountZ); +} + +static void WINAPI wine_vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) +{ + FIXME("stub: %p, 0x%s, 0x%s\n", commandBuffer, wine_dbgstr_longlong(buffer), wine_dbgstr_longlong(offset)); +} + +static void WINAPI wine_vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) +{ + FIXME("stub: %p, %u, %u, %u, %u\n", commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); +} + +static void WINAPI wine_vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) +{ + FIXME("stub: %p, %u, %u, %u, %d, %u\n", commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); +} + +static void WINAPI wine_vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) +{ + FIXME("stub: %p, 0x%s, 0x%s, %u, %u\n", commandBuffer, wine_dbgstr_longlong(buffer), wine_dbgstr_longlong(offset), drawCount, stride); +} + +static void WINAPI wine_vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) +{ + FIXME("stub: %p, 0x%s, 0x%s, %u, %u\n", commandBuffer, wine_dbgstr_longlong(buffer), wine_dbgstr_longlong(offset), drawCount, stride); +} + +static void WINAPI wine_vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query) +{ + FIXME("stub: %p, 0x%s, %u\n", commandBuffer, wine_dbgstr_longlong(queryPool), query); +} + +static void WINAPI wine_vkCmdEndRenderPass(VkCommandBuffer commandBuffer) +{ + FIXME("stub: %p\n", commandBuffer); +} + +static void WINAPI wine_vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) +{ + FIXME("stub: %p, %u, %p\n", commandBuffer, commandBufferCount, pCommandBuffers); +} + +static void WINAPI wine_vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) +{ + FIXME("stub: %p, 0x%s, 0x%s, 0x%s, %u\n", commandBuffer, wine_dbgstr_longlong(dstBuffer), wine_dbgstr_longlong(dstOffset), wine_dbgstr_longlong(size), data); +} + +static void WINAPI wine_vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) +{ + FIXME("stub: %p, %d\n", commandBuffer, contents); +} + +static void WINAPI wine_vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) +{ + FIXME("stub: %p, %#x, %#x, %#x, %u, %p, %u, %p, %u, %p\n", commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); +} + +static void WINAPI wine_vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void *pValues) +{ + FIXME("stub: %p, 0x%s, %#x, %u, %u, %p\n", commandBuffer, wine_dbgstr_longlong(layout), stageFlags, offset, size, pValues); +} + +static void WINAPI wine_vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) +{ + FIXME("stub: %p, 0x%s, %#x\n", commandBuffer, wine_dbgstr_longlong(event), stageMask); +} + +static void WINAPI wine_vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) +{ + FIXME("stub: %p, 0x%s, %u, %u\n", commandBuffer, wine_dbgstr_longlong(queryPool), firstQuery, queryCount); +} + +static void WINAPI wine_vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) +{ + FIXME("stub: %p, 0x%s, %d, 0x%s, %d, %u, %p\n", commandBuffer, wine_dbgstr_longlong(srcImage), srcImageLayout, wine_dbgstr_longlong(dstImage), dstImageLayout, regionCount, pRegions); +} + +static void WINAPI wine_vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) +{ + FIXME("stub: %p, %p\n", commandBuffer, blendConstants); +} + +static void WINAPI wine_vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) +{ + FIXME("stub: %p, %f, %f, %f\n", commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor); +} + +static void WINAPI wine_vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) +{ + FIXME("stub: %p, %f, %f\n", commandBuffer, minDepthBounds, maxDepthBounds); +} + +static void WINAPI wine_vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) +{ + FIXME("stub: %p, 0x%s, %#x\n", commandBuffer, wine_dbgstr_longlong(event), stageMask); +} + +static void WINAPI wine_vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) +{ + FIXME("stub: %p, %f\n", commandBuffer, lineWidth); +} + +static void WINAPI wine_vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) +{ + FIXME("stub: %p, %u, %u, %p\n", commandBuffer, firstScissor, scissorCount, pScissors); +} + +static void WINAPI wine_vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) +{ + FIXME("stub: %p, %#x, %u\n", commandBuffer, faceMask, compareMask); +} + +static void WINAPI wine_vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) +{ + FIXME("stub: %p, %#x, %u\n", commandBuffer, faceMask, reference); +} + +static void WINAPI wine_vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) +{ + FIXME("stub: %p, %#x, %u\n", commandBuffer, faceMask, writeMask); +} + +static void WINAPI wine_vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) +{ + FIXME("stub: %p, %u, %u, %p\n", commandBuffer, firstViewport, viewportCount, pViewports); +} + +static void WINAPI wine_vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void *pData) +{ + FIXME("stub: %p, 0x%s, 0x%s, 0x%s, %p\n", commandBuffer, wine_dbgstr_longlong(dstBuffer), wine_dbgstr_longlong(dstOffset), wine_dbgstr_longlong(dataSize), pData); +} + +static void WINAPI wine_vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) +{ + FIXME("stub: %p, %u, %p, %#x, %#x, %u, %p, %u, %p, %u, %p\n", commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); +} + +static void WINAPI wine_vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query) +{ + FIXME("stub: %p, %d, 0x%s, %u\n", commandBuffer, pipelineStage, wine_dbgstr_longlong(queryPool), query); +} + +static VkResult WINAPI wine_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pBuffer); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBufferView *pView) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pView); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pCommandPool); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) +{ + FIXME("stub: %p, 0x%s, %u, %p, %p, %p\n", device, wine_dbgstr_longlong(pipelineCache), createInfoCount, pCreateInfos, pAllocator, pPipelines); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pDescriptorPool); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pSetLayout); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + 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 VkResult WINAPI wine_vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pEvent); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pFence); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pFramebuffer); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) +{ + FIXME("stub: %p, 0x%s, %u, %p, %p, %p\n", device, wine_dbgstr_longlong(pipelineCache), createInfoCount, pCreateInfos, pAllocator, pPipelines); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pImage); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImageView *pView) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pView); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkPipelineCache *pPipelineCache) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pPipelineCache); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pPipelineLayout); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pQueryPool); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pRenderPass); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pSampler); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pSemaphore); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) +{ + FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pShaderModule); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static void WINAPI wine_vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(buffer), pAllocator); +} + +static void WINAPI wine_vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(bufferView), pAllocator); +} + +static void WINAPI wine_vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(commandPool), pAllocator); +} + +static void WINAPI wine_vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(descriptorPool), pAllocator); +} + +static void WINAPI wine_vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(descriptorSetLayout), pAllocator); +} + +static void WINAPI wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, %p\n", device, pAllocator); +} + +static void WINAPI wine_vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(event), pAllocator); +} + +static void WINAPI wine_vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(fence), pAllocator); +} + +static void WINAPI wine_vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(framebuffer), pAllocator); +} + +static void WINAPI wine_vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(image), pAllocator); +} + +static void WINAPI wine_vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(imageView), pAllocator); +} + +static void WINAPI wine_vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(pipeline), pAllocator); +} + +static void WINAPI wine_vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(pipelineCache), pAllocator); +} + +static void WINAPI wine_vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(pipelineLayout), pAllocator); +} + +static void WINAPI wine_vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(queryPool), pAllocator); +} + +static void WINAPI wine_vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(renderPass), pAllocator); +} + +static void WINAPI wine_vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(sampler), pAllocator); +} + +static void WINAPI wine_vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(semaphore), pAllocator); +} + +static void WINAPI wine_vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(shaderModule), pAllocator); +} + +static VkResult WINAPI wine_vkDeviceWaitIdle(VkDevice device) +{ + FIXME("stub: %p\n", device); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkEndCommandBuffer(VkCommandBuffer commandBuffer) +{ + FIXME("stub: %p\n", commandBuffer); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + static VkResult WINAPI wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties) { TRACE("%p, %p, %p\n", physicalDevice, pPropertyCount, pProperties); return physicalDevice->instance->funcs.p_vkEnumerateDeviceLayerProperties(physicalDevice->phys_dev, pPropertyCount, pProperties); }
+static VkResult WINAPI wine_vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) +{ + FIXME("stub: %p, %u, %p\n", device, memoryRangeCount, pMemoryRanges); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static void WINAPI wine_vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) +{ + FIXME("stub: %p, 0x%s, %u, %p\n", device, wine_dbgstr_longlong(commandPool), commandBufferCount, pCommandBuffers); +} + +static VkResult WINAPI wine_vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets) +{ + FIXME("stub: %p, 0x%s, %u, %p\n", device, wine_dbgstr_longlong(descriptorPool), descriptorSetCount, pDescriptorSets); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static void WINAPI wine_vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(memory), pAllocator); +} + +static void WINAPI wine_vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(buffer), pMemoryRequirements); +} + +static void WINAPI wine_vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize *pCommittedMemoryInBytes) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(memory), pCommittedMemoryInBytes); +} + +static PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *pName) +{ + FIXME("stub: %p, %p\n", device, pName); + return NULL; +} + +static void WINAPI wine_vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) +{ + FIXME("stub: %p, %u, %u, %p\n", device, queueFamilyIndex, queueIndex, pQueue); +} + +static VkResult WINAPI wine_vkGetEventStatus(VkDevice device, VkEvent event) +{ + FIXME("stub: %p, 0x%s\n", device, wine_dbgstr_longlong(event)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkGetFenceStatus(VkDevice device, VkFence fence) +{ + FIXME("stub: %p, 0x%s\n", device, wine_dbgstr_longlong(fence)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static void WINAPI wine_vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(image), pMemoryRequirements); +} + +static void WINAPI wine_vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t *pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements *pSparseMemoryRequirements) +{ + FIXME("stub: %p, 0x%s, %p, %p\n", device, wine_dbgstr_longlong(image), pSparseMemoryRequirementCount, pSparseMemoryRequirements); +} + +static void WINAPI wine_vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) +{ + FIXME("stub: %p, 0x%s, %p, %p\n", device, wine_dbgstr_longlong(image), pSubresource, pLayout); +} + static void WINAPI wine_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) { TRACE("%p, %p\n", physicalDevice, pFeatures); @@ -258,6 +805,236 @@ static void WINAPI wine_vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysica physicalDevice->instance->funcs.p_vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice->phys_dev, format, type, samples, usage, tiling, pPropertyCount, pProperties); }
+static VkResult WINAPI wine_vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData) +{ + FIXME("stub: %p, 0x%s, %p, %p\n", device, wine_dbgstr_longlong(pipelineCache), pDataSize, pData); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void *pData, VkDeviceSize stride, VkQueryResultFlags flags) +{ + FIXME("stub: %p, 0x%s, %u, %u, 0x%s, %p, 0x%s, %#x\n", device, wine_dbgstr_longlong(queryPool), firstQuery, queryCount, wine_dbgstr_longlong(dataSize), pData, wine_dbgstr_longlong(stride), flags); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static void WINAPI wine_vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D *pGranularity) +{ + FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(renderPass), pGranularity); +} + +static VkResult WINAPI wine_vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) +{ + FIXME("stub: %p, %u, %p\n", device, memoryRangeCount, pMemoryRanges); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) +{ + FIXME("stub: %p, 0x%s, 0x%s, 0x%s, %#x, %p\n", device, wine_dbgstr_longlong(memory), wine_dbgstr_longlong(offset), wine_dbgstr_longlong(size), flags, ppData); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches) +{ + FIXME("stub: %p, 0x%s, %u, %p\n", device, wine_dbgstr_longlong(dstCache), srcCacheCount, pSrcCaches); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) +{ + FIXME("stub: %p, %u, %p, 0x%s\n", queue, bindInfoCount, pBindInfo, wine_dbgstr_longlong(fence)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) +{ + FIXME("stub: %p, %u, %p, 0x%s\n", queue, submitCount, pSubmits, wine_dbgstr_longlong(fence)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkQueueWaitIdle(VkQueue queue) +{ + FIXME("stub: %p\n", queue); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) +{ + FIXME("stub: %p, %#x\n", commandBuffer, flags); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) +{ + FIXME("stub: %p, 0x%s, %#x\n", device, wine_dbgstr_longlong(commandPool), flags); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) +{ + FIXME("stub: %p, 0x%s, %#x\n", device, wine_dbgstr_longlong(descriptorPool), flags); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkResetEvent(VkDevice device, VkEvent event) +{ + FIXME("stub: %p, 0x%s\n", device, wine_dbgstr_longlong(event)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) +{ + FIXME("stub: %p, %u, %p\n", device, fenceCount, pFences); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static VkResult WINAPI wine_vkSetEvent(VkDevice device, VkEvent event) +{ + FIXME("stub: %p, 0x%s\n", device, wine_dbgstr_longlong(event)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static void WINAPI wine_vkUnmapMemory(VkDevice device, VkDeviceMemory memory) +{ + FIXME("stub: %p, 0x%s\n", device, wine_dbgstr_longlong(memory)); +} + +static void WINAPI wine_vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) +{ + FIXME("stub: %p, %u, %p, %u, %p\n", device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies); +} + +static VkResult WINAPI wine_vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) +{ + FIXME("stub: %p, %u, %p, %u, 0x%s\n", device, fenceCount, pFences, waitAll, wine_dbgstr_longlong(timeout)); + return VK_ERROR_OUT_OF_HOST_MEMORY; +} + +static const struct vulkan_func vk_device_dispatch_table[] = +{ + {"vkAllocateCommandBuffers", &wine_vkAllocateCommandBuffers}, + {"vkAllocateDescriptorSets", &wine_vkAllocateDescriptorSets}, + {"vkAllocateMemory", &wine_vkAllocateMemory}, + {"vkBeginCommandBuffer", &wine_vkBeginCommandBuffer}, + {"vkBindBufferMemory", &wine_vkBindBufferMemory}, + {"vkBindImageMemory", &wine_vkBindImageMemory}, + {"vkCmdBeginQuery", &wine_vkCmdBeginQuery}, + {"vkCmdBeginRenderPass", &wine_vkCmdBeginRenderPass}, + {"vkCmdBindDescriptorSets", &wine_vkCmdBindDescriptorSets}, + {"vkCmdBindIndexBuffer", &wine_vkCmdBindIndexBuffer}, + {"vkCmdBindPipeline", &wine_vkCmdBindPipeline}, + {"vkCmdBindVertexBuffers", &wine_vkCmdBindVertexBuffers}, + {"vkCmdBlitImage", &wine_vkCmdBlitImage}, + {"vkCmdClearAttachments", &wine_vkCmdClearAttachments}, + {"vkCmdClearColorImage", &wine_vkCmdClearColorImage}, + {"vkCmdClearDepthStencilImage", &wine_vkCmdClearDepthStencilImage}, + {"vkCmdCopyBuffer", &wine_vkCmdCopyBuffer}, + {"vkCmdCopyBufferToImage", &wine_vkCmdCopyBufferToImage}, + {"vkCmdCopyImage", &wine_vkCmdCopyImage}, + {"vkCmdCopyImageToBuffer", &wine_vkCmdCopyImageToBuffer}, + {"vkCmdCopyQueryPoolResults", &wine_vkCmdCopyQueryPoolResults}, + {"vkCmdDispatch", &wine_vkCmdDispatch}, + {"vkCmdDispatchIndirect", &wine_vkCmdDispatchIndirect}, + {"vkCmdDraw", &wine_vkCmdDraw}, + {"vkCmdDrawIndexed", &wine_vkCmdDrawIndexed}, + {"vkCmdDrawIndexedIndirect", &wine_vkCmdDrawIndexedIndirect}, + {"vkCmdDrawIndirect", &wine_vkCmdDrawIndirect}, + {"vkCmdEndQuery", &wine_vkCmdEndQuery}, + {"vkCmdEndRenderPass", &wine_vkCmdEndRenderPass}, + {"vkCmdExecuteCommands", &wine_vkCmdExecuteCommands}, + {"vkCmdFillBuffer", &wine_vkCmdFillBuffer}, + {"vkCmdNextSubpass", &wine_vkCmdNextSubpass}, + {"vkCmdPipelineBarrier", &wine_vkCmdPipelineBarrier}, + {"vkCmdPushConstants", &wine_vkCmdPushConstants}, + {"vkCmdResetEvent", &wine_vkCmdResetEvent}, + {"vkCmdResetQueryPool", &wine_vkCmdResetQueryPool}, + {"vkCmdResolveImage", &wine_vkCmdResolveImage}, + {"vkCmdSetBlendConstants", &wine_vkCmdSetBlendConstants}, + {"vkCmdSetDepthBias", &wine_vkCmdSetDepthBias}, + {"vkCmdSetDepthBounds", &wine_vkCmdSetDepthBounds}, + {"vkCmdSetEvent", &wine_vkCmdSetEvent}, + {"vkCmdSetLineWidth", &wine_vkCmdSetLineWidth}, + {"vkCmdSetScissor", &wine_vkCmdSetScissor}, + {"vkCmdSetStencilCompareMask", &wine_vkCmdSetStencilCompareMask}, + {"vkCmdSetStencilReference", &wine_vkCmdSetStencilReference}, + {"vkCmdSetStencilWriteMask", &wine_vkCmdSetStencilWriteMask}, + {"vkCmdSetViewport", &wine_vkCmdSetViewport}, + {"vkCmdUpdateBuffer", &wine_vkCmdUpdateBuffer}, + {"vkCmdWaitEvents", &wine_vkCmdWaitEvents}, + {"vkCmdWriteTimestamp", &wine_vkCmdWriteTimestamp}, + {"vkCreateBuffer", &wine_vkCreateBuffer}, + {"vkCreateBufferView", &wine_vkCreateBufferView}, + {"vkCreateCommandPool", &wine_vkCreateCommandPool}, + {"vkCreateComputePipelines", &wine_vkCreateComputePipelines}, + {"vkCreateDescriptorPool", &wine_vkCreateDescriptorPool}, + {"vkCreateDescriptorSetLayout", &wine_vkCreateDescriptorSetLayout}, + {"vkCreateEvent", &wine_vkCreateEvent}, + {"vkCreateFence", &wine_vkCreateFence}, + {"vkCreateFramebuffer", &wine_vkCreateFramebuffer}, + {"vkCreateGraphicsPipelines", &wine_vkCreateGraphicsPipelines}, + {"vkCreateImage", &wine_vkCreateImage}, + {"vkCreateImageView", &wine_vkCreateImageView}, + {"vkCreatePipelineCache", &wine_vkCreatePipelineCache}, + {"vkCreatePipelineLayout", &wine_vkCreatePipelineLayout}, + {"vkCreateQueryPool", &wine_vkCreateQueryPool}, + {"vkCreateRenderPass", &wine_vkCreateRenderPass}, + {"vkCreateSampler", &wine_vkCreateSampler}, + {"vkCreateSemaphore", &wine_vkCreateSemaphore}, + {"vkCreateShaderModule", &wine_vkCreateShaderModule}, + {"vkDestroyBuffer", &wine_vkDestroyBuffer}, + {"vkDestroyBufferView", &wine_vkDestroyBufferView}, + {"vkDestroyCommandPool", &wine_vkDestroyCommandPool}, + {"vkDestroyDescriptorPool", &wine_vkDestroyDescriptorPool}, + {"vkDestroyDescriptorSetLayout", &wine_vkDestroyDescriptorSetLayout}, + {"vkDestroyDevice", &wine_vkDestroyDevice}, + {"vkDestroyEvent", &wine_vkDestroyEvent}, + {"vkDestroyFence", &wine_vkDestroyFence}, + {"vkDestroyFramebuffer", &wine_vkDestroyFramebuffer}, + {"vkDestroyImage", &wine_vkDestroyImage}, + {"vkDestroyImageView", &wine_vkDestroyImageView}, + {"vkDestroyPipeline", &wine_vkDestroyPipeline}, + {"vkDestroyPipelineCache", &wine_vkDestroyPipelineCache}, + {"vkDestroyPipelineLayout", &wine_vkDestroyPipelineLayout}, + {"vkDestroyQueryPool", &wine_vkDestroyQueryPool}, + {"vkDestroyRenderPass", &wine_vkDestroyRenderPass}, + {"vkDestroySampler", &wine_vkDestroySampler}, + {"vkDestroySemaphore", &wine_vkDestroySemaphore}, + {"vkDestroyShaderModule", &wine_vkDestroyShaderModule}, + {"vkDeviceWaitIdle", &wine_vkDeviceWaitIdle}, + {"vkEndCommandBuffer", &wine_vkEndCommandBuffer}, + {"vkFlushMappedMemoryRanges", &wine_vkFlushMappedMemoryRanges}, + {"vkFreeCommandBuffers", &wine_vkFreeCommandBuffers}, + {"vkFreeDescriptorSets", &wine_vkFreeDescriptorSets}, + {"vkFreeMemory", &wine_vkFreeMemory}, + {"vkGetBufferMemoryRequirements", &wine_vkGetBufferMemoryRequirements}, + {"vkGetDeviceMemoryCommitment", &wine_vkGetDeviceMemoryCommitment}, + {"vkGetDeviceProcAddr", &wine_vkGetDeviceProcAddr}, + {"vkGetDeviceQueue", &wine_vkGetDeviceQueue}, + {"vkGetEventStatus", &wine_vkGetEventStatus}, + {"vkGetFenceStatus", &wine_vkGetFenceStatus}, + {"vkGetImageMemoryRequirements", &wine_vkGetImageMemoryRequirements}, + {"vkGetImageSparseMemoryRequirements", &wine_vkGetImageSparseMemoryRequirements}, + {"vkGetImageSubresourceLayout", &wine_vkGetImageSubresourceLayout}, + {"vkGetPipelineCacheData", &wine_vkGetPipelineCacheData}, + {"vkGetQueryPoolResults", &wine_vkGetQueryPoolResults}, + {"vkGetRenderAreaGranularity", &wine_vkGetRenderAreaGranularity}, + {"vkInvalidateMappedMemoryRanges", &wine_vkInvalidateMappedMemoryRanges}, + {"vkMapMemory", &wine_vkMapMemory}, + {"vkMergePipelineCaches", &wine_vkMergePipelineCaches}, + {"vkQueueBindSparse", &wine_vkQueueBindSparse}, + {"vkQueueSubmit", &wine_vkQueueSubmit}, + {"vkQueueWaitIdle", &wine_vkQueueWaitIdle}, + {"vkResetCommandBuffer", &wine_vkResetCommandBuffer}, + {"vkResetCommandPool", &wine_vkResetCommandPool}, + {"vkResetDescriptorPool", &wine_vkResetDescriptorPool}, + {"vkResetEvent", &wine_vkResetEvent}, + {"vkResetFences", &wine_vkResetFences}, + {"vkSetEvent", &wine_vkSetEvent}, + {"vkUnmapMemory", &wine_vkUnmapMemory}, + {"vkUpdateDescriptorSets", &wine_vkUpdateDescriptorSets}, + {"vkWaitForFences", &wine_vkWaitForFences}, +}; + static const struct vulkan_func vk_instance_dispatch_table[] = { {"vkCreateDevice", &wine_vkCreateDevice}, @@ -274,6 +1051,20 @@ static const struct vulkan_func vk_instance_dispatch_table[] = {"vkGetPhysicalDeviceSparseImageFormatProperties", &wine_vkGetPhysicalDeviceSparseImageFormatProperties}, };
+void *wine_vk_get_device_proc_addr(const char *name) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(vk_device_dispatch_table); i++) + { + if (strcmp(vk_device_dispatch_table[i].name, name) == 0) + { + TRACE("Found pName=%s in device table\n", name); + return vk_device_dispatch_table[i].func; + } + } + return NULL; +} + void *wine_vk_get_instance_proc_addr(const char *name) { unsigned int i; diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index b673ba502f..17916fceae 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -9,6 +9,7 @@ #endif
/* For use by vk_icdGetInstanceProcAddr / vkGetInstanceProcAddr */ +void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
/* Functions for which we have custom implementations outside of the thunks. */
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com --- dlls/winevulkan/make_vulkan | 39 +++++- dlls/winevulkan/vulkan.c | 68 +++++++++++ dlls/winevulkan/vulkan_private.h | 8 ++ dlls/winevulkan/vulkan_thunks.c | 6 - dlls/winevulkan/vulkan_thunks.h | 248 +++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/vulkan.c | 9 ++ include/wine/vulkan_driver.h | 3 +- 7 files changed, 370 insertions(+), 11 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index fcacd1128f..698d496a96 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -71,7 +71,7 @@ WINE_VULKAN_THUNKS_H = "vulkan_thunks.h" # Functions part of our winevulkan graphics driver interface. # DRIVER_VERSION should be bumped on any change to driver interface # in FUNCTION_OVERRIDES -DRIVER_VERSION = 1 +DRIVER_VERSION = 2
# Table of functions for which we have a special implementation. # This are regular device / instance functions for which we need @@ -88,9 +88,13 @@ FUNCTION_OVERRIDES = { "vkGetInstanceProcAddr": {"dispatch" : False, "driver" : True, "thunk" : False},
# Instance functions + "vkCreateDevice" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkDestroyInstance" : {"dispatch" : True, "driver" : True, "thunk" : False }, "vkEnumerateDeviceExtensionProperties" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkEnumeratePhysicalDevices" : {"dispatch" : True, "driver" : False, "thunk" : False}, + + # Device functions + "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : True}, }
@@ -351,9 +355,6 @@ class VkFunction(object):
def needs_stub(self): """ Temporary function to limit script hacks until more code is implemented. """ - if self.name == "vkCreateDevice": - return True - if self.params[0].type != "VkPhysicalDevice": return True
@@ -1791,6 +1792,19 @@ class VkGenerator(object): f.write(struct.definition(align=False, conv=True, postfix="_host")) f.write("\n")
+ f.write("/* For use by vkDevice and children */\n") + f.write("struct vulkan_device_funcs\n{\n") + for vk_func in self.registry.device_funcs: + if not vk_func.is_required(): + continue + + if not vk_func.needs_dispatch() or vk_func.is_driver_func(): + LOGGER.debug("skipping {0} in vulkan_device_funcs".format(vk_func.name)) + continue + + f.write(" {0};\n".format(vk_func.pfn(conv=False))) + f.write("};\n\n") + 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: @@ -1811,6 +1825,23 @@ class VkGenerator(object): f.write(" {0};\n".format(vk_func.pfn(conv=False))) f.write("};\n\n")
+ f.write("#define ALL_VK_DEVICE_FUNCS() \\n") + first = True + for vk_func in self.registry.device_funcs: + if not vk_func.is_required(): + continue + + if not vk_func.needs_dispatch() or vk_func.is_driver_func(): + LOGGER.debug("skipping {0} in ALL_VK_DEVICE_FUNCS".format(vk_func.name)) + continue + + if first: + f.write(" USE_VK_FUNC({0})".format(vk_func.name)) + first = False + else: + f.write(" \\n USE_VK_FUNC({0})".format(vk_func.name)) + f.write("\n\n") + f.write("#define ALL_VK_INSTANCE_FUNCS() \\n") first = True for vk_func in self.registry.instance_funcs: diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 12d56f5b51..d5fe25f36a 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -42,6 +42,22 @@ static void *wine_vk_get_global_proc_addr(const char *name);
static const struct vulkan_funcs *vk_funcs = NULL;
+/* Helper function used for freeing a device structure. This function supports full + * and partial object cleanups and can thus be used vkCreateDevice failures. + */ +static void wine_vk_device_free(struct VkDevice_T *device) +{ + if (!device) + return; + + if (device->device && device->funcs.p_vkDestroyDevice) + { + device->funcs.p_vkDestroyDevice(device->device, NULL /* pAllocator */); + } + + heap_free(device); +} + static BOOL wine_vk_init(void) { HDC hdc = GetDC(0); @@ -146,6 +162,58 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) heap_free(instance); }
+VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev, + const VkDeviceCreateInfo *create_info, + const VkAllocationCallbacks *allocator, VkDevice *device) +{ + struct VkDevice_T *object = NULL; + VkResult res; + + TRACE("%p %p %p %p\n", phys_dev, create_info, allocator, device); + + if (allocator) + { + FIXME("Support for allocation callbacks not implemented yet\n"); + } + + object = heap_alloc_zero(sizeof(*object)); + if (!object) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE; + + /* At least for now we can directly pass create_info through. All extensions we report + * should be compatible. In addition the loader is supposed to santize values e.g. layers. + */ + res = phys_dev->instance->funcs.p_vkCreateDevice(phys_dev->phys_dev, + create_info, NULL /* allocator */, &object->device); + if (res != VK_SUCCESS) + { + ERR("Failed to create device\n"); + goto err; + } + + object->phys_dev = phys_dev; + + /* Just load all function pointers we are aware off. The loader takes care of filtering. + * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons + * as functions pass through fewer dispatch tables within the loader. + */ +#define USE_VK_FUNC(name) \ + object->funcs.p_##name = (void*)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \ + if (object->funcs.p_##name == NULL) \ + TRACE("Not found %s\n", #name); + ALL_VK_DEVICE_FUNCS() +#undef USE_VK_FUNC + + *device = object; + return VK_SUCCESS; + +err: + wine_vk_device_free(object); + return res; +} + static VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkInstance *instance) { diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 8ef4b924a2..897c1e1418 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -48,6 +48,14 @@ struct wine_vk_base UINT_PTR loader_magic; };
+struct VkDevice_T +{ + struct wine_vk_base base; + struct vulkan_device_funcs funcs; + struct VkPhysicalDevice_T *phys_dev; /* parent */ + VkDevice device; /* native device */ +}; + struct VkInstance_T { struct wine_vk_base base; diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 0840f3c5c8..99095c60f9 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -467,12 +467,6 @@ static VkResult WINAPI wine_vkCreateDescriptorSetLayout(VkDevice device, const V return VK_ERROR_OUT_OF_HOST_MEMORY; }
-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 VkResult WINAPI wine_vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pEvent); diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 17916fceae..49a88968a2 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -13,6 +13,7 @@ void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
/* Functions for which we have custom implementations outside of the thunks. */ +VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) DECLSPEC_HIDDEN; void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN; @@ -164,6 +165,131 @@ typedef struct VkPhysicalDeviceProperties_host } VkPhysicalDeviceProperties_host;
+/* For use by vkDevice and children */ +struct vulkan_device_funcs +{ + VkResult (*p_vkAllocateCommandBuffers)(VkDevice, const VkCommandBufferAllocateInfo *, VkCommandBuffer *); + VkResult (*p_vkAllocateDescriptorSets)(VkDevice, const VkDescriptorSetAllocateInfo *, VkDescriptorSet *); + VkResult (*p_vkAllocateMemory)(VkDevice, const VkMemoryAllocateInfo *, const VkAllocationCallbacks *, VkDeviceMemory *); + VkResult (*p_vkBeginCommandBuffer)(VkCommandBuffer, const VkCommandBufferBeginInfo *); + VkResult (*p_vkBindBufferMemory)(VkDevice, VkBuffer, VkDeviceMemory, VkDeviceSize); + VkResult (*p_vkBindImageMemory)(VkDevice, VkImage, VkDeviceMemory, VkDeviceSize); + void (*p_vkCmdBeginQuery)(VkCommandBuffer, VkQueryPool, uint32_t, VkQueryControlFlags); + void (*p_vkCmdBeginRenderPass)(VkCommandBuffer, const VkRenderPassBeginInfo *, VkSubpassContents); + void (*p_vkCmdBindDescriptorSets)(VkCommandBuffer, VkPipelineBindPoint, VkPipelineLayout, uint32_t, uint32_t, const VkDescriptorSet *, uint32_t, const uint32_t *); + void (*p_vkCmdBindIndexBuffer)(VkCommandBuffer, VkBuffer, VkDeviceSize, VkIndexType); + void (*p_vkCmdBindPipeline)(VkCommandBuffer, VkPipelineBindPoint, VkPipeline); + void (*p_vkCmdBindVertexBuffers)(VkCommandBuffer, uint32_t, uint32_t, const VkBuffer *, const VkDeviceSize *); + void (*p_vkCmdBlitImage)(VkCommandBuffer, VkImage, VkImageLayout, VkImage, VkImageLayout, uint32_t, const VkImageBlit *, VkFilter); + void (*p_vkCmdClearAttachments)(VkCommandBuffer, uint32_t, const VkClearAttachment *, uint32_t, const VkClearRect *); + void (*p_vkCmdClearColorImage)(VkCommandBuffer, VkImage, VkImageLayout, const VkClearColorValue *, uint32_t, const VkImageSubresourceRange *); + void (*p_vkCmdClearDepthStencilImage)(VkCommandBuffer, VkImage, VkImageLayout, const VkClearDepthStencilValue *, uint32_t, const VkImageSubresourceRange *); + void (*p_vkCmdCopyBuffer)(VkCommandBuffer, VkBuffer, VkBuffer, uint32_t, const VkBufferCopy *); + void (*p_vkCmdCopyBufferToImage)(VkCommandBuffer, VkBuffer, VkImage, VkImageLayout, uint32_t, const VkBufferImageCopy *); + void (*p_vkCmdCopyImage)(VkCommandBuffer, VkImage, VkImageLayout, VkImage, VkImageLayout, uint32_t, const VkImageCopy *); + void (*p_vkCmdCopyImageToBuffer)(VkCommandBuffer, VkImage, VkImageLayout, VkBuffer, uint32_t, const VkBufferImageCopy *); + void (*p_vkCmdCopyQueryPoolResults)(VkCommandBuffer, VkQueryPool, uint32_t, uint32_t, VkBuffer, VkDeviceSize, VkDeviceSize, VkQueryResultFlags); + void (*p_vkCmdDispatch)(VkCommandBuffer, uint32_t, uint32_t, uint32_t); + void (*p_vkCmdDispatchIndirect)(VkCommandBuffer, VkBuffer, VkDeviceSize); + void (*p_vkCmdDraw)(VkCommandBuffer, uint32_t, uint32_t, uint32_t, uint32_t); + void (*p_vkCmdDrawIndexed)(VkCommandBuffer, uint32_t, uint32_t, uint32_t, int32_t, uint32_t); + void (*p_vkCmdDrawIndexedIndirect)(VkCommandBuffer, VkBuffer, VkDeviceSize, uint32_t, uint32_t); + void (*p_vkCmdDrawIndirect)(VkCommandBuffer, VkBuffer, VkDeviceSize, uint32_t, uint32_t); + void (*p_vkCmdEndQuery)(VkCommandBuffer, VkQueryPool, uint32_t); + void (*p_vkCmdEndRenderPass)(VkCommandBuffer); + void (*p_vkCmdExecuteCommands)(VkCommandBuffer, uint32_t, const VkCommandBuffer *); + void (*p_vkCmdFillBuffer)(VkCommandBuffer, VkBuffer, VkDeviceSize, VkDeviceSize, uint32_t); + void (*p_vkCmdNextSubpass)(VkCommandBuffer, VkSubpassContents); + void (*p_vkCmdPipelineBarrier)(VkCommandBuffer, VkPipelineStageFlags, VkPipelineStageFlags, VkDependencyFlags, uint32_t, const VkMemoryBarrier *, uint32_t, const VkBufferMemoryBarrier *, uint32_t, const VkImageMemoryBarrier *); + void (*p_vkCmdPushConstants)(VkCommandBuffer, VkPipelineLayout, VkShaderStageFlags, uint32_t, uint32_t, const void *); + void (*p_vkCmdResetEvent)(VkCommandBuffer, VkEvent, VkPipelineStageFlags); + void (*p_vkCmdResetQueryPool)(VkCommandBuffer, VkQueryPool, uint32_t, uint32_t); + void (*p_vkCmdResolveImage)(VkCommandBuffer, VkImage, VkImageLayout, VkImage, VkImageLayout, uint32_t, const VkImageResolve *); + void (*p_vkCmdSetBlendConstants)(VkCommandBuffer, const float[4]); + void (*p_vkCmdSetDepthBias)(VkCommandBuffer, float, float, float); + void (*p_vkCmdSetDepthBounds)(VkCommandBuffer, float, float); + void (*p_vkCmdSetEvent)(VkCommandBuffer, VkEvent, VkPipelineStageFlags); + void (*p_vkCmdSetLineWidth)(VkCommandBuffer, float); + void (*p_vkCmdSetScissor)(VkCommandBuffer, uint32_t, uint32_t, const VkRect2D *); + void (*p_vkCmdSetStencilCompareMask)(VkCommandBuffer, VkStencilFaceFlags, uint32_t); + void (*p_vkCmdSetStencilReference)(VkCommandBuffer, VkStencilFaceFlags, uint32_t); + void (*p_vkCmdSetStencilWriteMask)(VkCommandBuffer, VkStencilFaceFlags, uint32_t); + void (*p_vkCmdSetViewport)(VkCommandBuffer, uint32_t, uint32_t, const VkViewport *); + void (*p_vkCmdUpdateBuffer)(VkCommandBuffer, VkBuffer, VkDeviceSize, VkDeviceSize, const void *); + void (*p_vkCmdWaitEvents)(VkCommandBuffer, uint32_t, const VkEvent *, VkPipelineStageFlags, VkPipelineStageFlags, uint32_t, const VkMemoryBarrier *, uint32_t, const VkBufferMemoryBarrier *, uint32_t, const VkImageMemoryBarrier *); + void (*p_vkCmdWriteTimestamp)(VkCommandBuffer, VkPipelineStageFlagBits, VkQueryPool, uint32_t); + VkResult (*p_vkCreateBuffer)(VkDevice, const VkBufferCreateInfo *, const VkAllocationCallbacks *, VkBuffer *); + VkResult (*p_vkCreateBufferView)(VkDevice, const VkBufferViewCreateInfo *, const VkAllocationCallbacks *, VkBufferView *); + VkResult (*p_vkCreateCommandPool)(VkDevice, const VkCommandPoolCreateInfo *, const VkAllocationCallbacks *, VkCommandPool *); + VkResult (*p_vkCreateComputePipelines)(VkDevice, VkPipelineCache, uint32_t, const VkComputePipelineCreateInfo *, const VkAllocationCallbacks *, VkPipeline *); + VkResult (*p_vkCreateDescriptorPool)(VkDevice, const VkDescriptorPoolCreateInfo *, const VkAllocationCallbacks *, VkDescriptorPool *); + VkResult (*p_vkCreateDescriptorSetLayout)(VkDevice, const VkDescriptorSetLayoutCreateInfo *, const VkAllocationCallbacks *, VkDescriptorSetLayout *); + VkResult (*p_vkCreateEvent)(VkDevice, const VkEventCreateInfo *, const VkAllocationCallbacks *, VkEvent *); + VkResult (*p_vkCreateFence)(VkDevice, const VkFenceCreateInfo *, const VkAllocationCallbacks *, VkFence *); + VkResult (*p_vkCreateFramebuffer)(VkDevice, const VkFramebufferCreateInfo *, const VkAllocationCallbacks *, VkFramebuffer *); + VkResult (*p_vkCreateGraphicsPipelines)(VkDevice, VkPipelineCache, uint32_t, const VkGraphicsPipelineCreateInfo *, const VkAllocationCallbacks *, VkPipeline *); + VkResult (*p_vkCreateImage)(VkDevice, const VkImageCreateInfo *, const VkAllocationCallbacks *, VkImage *); + VkResult (*p_vkCreateImageView)(VkDevice, const VkImageViewCreateInfo *, const VkAllocationCallbacks *, VkImageView *); + VkResult (*p_vkCreatePipelineCache)(VkDevice, const VkPipelineCacheCreateInfo *, const VkAllocationCallbacks *, VkPipelineCache *); + VkResult (*p_vkCreatePipelineLayout)(VkDevice, const VkPipelineLayoutCreateInfo *, const VkAllocationCallbacks *, VkPipelineLayout *); + VkResult (*p_vkCreateQueryPool)(VkDevice, const VkQueryPoolCreateInfo *, const VkAllocationCallbacks *, VkQueryPool *); + VkResult (*p_vkCreateRenderPass)(VkDevice, const VkRenderPassCreateInfo *, const VkAllocationCallbacks *, VkRenderPass *); + VkResult (*p_vkCreateSampler)(VkDevice, const VkSamplerCreateInfo *, const VkAllocationCallbacks *, VkSampler *); + VkResult (*p_vkCreateSemaphore)(VkDevice, const VkSemaphoreCreateInfo *, const VkAllocationCallbacks *, VkSemaphore *); + VkResult (*p_vkCreateShaderModule)(VkDevice, const VkShaderModuleCreateInfo *, const VkAllocationCallbacks *, VkShaderModule *); + void (*p_vkDestroyBuffer)(VkDevice, VkBuffer, const VkAllocationCallbacks *); + void (*p_vkDestroyBufferView)(VkDevice, VkBufferView, const VkAllocationCallbacks *); + void (*p_vkDestroyCommandPool)(VkDevice, VkCommandPool, const VkAllocationCallbacks *); + void (*p_vkDestroyDescriptorPool)(VkDevice, VkDescriptorPool, const VkAllocationCallbacks *); + void (*p_vkDestroyDescriptorSetLayout)(VkDevice, VkDescriptorSetLayout, const VkAllocationCallbacks *); + void (*p_vkDestroyDevice)(VkDevice, const VkAllocationCallbacks *); + void (*p_vkDestroyEvent)(VkDevice, VkEvent, const VkAllocationCallbacks *); + void (*p_vkDestroyFence)(VkDevice, VkFence, const VkAllocationCallbacks *); + void (*p_vkDestroyFramebuffer)(VkDevice, VkFramebuffer, const VkAllocationCallbacks *); + void (*p_vkDestroyImage)(VkDevice, VkImage, const VkAllocationCallbacks *); + void (*p_vkDestroyImageView)(VkDevice, VkImageView, const VkAllocationCallbacks *); + void (*p_vkDestroyPipeline)(VkDevice, VkPipeline, const VkAllocationCallbacks *); + void (*p_vkDestroyPipelineCache)(VkDevice, VkPipelineCache, const VkAllocationCallbacks *); + void (*p_vkDestroyPipelineLayout)(VkDevice, VkPipelineLayout, const VkAllocationCallbacks *); + void (*p_vkDestroyQueryPool)(VkDevice, VkQueryPool, const VkAllocationCallbacks *); + void (*p_vkDestroyRenderPass)(VkDevice, VkRenderPass, const VkAllocationCallbacks *); + void (*p_vkDestroySampler)(VkDevice, VkSampler, const VkAllocationCallbacks *); + void (*p_vkDestroySemaphore)(VkDevice, VkSemaphore, const VkAllocationCallbacks *); + void (*p_vkDestroyShaderModule)(VkDevice, VkShaderModule, const VkAllocationCallbacks *); + VkResult (*p_vkDeviceWaitIdle)(VkDevice); + VkResult (*p_vkEndCommandBuffer)(VkCommandBuffer); + VkResult (*p_vkFlushMappedMemoryRanges)(VkDevice, uint32_t, const VkMappedMemoryRange *); + void (*p_vkFreeCommandBuffers)(VkDevice, VkCommandPool, uint32_t, const VkCommandBuffer *); + VkResult (*p_vkFreeDescriptorSets)(VkDevice, VkDescriptorPool, uint32_t, const VkDescriptorSet *); + void (*p_vkFreeMemory)(VkDevice, VkDeviceMemory, const VkAllocationCallbacks *); + void (*p_vkGetBufferMemoryRequirements)(VkDevice, VkBuffer, VkMemoryRequirements *); + void (*p_vkGetDeviceMemoryCommitment)(VkDevice, VkDeviceMemory, VkDeviceSize *); + void (*p_vkGetDeviceQueue)(VkDevice, uint32_t, uint32_t, VkQueue *); + VkResult (*p_vkGetEventStatus)(VkDevice, VkEvent); + VkResult (*p_vkGetFenceStatus)(VkDevice, VkFence); + void (*p_vkGetImageMemoryRequirements)(VkDevice, VkImage, VkMemoryRequirements *); + void (*p_vkGetImageSparseMemoryRequirements)(VkDevice, VkImage, uint32_t *, VkSparseImageMemoryRequirements *); + void (*p_vkGetImageSubresourceLayout)(VkDevice, VkImage, const VkImageSubresource *, VkSubresourceLayout *); + VkResult (*p_vkGetPipelineCacheData)(VkDevice, VkPipelineCache, size_t *, void *); + VkResult (*p_vkGetQueryPoolResults)(VkDevice, VkQueryPool, uint32_t, uint32_t, size_t, void *, VkDeviceSize, VkQueryResultFlags); + void (*p_vkGetRenderAreaGranularity)(VkDevice, VkRenderPass, VkExtent2D *); + VkResult (*p_vkInvalidateMappedMemoryRanges)(VkDevice, uint32_t, const VkMappedMemoryRange *); + VkResult (*p_vkMapMemory)(VkDevice, VkDeviceMemory, VkDeviceSize, VkDeviceSize, VkMemoryMapFlags, void **); + VkResult (*p_vkMergePipelineCaches)(VkDevice, VkPipelineCache, uint32_t, const VkPipelineCache *); + VkResult (*p_vkQueueBindSparse)(VkQueue, uint32_t, const VkBindSparseInfo *, VkFence); + VkResult (*p_vkQueueSubmit)(VkQueue, uint32_t, const VkSubmitInfo *, VkFence); + VkResult (*p_vkQueueWaitIdle)(VkQueue); + VkResult (*p_vkResetCommandBuffer)(VkCommandBuffer, VkCommandBufferResetFlags); + VkResult (*p_vkResetCommandPool)(VkDevice, VkCommandPool, VkCommandPoolResetFlags); + VkResult (*p_vkResetDescriptorPool)(VkDevice, VkDescriptorPool, VkDescriptorPoolResetFlags); + VkResult (*p_vkResetEvent)(VkDevice, VkEvent); + VkResult (*p_vkResetFences)(VkDevice, uint32_t, const VkFence *); + VkResult (*p_vkSetEvent)(VkDevice, VkEvent); + void (*p_vkUnmapMemory)(VkDevice, VkDeviceMemory); + void (*p_vkUpdateDescriptorSets)(VkDevice, uint32_t, const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *); + VkResult (*p_vkWaitForFences)(VkDevice, uint32_t, const VkFence *, VkBool32, uint64_t); +}; + /* For use by vkInstance and children */ struct vulkan_instance_funcs { @@ -192,6 +318,128 @@ struct vulkan_instance_funcs void (*p_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkSampleCountFlagBits, VkImageUsageFlags, VkImageTiling, uint32_t *, VkSparseImageFormatProperties *); };
+#define ALL_VK_DEVICE_FUNCS() \ + USE_VK_FUNC(vkAllocateCommandBuffers) \ + USE_VK_FUNC(vkAllocateDescriptorSets) \ + USE_VK_FUNC(vkAllocateMemory) \ + USE_VK_FUNC(vkBeginCommandBuffer) \ + USE_VK_FUNC(vkBindBufferMemory) \ + USE_VK_FUNC(vkBindImageMemory) \ + USE_VK_FUNC(vkCmdBeginQuery) \ + USE_VK_FUNC(vkCmdBeginRenderPass) \ + USE_VK_FUNC(vkCmdBindDescriptorSets) \ + USE_VK_FUNC(vkCmdBindIndexBuffer) \ + USE_VK_FUNC(vkCmdBindPipeline) \ + USE_VK_FUNC(vkCmdBindVertexBuffers) \ + USE_VK_FUNC(vkCmdBlitImage) \ + USE_VK_FUNC(vkCmdClearAttachments) \ + USE_VK_FUNC(vkCmdClearColorImage) \ + USE_VK_FUNC(vkCmdClearDepthStencilImage) \ + USE_VK_FUNC(vkCmdCopyBuffer) \ + USE_VK_FUNC(vkCmdCopyBufferToImage) \ + USE_VK_FUNC(vkCmdCopyImage) \ + USE_VK_FUNC(vkCmdCopyImageToBuffer) \ + USE_VK_FUNC(vkCmdCopyQueryPoolResults) \ + USE_VK_FUNC(vkCmdDispatch) \ + USE_VK_FUNC(vkCmdDispatchIndirect) \ + USE_VK_FUNC(vkCmdDraw) \ + USE_VK_FUNC(vkCmdDrawIndexed) \ + USE_VK_FUNC(vkCmdDrawIndexedIndirect) \ + USE_VK_FUNC(vkCmdDrawIndirect) \ + USE_VK_FUNC(vkCmdEndQuery) \ + USE_VK_FUNC(vkCmdEndRenderPass) \ + USE_VK_FUNC(vkCmdExecuteCommands) \ + USE_VK_FUNC(vkCmdFillBuffer) \ + USE_VK_FUNC(vkCmdNextSubpass) \ + USE_VK_FUNC(vkCmdPipelineBarrier) \ + USE_VK_FUNC(vkCmdPushConstants) \ + USE_VK_FUNC(vkCmdResetEvent) \ + USE_VK_FUNC(vkCmdResetQueryPool) \ + USE_VK_FUNC(vkCmdResolveImage) \ + USE_VK_FUNC(vkCmdSetBlendConstants) \ + USE_VK_FUNC(vkCmdSetDepthBias) \ + USE_VK_FUNC(vkCmdSetDepthBounds) \ + USE_VK_FUNC(vkCmdSetEvent) \ + USE_VK_FUNC(vkCmdSetLineWidth) \ + USE_VK_FUNC(vkCmdSetScissor) \ + USE_VK_FUNC(vkCmdSetStencilCompareMask) \ + USE_VK_FUNC(vkCmdSetStencilReference) \ + USE_VK_FUNC(vkCmdSetStencilWriteMask) \ + USE_VK_FUNC(vkCmdSetViewport) \ + USE_VK_FUNC(vkCmdUpdateBuffer) \ + USE_VK_FUNC(vkCmdWaitEvents) \ + USE_VK_FUNC(vkCmdWriteTimestamp) \ + USE_VK_FUNC(vkCreateBuffer) \ + USE_VK_FUNC(vkCreateBufferView) \ + USE_VK_FUNC(vkCreateCommandPool) \ + USE_VK_FUNC(vkCreateComputePipelines) \ + USE_VK_FUNC(vkCreateDescriptorPool) \ + USE_VK_FUNC(vkCreateDescriptorSetLayout) \ + USE_VK_FUNC(vkCreateEvent) \ + USE_VK_FUNC(vkCreateFence) \ + USE_VK_FUNC(vkCreateFramebuffer) \ + USE_VK_FUNC(vkCreateGraphicsPipelines) \ + USE_VK_FUNC(vkCreateImage) \ + USE_VK_FUNC(vkCreateImageView) \ + USE_VK_FUNC(vkCreatePipelineCache) \ + USE_VK_FUNC(vkCreatePipelineLayout) \ + USE_VK_FUNC(vkCreateQueryPool) \ + USE_VK_FUNC(vkCreateRenderPass) \ + USE_VK_FUNC(vkCreateSampler) \ + USE_VK_FUNC(vkCreateSemaphore) \ + USE_VK_FUNC(vkCreateShaderModule) \ + USE_VK_FUNC(vkDestroyBuffer) \ + USE_VK_FUNC(vkDestroyBufferView) \ + USE_VK_FUNC(vkDestroyCommandPool) \ + USE_VK_FUNC(vkDestroyDescriptorPool) \ + USE_VK_FUNC(vkDestroyDescriptorSetLayout) \ + USE_VK_FUNC(vkDestroyDevice) \ + USE_VK_FUNC(vkDestroyEvent) \ + USE_VK_FUNC(vkDestroyFence) \ + USE_VK_FUNC(vkDestroyFramebuffer) \ + USE_VK_FUNC(vkDestroyImage) \ + USE_VK_FUNC(vkDestroyImageView) \ + USE_VK_FUNC(vkDestroyPipeline) \ + USE_VK_FUNC(vkDestroyPipelineCache) \ + USE_VK_FUNC(vkDestroyPipelineLayout) \ + USE_VK_FUNC(vkDestroyQueryPool) \ + USE_VK_FUNC(vkDestroyRenderPass) \ + USE_VK_FUNC(vkDestroySampler) \ + USE_VK_FUNC(vkDestroySemaphore) \ + USE_VK_FUNC(vkDestroyShaderModule) \ + USE_VK_FUNC(vkDeviceWaitIdle) \ + USE_VK_FUNC(vkEndCommandBuffer) \ + USE_VK_FUNC(vkFlushMappedMemoryRanges) \ + USE_VK_FUNC(vkFreeCommandBuffers) \ + USE_VK_FUNC(vkFreeDescriptorSets) \ + USE_VK_FUNC(vkFreeMemory) \ + USE_VK_FUNC(vkGetBufferMemoryRequirements) \ + USE_VK_FUNC(vkGetDeviceMemoryCommitment) \ + USE_VK_FUNC(vkGetDeviceQueue) \ + USE_VK_FUNC(vkGetEventStatus) \ + USE_VK_FUNC(vkGetFenceStatus) \ + USE_VK_FUNC(vkGetImageMemoryRequirements) \ + USE_VK_FUNC(vkGetImageSparseMemoryRequirements) \ + USE_VK_FUNC(vkGetImageSubresourceLayout) \ + USE_VK_FUNC(vkGetPipelineCacheData) \ + USE_VK_FUNC(vkGetQueryPoolResults) \ + USE_VK_FUNC(vkGetRenderAreaGranularity) \ + USE_VK_FUNC(vkInvalidateMappedMemoryRanges) \ + USE_VK_FUNC(vkMapMemory) \ + USE_VK_FUNC(vkMergePipelineCaches) \ + USE_VK_FUNC(vkQueueBindSparse) \ + USE_VK_FUNC(vkQueueSubmit) \ + USE_VK_FUNC(vkQueueWaitIdle) \ + USE_VK_FUNC(vkResetCommandBuffer) \ + USE_VK_FUNC(vkResetCommandPool) \ + USE_VK_FUNC(vkResetDescriptorPool) \ + USE_VK_FUNC(vkResetEvent) \ + USE_VK_FUNC(vkResetFences) \ + USE_VK_FUNC(vkSetEvent) \ + USE_VK_FUNC(vkUnmapMemory) \ + USE_VK_FUNC(vkUpdateDescriptorSets) \ + USE_VK_FUNC(vkWaitForFences) + #define ALL_VK_INSTANCE_FUNCS() \ USE_VK_FUNC(vkCreateDevice)\ USE_VK_FUNC(vkEnumerateDeviceExtensionProperties)\ diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index c3fed9e58a..c99ca66168 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -36,6 +36,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); +static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
static BOOL wine_vk_init(void) @@ -51,6 +52,7 @@ static BOOL wine_vk_init(void) #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(vulkan_handle, #f, NULL, 0)) == NULL) return FALSE; LOAD_FUNCPTR(vkCreateInstance) LOAD_FUNCPTR(vkDestroyInstance) +LOAD_FUNCPTR(vkGetDeviceProcAddr) LOAD_FUNCPTR(vkGetInstanceProcAddr) #undef LOAD_FUNCPTR
@@ -116,6 +118,12 @@ static VkResult X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_ return VK_SUCCESS; }
+static void * X11DRV_vkGetDeviceProcAddr(VkDevice device, const char *name) +{ + TRACE("%p, %s\n", device, debugstr_a(name)); + return pvkGetDeviceProcAddr(device, name); +} + static void * X11DRV_vkGetInstanceProcAddr(VkInstance instance, const char *name) { TRACE("%p, %s\n", instance, debugstr_a(name)); @@ -127,6 +135,7 @@ static const struct vulkan_funcs vulkan_funcs = X11DRV_vkCreateInstance, X11DRV_vkDestroyInstance, X11DRV_vkEnumerateInstanceExtensionProperties, + X11DRV_vkGetDeviceProcAddr, X11DRV_vkGetInstanceProcAddr };
diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index 2e2abf9f02..8d69222e03 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -4,7 +4,7 @@ #define __WINE_VULKAN_DRIVER_H
/* Wine internal vulkan driver version, needs to be bumped upon vulkan_funcs changes. */ -#define WINE_VULKAN_DRIVER_VERSION 1 +#define WINE_VULKAN_DRIVER_VERSION 2
struct vulkan_funcs { @@ -15,6 +15,7 @@ struct vulkan_funcs VkResult (*p_vkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); void (*p_vkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); VkResult (*p_vkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *); + void * (*p_vkGetDeviceProcAddr)(VkDevice, const char *); void * (*p_vkGetInstanceProcAddr)(VkInstance, const char *); };
On Thu, Mar 8, 2018 at 7:57 AM, Roderick Colenbrander thunderbird2k@gmail.com wrote:
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com
dlls/winevulkan/make_vulkan | 39 +++++- dlls/winevulkan/vulkan.c | 68 +++++++++++ dlls/winevulkan/vulkan_private.h | 8 ++ dlls/winevulkan/vulkan_thunks.c | 6 - dlls/winevulkan/vulkan_thunks.h | 248 +++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/vulkan.c | 9 ++ include/wine/vulkan_driver.h | 3 +- 7 files changed, 370 insertions(+), 11 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index fcacd1128f..698d496a96 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -71,7 +71,7 @@ WINE_VULKAN_THUNKS_H = "vulkan_thunks.h" # Functions part of our winevulkan graphics driver interface. # DRIVER_VERSION should be bumped on any change to driver interface # in FUNCTION_OVERRIDES -DRIVER_VERSION = 1 +DRIVER_VERSION = 2
# Table of functions for which we have a special implementation. # This are regular device / instance functions for which we need @@ -88,9 +88,13 @@ FUNCTION_OVERRIDES = { "vkGetInstanceProcAddr": {"dispatch" : False, "driver" : True, "thunk" : False},
# Instance functions
- "vkCreateDevice" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkDestroyInstance" : {"dispatch" : True, "driver" : True, "thunk" : False }, "vkEnumerateDeviceExtensionProperties" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkEnumeratePhysicalDevices" : {"dispatch" : True, "driver" : False, "thunk" : False},
- # Device functions
- "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : True},
}
@@ -351,9 +355,6 @@ class VkFunction(object):
def needs_stub(self): """ Temporary function to limit script hacks until more code is implemented. """
if self.name == "vkCreateDevice":
return True
if self.params[0].type != "VkPhysicalDevice": return True
@@ -1791,6 +1792,19 @@ class VkGenerator(object): f.write(struct.definition(align=False, conv=True, postfix="_host")) f.write("\n")
f.write("/* For use by vkDevice and children */\n")
f.write("struct vulkan_device_funcs\n{\n")
for vk_func in self.registry.device_funcs:
if not vk_func.is_required():
continue
if not vk_func.needs_dispatch() or vk_func.is_driver_func():
LOGGER.debug("skipping {0} in vulkan_device_funcs".format(vk_func.name))
continue
f.write(" {0};\n".format(vk_func.pfn(conv=False)))
f.write("};\n\n")
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:
@@ -1811,6 +1825,23 @@ class VkGenerator(object): f.write(" {0};\n".format(vk_func.pfn(conv=False))) f.write("};\n\n")
f.write("#define ALL_VK_DEVICE_FUNCS() \\\n")
first = True
for vk_func in self.registry.device_funcs:
if not vk_func.is_required():
continue
if not vk_func.needs_dispatch() or vk_func.is_driver_func():
LOGGER.debug("skipping {0} in ALL_VK_DEVICE_FUNCS".format(vk_func.name))
continue
if first:
f.write(" USE_VK_FUNC({0})".format(vk_func.name))
first = False
else:
f.write(" \\\n USE_VK_FUNC({0})".format(vk_func.name))
f.write("\n\n")
f.write("#define ALL_VK_INSTANCE_FUNCS() \\\n") first = True for vk_func in self.registry.instance_funcs:
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 12d56f5b51..d5fe25f36a 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -42,6 +42,22 @@ static void *wine_vk_get_global_proc_addr(const char *name);
static const struct vulkan_funcs *vk_funcs = NULL;
+/* Helper function used for freeing a device structure. This function supports full
- and partial object cleanups and can thus be used vkCreateDevice failures.
A word is missing in the sentence:
can thus be used *for* vkCreateDevice failures
- */
+static void wine_vk_device_free(struct VkDevice_T *device) +{
- if (!device)
return;
- if (device->device && device->funcs.p_vkDestroyDevice)
- {
device->funcs.p_vkDestroyDevice(device->device, NULL /* pAllocator */);
- }
- heap_free(device);
+}
static BOOL wine_vk_init(void) { HDC hdc = GetDC(0); @@ -146,6 +162,58 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) heap_free(instance); }
+VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev,
const VkDeviceCreateInfo *create_info,
const VkAllocationCallbacks *allocator, VkDevice *device)
+{
- struct VkDevice_T *object = NULL;
- VkResult res;
- TRACE("%p %p %p %p\n", phys_dev, create_info, allocator, device);
- if (allocator)
- {
FIXME("Support for allocation callbacks not implemented yet\n");
- }
- object = heap_alloc_zero(sizeof(*object));
- if (!object)
return VK_ERROR_OUT_OF_HOST_MEMORY;
- object->base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
- /* At least for now we can directly pass create_info through. All extensions we report
* should be compatible. In addition the loader is supposed to santize values e.g. layers.
Typo: sanitize.
*/
- res = phys_dev->instance->funcs.p_vkCreateDevice(phys_dev->phys_dev,
create_info, NULL /* allocator */, &object->device);
- if (res != VK_SUCCESS)
- {
ERR("Failed to create device\n");
goto err;
- }
- object->phys_dev = phys_dev;
- /* Just load all function pointers we are aware off. The loader takes care of filtering.
* We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons
* as functions pass through fewer dispatch tables within the loader.
*/
+#define USE_VK_FUNC(name) \
- object->funcs.p_##name = (void*)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \
void *
- if (object->funcs.p_##name == NULL) \
TRACE("Not found %s\n", #name);
- ALL_VK_DEVICE_FUNCS()
+#undef USE_VK_FUNC
- *device = object;
- return VK_SUCCESS;
+err:
- wine_vk_device_free(object);
- return res;
+}
static VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkInstance *instance) { diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 8ef4b924a2..897c1e1418 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -48,6 +48,14 @@ struct wine_vk_base UINT_PTR loader_magic; };
+struct VkDevice_T +{
- struct wine_vk_base base;
- struct vulkan_device_funcs funcs;
- struct VkPhysicalDevice_T *phys_dev; /* parent */
- VkDevice device; /* native device */
+};
struct VkInstance_T { struct wine_vk_base base; diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 0840f3c5c8..99095c60f9 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -467,12 +467,6 @@ static VkResult WINAPI wine_vkCreateDescriptorSetLayout(VkDevice device, const V return VK_ERROR_OUT_OF_HOST_MEMORY; }
-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 VkResult WINAPI wine_vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) { FIXME("stub: %p, %p, %p, %p\n", device, pCreateInfo, pAllocator, pEvent); diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 17916fceae..49a88968a2 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -13,6 +13,7 @@ void *wine_vk_get_device_proc_addr(const char *name) DECLSPEC_HIDDEN; void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
/* Functions for which we have custom implementations outside of the thunks. */ +VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) DECLSPEC_HIDDEN; void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN; @@ -164,6 +165,131 @@ typedef struct VkPhysicalDeviceProperties_host } VkPhysicalDeviceProperties_host;
+/* For use by vkDevice and children */ +struct vulkan_device_funcs +{
- VkResult (*p_vkAllocateCommandBuffers)(VkDevice, const VkCommandBufferAllocateInfo *, VkCommandBuffer *);
- VkResult (*p_vkAllocateDescriptorSets)(VkDevice, const VkDescriptorSetAllocateInfo *, VkDescriptorSet *);
- VkResult (*p_vkAllocateMemory)(VkDevice, const VkMemoryAllocateInfo *, const VkAllocationCallbacks *, VkDeviceMemory *);
- VkResult (*p_vkBeginCommandBuffer)(VkCommandBuffer, const VkCommandBufferBeginInfo *);
- VkResult (*p_vkBindBufferMemory)(VkDevice, VkBuffer, VkDeviceMemory, VkDeviceSize);
- VkResult (*p_vkBindImageMemory)(VkDevice, VkImage, VkDeviceMemory, VkDeviceSize);
- void (*p_vkCmdBeginQuery)(VkCommandBuffer, VkQueryPool, uint32_t, VkQueryControlFlags);
- void (*p_vkCmdBeginRenderPass)(VkCommandBuffer, const VkRenderPassBeginInfo *, VkSubpassContents);
- void (*p_vkCmdBindDescriptorSets)(VkCommandBuffer, VkPipelineBindPoint, VkPipelineLayout, uint32_t, uint32_t, const VkDescriptorSet *, uint32_t, const uint32_t *);
- void (*p_vkCmdBindIndexBuffer)(VkCommandBuffer, VkBuffer, VkDeviceSize, VkIndexType);
- void (*p_vkCmdBindPipeline)(VkCommandBuffer, VkPipelineBindPoint, VkPipeline);
- void (*p_vkCmdBindVertexBuffers)(VkCommandBuffer, uint32_t, uint32_t, const VkBuffer *, const VkDeviceSize *);
- void (*p_vkCmdBlitImage)(VkCommandBuffer, VkImage, VkImageLayout, VkImage, VkImageLayout, uint32_t, const VkImageBlit *, VkFilter);
- void (*p_vkCmdClearAttachments)(VkCommandBuffer, uint32_t, const VkClearAttachment *, uint32_t, const VkClearRect *);
- void (*p_vkCmdClearColorImage)(VkCommandBuffer, VkImage, VkImageLayout, const VkClearColorValue *, uint32_t, const VkImageSubresourceRange *);
- void (*p_vkCmdClearDepthStencilImage)(VkCommandBuffer, VkImage, VkImageLayout, const VkClearDepthStencilValue *, uint32_t, const VkImageSubresourceRange *);
- void (*p_vkCmdCopyBuffer)(VkCommandBuffer, VkBuffer, VkBuffer, uint32_t, const VkBufferCopy *);
- void (*p_vkCmdCopyBufferToImage)(VkCommandBuffer, VkBuffer, VkImage, VkImageLayout, uint32_t, const VkBufferImageCopy *);
- void (*p_vkCmdCopyImage)(VkCommandBuffer, VkImage, VkImageLayout, VkImage, VkImageLayout, uint32_t, const VkImageCopy *);
- void (*p_vkCmdCopyImageToBuffer)(VkCommandBuffer, VkImage, VkImageLayout, VkBuffer, uint32_t, const VkBufferImageCopy *);
- void (*p_vkCmdCopyQueryPoolResults)(VkCommandBuffer, VkQueryPool, uint32_t, uint32_t, VkBuffer, VkDeviceSize, VkDeviceSize, VkQueryResultFlags);
- void (*p_vkCmdDispatch)(VkCommandBuffer, uint32_t, uint32_t, uint32_t);
- void (*p_vkCmdDispatchIndirect)(VkCommandBuffer, VkBuffer, VkDeviceSize);
- void (*p_vkCmdDraw)(VkCommandBuffer, uint32_t, uint32_t, uint32_t, uint32_t);
- void (*p_vkCmdDrawIndexed)(VkCommandBuffer, uint32_t, uint32_t, uint32_t, int32_t, uint32_t);
- void (*p_vkCmdDrawIndexedIndirect)(VkCommandBuffer, VkBuffer, VkDeviceSize, uint32_t, uint32_t);
- void (*p_vkCmdDrawIndirect)(VkCommandBuffer, VkBuffer, VkDeviceSize, uint32_t, uint32_t);
- void (*p_vkCmdEndQuery)(VkCommandBuffer, VkQueryPool, uint32_t);
- void (*p_vkCmdEndRenderPass)(VkCommandBuffer);
- void (*p_vkCmdExecuteCommands)(VkCommandBuffer, uint32_t, const VkCommandBuffer *);
- void (*p_vkCmdFillBuffer)(VkCommandBuffer, VkBuffer, VkDeviceSize, VkDeviceSize, uint32_t);
- void (*p_vkCmdNextSubpass)(VkCommandBuffer, VkSubpassContents);
- void (*p_vkCmdPipelineBarrier)(VkCommandBuffer, VkPipelineStageFlags, VkPipelineStageFlags, VkDependencyFlags, uint32_t, const VkMemoryBarrier *, uint32_t, const VkBufferMemoryBarrier *, uint32_t, const VkImageMemoryBarrier *);
- void (*p_vkCmdPushConstants)(VkCommandBuffer, VkPipelineLayout, VkShaderStageFlags, uint32_t, uint32_t, const void *);
- void (*p_vkCmdResetEvent)(VkCommandBuffer, VkEvent, VkPipelineStageFlags);
- void (*p_vkCmdResetQueryPool)(VkCommandBuffer, VkQueryPool, uint32_t, uint32_t);
- void (*p_vkCmdResolveImage)(VkCommandBuffer, VkImage, VkImageLayout, VkImage, VkImageLayout, uint32_t, const VkImageResolve *);
- void (*p_vkCmdSetBlendConstants)(VkCommandBuffer, const float[4]);
- void (*p_vkCmdSetDepthBias)(VkCommandBuffer, float, float, float);
- void (*p_vkCmdSetDepthBounds)(VkCommandBuffer, float, float);
- void (*p_vkCmdSetEvent)(VkCommandBuffer, VkEvent, VkPipelineStageFlags);
- void (*p_vkCmdSetLineWidth)(VkCommandBuffer, float);
- void (*p_vkCmdSetScissor)(VkCommandBuffer, uint32_t, uint32_t, const VkRect2D *);
- void (*p_vkCmdSetStencilCompareMask)(VkCommandBuffer, VkStencilFaceFlags, uint32_t);
- void (*p_vkCmdSetStencilReference)(VkCommandBuffer, VkStencilFaceFlags, uint32_t);
- void (*p_vkCmdSetStencilWriteMask)(VkCommandBuffer, VkStencilFaceFlags, uint32_t);
- void (*p_vkCmdSetViewport)(VkCommandBuffer, uint32_t, uint32_t, const VkViewport *);
- void (*p_vkCmdUpdateBuffer)(VkCommandBuffer, VkBuffer, VkDeviceSize, VkDeviceSize, const void *);
- void (*p_vkCmdWaitEvents)(VkCommandBuffer, uint32_t, const VkEvent *, VkPipelineStageFlags, VkPipelineStageFlags, uint32_t, const VkMemoryBarrier *, uint32_t, const VkBufferMemoryBarrier *, uint32_t, const VkImageMemoryBarrier *);
- void (*p_vkCmdWriteTimestamp)(VkCommandBuffer, VkPipelineStageFlagBits, VkQueryPool, uint32_t);
- VkResult (*p_vkCreateBuffer)(VkDevice, const VkBufferCreateInfo *, const VkAllocationCallbacks *, VkBuffer *);
- VkResult (*p_vkCreateBufferView)(VkDevice, const VkBufferViewCreateInfo *, const VkAllocationCallbacks *, VkBufferView *);
- VkResult (*p_vkCreateCommandPool)(VkDevice, const VkCommandPoolCreateInfo *, const VkAllocationCallbacks *, VkCommandPool *);
- VkResult (*p_vkCreateComputePipelines)(VkDevice, VkPipelineCache, uint32_t, const VkComputePipelineCreateInfo *, const VkAllocationCallbacks *, VkPipeline *);
- VkResult (*p_vkCreateDescriptorPool)(VkDevice, const VkDescriptorPoolCreateInfo *, const VkAllocationCallbacks *, VkDescriptorPool *);
- VkResult (*p_vkCreateDescriptorSetLayout)(VkDevice, const VkDescriptorSetLayoutCreateInfo *, const VkAllocationCallbacks *, VkDescriptorSetLayout *);
- VkResult (*p_vkCreateEvent)(VkDevice, const VkEventCreateInfo *, const VkAllocationCallbacks *, VkEvent *);
- VkResult (*p_vkCreateFence)(VkDevice, const VkFenceCreateInfo *, const VkAllocationCallbacks *, VkFence *);
- VkResult (*p_vkCreateFramebuffer)(VkDevice, const VkFramebufferCreateInfo *, const VkAllocationCallbacks *, VkFramebuffer *);
- VkResult (*p_vkCreateGraphicsPipelines)(VkDevice, VkPipelineCache, uint32_t, const VkGraphicsPipelineCreateInfo *, const VkAllocationCallbacks *, VkPipeline *);
- VkResult (*p_vkCreateImage)(VkDevice, const VkImageCreateInfo *, const VkAllocationCallbacks *, VkImage *);
- VkResult (*p_vkCreateImageView)(VkDevice, const VkImageViewCreateInfo *, const VkAllocationCallbacks *, VkImageView *);
- VkResult (*p_vkCreatePipelineCache)(VkDevice, const VkPipelineCacheCreateInfo *, const VkAllocationCallbacks *, VkPipelineCache *);
- VkResult (*p_vkCreatePipelineLayout)(VkDevice, const VkPipelineLayoutCreateInfo *, const VkAllocationCallbacks *, VkPipelineLayout *);
- VkResult (*p_vkCreateQueryPool)(VkDevice, const VkQueryPoolCreateInfo *, const VkAllocationCallbacks *, VkQueryPool *);
- VkResult (*p_vkCreateRenderPass)(VkDevice, const VkRenderPassCreateInfo *, const VkAllocationCallbacks *, VkRenderPass *);
- VkResult (*p_vkCreateSampler)(VkDevice, const VkSamplerCreateInfo *, const VkAllocationCallbacks *, VkSampler *);
- VkResult (*p_vkCreateSemaphore)(VkDevice, const VkSemaphoreCreateInfo *, const VkAllocationCallbacks *, VkSemaphore *);
- VkResult (*p_vkCreateShaderModule)(VkDevice, const VkShaderModuleCreateInfo *, const VkAllocationCallbacks *, VkShaderModule *);
- void (*p_vkDestroyBuffer)(VkDevice, VkBuffer, const VkAllocationCallbacks *);
- void (*p_vkDestroyBufferView)(VkDevice, VkBufferView, const VkAllocationCallbacks *);
- void (*p_vkDestroyCommandPool)(VkDevice, VkCommandPool, const VkAllocationCallbacks *);
- void (*p_vkDestroyDescriptorPool)(VkDevice, VkDescriptorPool, const VkAllocationCallbacks *);
- void (*p_vkDestroyDescriptorSetLayout)(VkDevice, VkDescriptorSetLayout, const VkAllocationCallbacks *);
- void (*p_vkDestroyDevice)(VkDevice, const VkAllocationCallbacks *);
- void (*p_vkDestroyEvent)(VkDevice, VkEvent, const VkAllocationCallbacks *);
- void (*p_vkDestroyFence)(VkDevice, VkFence, const VkAllocationCallbacks *);
- void (*p_vkDestroyFramebuffer)(VkDevice, VkFramebuffer, const VkAllocationCallbacks *);
- void (*p_vkDestroyImage)(VkDevice, VkImage, const VkAllocationCallbacks *);
- void (*p_vkDestroyImageView)(VkDevice, VkImageView, const VkAllocationCallbacks *);
- void (*p_vkDestroyPipeline)(VkDevice, VkPipeline, const VkAllocationCallbacks *);
- void (*p_vkDestroyPipelineCache)(VkDevice, VkPipelineCache, const VkAllocationCallbacks *);
- void (*p_vkDestroyPipelineLayout)(VkDevice, VkPipelineLayout, const VkAllocationCallbacks *);
- void (*p_vkDestroyQueryPool)(VkDevice, VkQueryPool, const VkAllocationCallbacks *);
- void (*p_vkDestroyRenderPass)(VkDevice, VkRenderPass, const VkAllocationCallbacks *);
- void (*p_vkDestroySampler)(VkDevice, VkSampler, const VkAllocationCallbacks *);
- void (*p_vkDestroySemaphore)(VkDevice, VkSemaphore, const VkAllocationCallbacks *);
- void (*p_vkDestroyShaderModule)(VkDevice, VkShaderModule, const VkAllocationCallbacks *);
- VkResult (*p_vkDeviceWaitIdle)(VkDevice);
- VkResult (*p_vkEndCommandBuffer)(VkCommandBuffer);
- VkResult (*p_vkFlushMappedMemoryRanges)(VkDevice, uint32_t, const VkMappedMemoryRange *);
- void (*p_vkFreeCommandBuffers)(VkDevice, VkCommandPool, uint32_t, const VkCommandBuffer *);
- VkResult (*p_vkFreeDescriptorSets)(VkDevice, VkDescriptorPool, uint32_t, const VkDescriptorSet *);
- void (*p_vkFreeMemory)(VkDevice, VkDeviceMemory, const VkAllocationCallbacks *);
- void (*p_vkGetBufferMemoryRequirements)(VkDevice, VkBuffer, VkMemoryRequirements *);
- void (*p_vkGetDeviceMemoryCommitment)(VkDevice, VkDeviceMemory, VkDeviceSize *);
- void (*p_vkGetDeviceQueue)(VkDevice, uint32_t, uint32_t, VkQueue *);
- VkResult (*p_vkGetEventStatus)(VkDevice, VkEvent);
- VkResult (*p_vkGetFenceStatus)(VkDevice, VkFence);
- void (*p_vkGetImageMemoryRequirements)(VkDevice, VkImage, VkMemoryRequirements *);
- void (*p_vkGetImageSparseMemoryRequirements)(VkDevice, VkImage, uint32_t *, VkSparseImageMemoryRequirements *);
- void (*p_vkGetImageSubresourceLayout)(VkDevice, VkImage, const VkImageSubresource *, VkSubresourceLayout *);
- VkResult (*p_vkGetPipelineCacheData)(VkDevice, VkPipelineCache, size_t *, void *);
- VkResult (*p_vkGetQueryPoolResults)(VkDevice, VkQueryPool, uint32_t, uint32_t, size_t, void *, VkDeviceSize, VkQueryResultFlags);
- void (*p_vkGetRenderAreaGranularity)(VkDevice, VkRenderPass, VkExtent2D *);
- VkResult (*p_vkInvalidateMappedMemoryRanges)(VkDevice, uint32_t, const VkMappedMemoryRange *);
- VkResult (*p_vkMapMemory)(VkDevice, VkDeviceMemory, VkDeviceSize, VkDeviceSize, VkMemoryMapFlags, void **);
- VkResult (*p_vkMergePipelineCaches)(VkDevice, VkPipelineCache, uint32_t, const VkPipelineCache *);
- VkResult (*p_vkQueueBindSparse)(VkQueue, uint32_t, const VkBindSparseInfo *, VkFence);
- VkResult (*p_vkQueueSubmit)(VkQueue, uint32_t, const VkSubmitInfo *, VkFence);
- VkResult (*p_vkQueueWaitIdle)(VkQueue);
- VkResult (*p_vkResetCommandBuffer)(VkCommandBuffer, VkCommandBufferResetFlags);
- VkResult (*p_vkResetCommandPool)(VkDevice, VkCommandPool, VkCommandPoolResetFlags);
- VkResult (*p_vkResetDescriptorPool)(VkDevice, VkDescriptorPool, VkDescriptorPoolResetFlags);
- VkResult (*p_vkResetEvent)(VkDevice, VkEvent);
- VkResult (*p_vkResetFences)(VkDevice, uint32_t, const VkFence *);
- VkResult (*p_vkSetEvent)(VkDevice, VkEvent);
- void (*p_vkUnmapMemory)(VkDevice, VkDeviceMemory);
- void (*p_vkUpdateDescriptorSets)(VkDevice, uint32_t, const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *);
- VkResult (*p_vkWaitForFences)(VkDevice, uint32_t, const VkFence *, VkBool32, uint64_t);
+};
/* For use by vkInstance and children */ struct vulkan_instance_funcs { @@ -192,6 +318,128 @@ struct vulkan_instance_funcs void (*p_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice, VkFormat, VkImageType, VkSampleCountFlagBits, VkImageUsageFlags, VkImageTiling, uint32_t *, VkSparseImageFormatProperties *); };
+#define ALL_VK_DEVICE_FUNCS() \
- USE_VK_FUNC(vkAllocateCommandBuffers) \
- USE_VK_FUNC(vkAllocateDescriptorSets) \
- USE_VK_FUNC(vkAllocateMemory) \
- USE_VK_FUNC(vkBeginCommandBuffer) \
- USE_VK_FUNC(vkBindBufferMemory) \
- USE_VK_FUNC(vkBindImageMemory) \
- USE_VK_FUNC(vkCmdBeginQuery) \
- USE_VK_FUNC(vkCmdBeginRenderPass) \
- USE_VK_FUNC(vkCmdBindDescriptorSets) \
- USE_VK_FUNC(vkCmdBindIndexBuffer) \
- USE_VK_FUNC(vkCmdBindPipeline) \
- USE_VK_FUNC(vkCmdBindVertexBuffers) \
- USE_VK_FUNC(vkCmdBlitImage) \
- USE_VK_FUNC(vkCmdClearAttachments) \
- USE_VK_FUNC(vkCmdClearColorImage) \
- USE_VK_FUNC(vkCmdClearDepthStencilImage) \
- USE_VK_FUNC(vkCmdCopyBuffer) \
- USE_VK_FUNC(vkCmdCopyBufferToImage) \
- USE_VK_FUNC(vkCmdCopyImage) \
- USE_VK_FUNC(vkCmdCopyImageToBuffer) \
- USE_VK_FUNC(vkCmdCopyQueryPoolResults) \
- USE_VK_FUNC(vkCmdDispatch) \
- USE_VK_FUNC(vkCmdDispatchIndirect) \
- USE_VK_FUNC(vkCmdDraw) \
- USE_VK_FUNC(vkCmdDrawIndexed) \
- USE_VK_FUNC(vkCmdDrawIndexedIndirect) \
- USE_VK_FUNC(vkCmdDrawIndirect) \
- USE_VK_FUNC(vkCmdEndQuery) \
- USE_VK_FUNC(vkCmdEndRenderPass) \
- USE_VK_FUNC(vkCmdExecuteCommands) \
- USE_VK_FUNC(vkCmdFillBuffer) \
- USE_VK_FUNC(vkCmdNextSubpass) \
- USE_VK_FUNC(vkCmdPipelineBarrier) \
- USE_VK_FUNC(vkCmdPushConstants) \
- USE_VK_FUNC(vkCmdResetEvent) \
- USE_VK_FUNC(vkCmdResetQueryPool) \
- USE_VK_FUNC(vkCmdResolveImage) \
- USE_VK_FUNC(vkCmdSetBlendConstants) \
- USE_VK_FUNC(vkCmdSetDepthBias) \
- USE_VK_FUNC(vkCmdSetDepthBounds) \
- USE_VK_FUNC(vkCmdSetEvent) \
- USE_VK_FUNC(vkCmdSetLineWidth) \
- USE_VK_FUNC(vkCmdSetScissor) \
- USE_VK_FUNC(vkCmdSetStencilCompareMask) \
- USE_VK_FUNC(vkCmdSetStencilReference) \
- USE_VK_FUNC(vkCmdSetStencilWriteMask) \
- USE_VK_FUNC(vkCmdSetViewport) \
- USE_VK_FUNC(vkCmdUpdateBuffer) \
- USE_VK_FUNC(vkCmdWaitEvents) \
- USE_VK_FUNC(vkCmdWriteTimestamp) \
- USE_VK_FUNC(vkCreateBuffer) \
- USE_VK_FUNC(vkCreateBufferView) \
- USE_VK_FUNC(vkCreateCommandPool) \
- USE_VK_FUNC(vkCreateComputePipelines) \
- USE_VK_FUNC(vkCreateDescriptorPool) \
- USE_VK_FUNC(vkCreateDescriptorSetLayout) \
- USE_VK_FUNC(vkCreateEvent) \
- USE_VK_FUNC(vkCreateFence) \
- USE_VK_FUNC(vkCreateFramebuffer) \
- USE_VK_FUNC(vkCreateGraphicsPipelines) \
- USE_VK_FUNC(vkCreateImage) \
- USE_VK_FUNC(vkCreateImageView) \
- USE_VK_FUNC(vkCreatePipelineCache) \
- USE_VK_FUNC(vkCreatePipelineLayout) \
- USE_VK_FUNC(vkCreateQueryPool) \
- USE_VK_FUNC(vkCreateRenderPass) \
- USE_VK_FUNC(vkCreateSampler) \
- USE_VK_FUNC(vkCreateSemaphore) \
- USE_VK_FUNC(vkCreateShaderModule) \
- USE_VK_FUNC(vkDestroyBuffer) \
- USE_VK_FUNC(vkDestroyBufferView) \
- USE_VK_FUNC(vkDestroyCommandPool) \
- USE_VK_FUNC(vkDestroyDescriptorPool) \
- USE_VK_FUNC(vkDestroyDescriptorSetLayout) \
- USE_VK_FUNC(vkDestroyDevice) \
- USE_VK_FUNC(vkDestroyEvent) \
- USE_VK_FUNC(vkDestroyFence) \
- USE_VK_FUNC(vkDestroyFramebuffer) \
- USE_VK_FUNC(vkDestroyImage) \
- USE_VK_FUNC(vkDestroyImageView) \
- USE_VK_FUNC(vkDestroyPipeline) \
- USE_VK_FUNC(vkDestroyPipelineCache) \
- USE_VK_FUNC(vkDestroyPipelineLayout) \
- USE_VK_FUNC(vkDestroyQueryPool) \
- USE_VK_FUNC(vkDestroyRenderPass) \
- USE_VK_FUNC(vkDestroySampler) \
- USE_VK_FUNC(vkDestroySemaphore) \
- USE_VK_FUNC(vkDestroyShaderModule) \
- USE_VK_FUNC(vkDeviceWaitIdle) \
- USE_VK_FUNC(vkEndCommandBuffer) \
- USE_VK_FUNC(vkFlushMappedMemoryRanges) \
- USE_VK_FUNC(vkFreeCommandBuffers) \
- USE_VK_FUNC(vkFreeDescriptorSets) \
- USE_VK_FUNC(vkFreeMemory) \
- USE_VK_FUNC(vkGetBufferMemoryRequirements) \
- USE_VK_FUNC(vkGetDeviceMemoryCommitment) \
- USE_VK_FUNC(vkGetDeviceQueue) \
- USE_VK_FUNC(vkGetEventStatus) \
- USE_VK_FUNC(vkGetFenceStatus) \
- USE_VK_FUNC(vkGetImageMemoryRequirements) \
- USE_VK_FUNC(vkGetImageSparseMemoryRequirements) \
- USE_VK_FUNC(vkGetImageSubresourceLayout) \
- USE_VK_FUNC(vkGetPipelineCacheData) \
- USE_VK_FUNC(vkGetQueryPoolResults) \
- USE_VK_FUNC(vkGetRenderAreaGranularity) \
- USE_VK_FUNC(vkInvalidateMappedMemoryRanges) \
- USE_VK_FUNC(vkMapMemory) \
- USE_VK_FUNC(vkMergePipelineCaches) \
- USE_VK_FUNC(vkQueueBindSparse) \
- USE_VK_FUNC(vkQueueSubmit) \
- USE_VK_FUNC(vkQueueWaitIdle) \
- USE_VK_FUNC(vkResetCommandBuffer) \
- USE_VK_FUNC(vkResetCommandPool) \
- USE_VK_FUNC(vkResetDescriptorPool) \
- USE_VK_FUNC(vkResetEvent) \
- USE_VK_FUNC(vkResetFences) \
- USE_VK_FUNC(vkSetEvent) \
- USE_VK_FUNC(vkUnmapMemory) \
- USE_VK_FUNC(vkUpdateDescriptorSets) \
- USE_VK_FUNC(vkWaitForFences)
#define ALL_VK_INSTANCE_FUNCS() \ USE_VK_FUNC(vkCreateDevice)\ USE_VK_FUNC(vkEnumerateDeviceExtensionProperties)\ diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index c3fed9e58a..c99ca66168 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -36,6 +36,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); +static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
static BOOL wine_vk_init(void) @@ -51,6 +52,7 @@ static BOOL wine_vk_init(void) #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(vulkan_handle, #f, NULL, 0)) == NULL) return FALSE; LOAD_FUNCPTR(vkCreateInstance) LOAD_FUNCPTR(vkDestroyInstance) +LOAD_FUNCPTR(vkGetDeviceProcAddr) LOAD_FUNCPTR(vkGetInstanceProcAddr) #undef LOAD_FUNCPTR
@@ -116,6 +118,12 @@ static VkResult X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_ return VK_SUCCESS; }
+static void * X11DRV_vkGetDeviceProcAddr(VkDevice device, const char *name) +{
- TRACE("%p, %s\n", device, debugstr_a(name));
- return pvkGetDeviceProcAddr(device, name);
+}
static void * X11DRV_vkGetInstanceProcAddr(VkInstance instance, const char *name) { TRACE("%p, %s\n", instance, debugstr_a(name)); @@ -127,6 +135,7 @@ static const struct vulkan_funcs vulkan_funcs = X11DRV_vkCreateInstance, X11DRV_vkDestroyInstance, X11DRV_vkEnumerateInstanceExtensionProperties,
- X11DRV_vkGetDeviceProcAddr, X11DRV_vkGetInstanceProcAddr
};
diff --git a/include/wine/vulkan_driver.h b/include/wine/vulkan_driver.h index 2e2abf9f02..8d69222e03 100644 --- a/include/wine/vulkan_driver.h +++ b/include/wine/vulkan_driver.h @@ -4,7 +4,7 @@ #define __WINE_VULKAN_DRIVER_H
/* Wine internal vulkan driver version, needs to be bumped upon vulkan_funcs changes. */ -#define WINE_VULKAN_DRIVER_VERSION 1 +#define WINE_VULKAN_DRIVER_VERSION 2
struct vulkan_funcs { @@ -15,6 +15,7 @@ struct vulkan_funcs VkResult (*p_vkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); void (*p_vkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); VkResult (*p_vkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *);
- void * (*p_vkGetDeviceProcAddr)(VkDevice, const char *); void * (*p_vkGetInstanceProcAddr)(VkInstance, const char *);
};
-- 2.14.3
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com --- dlls/winevulkan/make_vulkan | 2 +- dlls/winevulkan/vulkan.c | 22 ++++++++++++++++++++++ dlls/winevulkan/vulkan_thunks.c | 6 ------ dlls/winevulkan/vulkan_thunks.h | 1 + 4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 698d496a96..35f40c79ce 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -94,7 +94,7 @@ FUNCTION_OVERRIDES = { "vkEnumeratePhysicalDevices" : {"dispatch" : True, "driver" : False, "thunk" : False},
# Device functions - "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : True}, + "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : False}, }
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index d5fe25f36a..c3bf11ccfe 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -352,6 +352,28 @@ VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *d return res; }
+PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *name) +{ + void *func; + TRACE("%p, %s\n", device, debugstr_a(name)); + + /* The spec leaves return value undefined for a NULL device, let's just return NULL. */ + if (!device || !name) + return NULL; + + /* Per the spec, we are only supposed to return device functions as in functions + * for which the first parameter is vkDevice or a child of vkDevice like a + * vkCommandBuffer or vkQueue. + * Loader takes are of filtering of extensions which are enabled or not. + */ + func = wine_vk_get_device_proc_addr(name); + if (func) + return func; + + TRACE("Function %s not found\n", name); + return NULL; +} + static PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance, const char *name) { void *func; diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 99095c60f9..3c90686c59 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -690,12 +690,6 @@ static void WINAPI wine_vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMem FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(memory), pCommittedMemoryInBytes); }
-static PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *pName) -{ - FIXME("stub: %p, %p\n", device, pName); - return NULL; -} - static void WINAPI wine_vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { FIXME("stub: %p, %u, %u, %p\n", device, queueFamilyIndex, queueIndex, pQueue); diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 49a88968a2..8fd1491779 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -17,6 +17,7 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDev void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN; +PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *pName) DECLSPEC_HIDDEN;
typedef struct VkImageFormatProperties_host {
On Thu, Mar 8, 2018 at 7:57 AM, Roderick Colenbrander thunderbird2k@gmail.com wrote:
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com
dlls/winevulkan/make_vulkan | 2 +- dlls/winevulkan/vulkan.c | 22 ++++++++++++++++++++++ dlls/winevulkan/vulkan_thunks.c | 6 ------ dlls/winevulkan/vulkan_thunks.h | 1 + 4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 698d496a96..35f40c79ce 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -94,7 +94,7 @@ FUNCTION_OVERRIDES = { "vkEnumeratePhysicalDevices" : {"dispatch" : True, "driver" : False, "thunk" : False},
# Device functions
- "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : True},
- "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : False},
}
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index d5fe25f36a..c3bf11ccfe 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -352,6 +352,28 @@ VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *d return res; }
+PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *name) +{
- void *func;
- TRACE("%p, %s\n", device, debugstr_a(name));
- /* The spec leaves return value undefined for a NULL device, let's just return NULL. */
- if (!device || !name)
return NULL;
- /* Per the spec, we are only supposed to return device functions as in functions
* for which the first parameter is vkDevice or a child of vkDevice like a
* vkCommandBuffer or vkQueue.
* Loader takes are of filtering of extensions which are enabled or not.
*/
- func = wine_vk_get_device_proc_addr(name);
- if (func)
return func;
- TRACE("Function %s not found\n", name);
debugstr_a(name)
- return NULL;
+}
static PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance, const char *name) { void *func; diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 99095c60f9..3c90686c59 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -690,12 +690,6 @@ static void WINAPI wine_vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMem FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(memory), pCommittedMemoryInBytes); }
-static PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *pName) -{
- FIXME("stub: %p, %p\n", device, pName);
- return NULL;
-}
static void WINAPI wine_vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) { FIXME("stub: %p, %u, %u, %p\n", device, queueFamilyIndex, queueIndex, pQueue); diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 49a88968a2..8fd1491779 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -17,6 +17,7 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDev void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN; +PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *pName) DECLSPEC_HIDDEN;
typedef struct VkImageFormatProperties_host { -- 2.14.3
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com --- dlls/winevulkan/make_vulkan | 1 + dlls/winevulkan/vulkan.c | 10 ++++++++++ dlls/winevulkan/vulkan_thunks.c | 5 ----- dlls/winevulkan/vulkan_thunks.h | 1 + 4 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 35f40c79ce..8f1ebeb146 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -94,6 +94,7 @@ FUNCTION_OVERRIDES = { "vkEnumeratePhysicalDevices" : {"dispatch" : True, "driver" : False, "thunk" : False},
# Device functions + "vkDestroyDevice" : {"dispatch" : True, "driver" : False, "thunk" : False}, "vkGetDeviceProcAddr" : {"dispatch" : True, "driver" : True, "thunk" : False}, }
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index c3bf11ccfe..579f1342d5 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -271,6 +271,16 @@ err: return res; }
+void WINAPI wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *allocator) +{ + TRACE("%p %p\n", device, allocator); + + if (allocator) + FIXME("Support for allocation callbacks not implemented yet\n"); + + wine_vk_device_free(device); +} + void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator) { TRACE("%p, %p\n", instance, allocator); diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 3c90686c59..d6c36e9fc7 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -570,11 +570,6 @@ static void WINAPI wine_vkDestroyDescriptorSetLayout(VkDevice device, VkDescript FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(descriptorSetLayout), pAllocator); }
-static void WINAPI wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) -{ - FIXME("stub: %p, %p\n", device, pAllocator); -} - static void WINAPI wine_vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) { FIXME("stub: %p, 0x%s, %p\n", device, wine_dbgstr_longlong(event), pAllocator); diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 8fd1491779..8d49404cb1 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -14,6 +14,7 @@ void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
/* Functions for which we have custom implementations outside of the thunks. */ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) DECLSPEC_HIDDEN; +void WINAPI wine_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN;