Hi all,
This is a resubmit of the series based on feedback from Jozef. While looking over his feedback found a few other tiny things like another 'void*' and 'pName' in some print, which I fixed as well.
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 | 807 ++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan.c | 106 ++++- dlls/winevulkan/vulkan_private.h | 8 + dlls/winevulkan/vulkan_thunks.c | 998 ++++++++++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_thunks.h | 415 ++++++++++++++++ dlls/winex11.drv/vulkan.c | 9 + include/wine/vulkan_driver.h | 3 +- 7 files changed, 2322 insertions(+), 24 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..12ea0a3f62 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. + Functions 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 underlying '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("TODO: 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 x86 platforms. */\n") + f.write("#if (defined(__i386__))\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..4ae102b83b 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 x86 platforms. */ +#if (defined(__i386__)) + #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 *); };
Signed-off-by: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com
Signed-off-by: Józef Kucia jkucia@codeweavers.com
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 | 41 ++- dlls/winevulkan/vulkan.c | 4 + dlls/winevulkan/vulkan_thunks.c | 793 +++++++++++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_thunks.h | 1 + 4 files changed, 831 insertions(+), 8 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 12ea0a3f62..abeab675df 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 name=%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") @@ -1730,7 +1756,7 @@ class VkGenerator(object): f.write(" {\n") f.write(" if (strcmp(vk_instance_dispatch_table[i].name, name) == 0)\n") f.write(" {\n") - f.write(" TRACE("Found pName=%s in instance table\n", name);\n") + f.write(" TRACE("Found name=%s in instance table\n", name);\n") f.write(" return vk_instance_dispatch_table[i].func;\n") f.write(" }\n") f.write(" }\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..5fdbffaa62 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 name=%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; @@ -281,7 +1072,7 @@ void *wine_vk_get_instance_proc_addr(const char *name) { if (strcmp(vk_instance_dispatch_table[i].name, name) == 0) { - TRACE("Found pName=%s in instance table\n", name); + TRACE("Found name=%s in instance table\n", name); return vk_instance_dispatch_table[i].func; } } diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 4ae102b83b..e7f0ab6dbc 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 | 70 ++++++++++- 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, 371 insertions(+), 12 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index abeab675df..afb379901e 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..83c94eb856 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 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 sanitize 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) { @@ -178,7 +246,7 @@ static VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_ * ICD may support. */ #define USE_VK_FUNC(name) \ - object->funcs.p_##name = (void*)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name); + object->funcs.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name); ALL_VK_INSTANCE_FUNCS() #undef USE_VK_FUNC
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 5fdbffaa62..f02ee3e2bf 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 e7f0ab6dbc..0a30090a57 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 *); };
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 afb379901e..b86ecd4c55 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 83c94eb856..ee877e0f80 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", 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 f02ee3e2bf..13a5d5d7ea 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 0a30090a57..d137a2b34f 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 {
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 b86ecd4c55..a5b25c7dac 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 ee877e0f80..678506fbb0 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 13a5d5d7ea..3670926c3e 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 d137a2b34f..fab1215a59 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;