Current solution of _set_direction() is very imprecise. This MR replaces it with more precise needs_conversion() functions. It already fixes a few cases and will be more important in the future, when we will use more generated conversion functions.
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 3 --- dlls/winevulkan/vulkan_thunks.c | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index d7b253020b4..aa44f444fbf 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -1728,9 +1728,6 @@ class VkParam(VkVariable): def needs_unwrapping(self): """ Returns if parameter needs unwrapping of handle. """
- if self.func.needs_private_thunk(): - return False - # Wrapped handle parameters are handled separately, only look for wrapped handles in structs if self.is_struct(): return self.struct.needs_unwrapping() diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 6bc56df790f..5d6835d2290 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -2136,13 +2136,13 @@ static inline void convert_VkPhysicalDeviceProperties2_host_to_win32(const VkPhy #endif /* USE_STRUCT_CONVERSION */
#if defined(USE_STRUCT_CONVERSION) -static inline void convert_VkPhysicalDeviceSurfaceInfo2KHR_win32_to_host(const VkPhysicalDeviceSurfaceInfo2KHR *in, VkPhysicalDeviceSurfaceInfo2KHR_host *out) +static inline void convert_VkPhysicalDeviceSurfaceInfo2KHR_win32_to_unwrapped_host(const VkPhysicalDeviceSurfaceInfo2KHR *in, VkPhysicalDeviceSurfaceInfo2KHR_host *out) { if (!in) return;
out->sType = in->sType; out->pNext = in->pNext; - out->surface = wine_surface_from_handle(in->surface)->driver_surface; + out->surface = in->surface; } #endif /* USE_STRUCT_CONVERSION */
@@ -2157,6 +2157,17 @@ static inline void convert_VkPhysicalDeviceSurfaceInfo2KHR_win64_to_host(const V } #endif /* USE_STRUCT_CONVERSION */
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkPhysicalDeviceSurfaceInfo2KHR_win32_to_host(const VkPhysicalDeviceSurfaceInfo2KHR *in, VkPhysicalDeviceSurfaceInfo2KHR_host *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->surface = wine_surface_from_handle(in->surface)->driver_surface; +} +#endif /* USE_STRUCT_CONVERSION */ + #if defined(USE_STRUCT_CONVERSION) static inline void convert_VkPipelineExecutableInfoKHR_win32_to_host(const VkPipelineExecutableInfoKHR *in, VkPipelineExecutableInfoKHR_host *out) { @@ -17032,7 +17043,7 @@ static NTSTATUS thunk32_vkGetPhysicalDeviceSurfaceCapabilities2KHR(void *args)
TRACE("%p, %p, %p\n", params->physicalDevice, params->pSurfaceInfo, params->pSurfaceCapabilities);
- convert_VkPhysicalDeviceSurfaceInfo2KHR_win32_to_host(params->pSurfaceInfo, &pSurfaceInfo_host); + convert_VkPhysicalDeviceSurfaceInfo2KHR_win32_to_unwrapped_host(params->pSurfaceInfo, &pSurfaceInfo_host); params->result = wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(params->physicalDevice, &pSurfaceInfo_host, params->pSurfaceCapabilities); return STATUS_SUCCESS; }
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 82 +++++++++++++++---------------------- 1 file changed, 33 insertions(+), 49 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index aa44f444fbf..cc081450164 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -587,10 +587,7 @@ class VkFunction(object): vk_param = VkParam.from_xml(param, types) params.append(vk_param)
- func = VkFunction(_type=func_type, name=func_name, params=params) - for param in params: - param.set_conversions(func) - return func + 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. @@ -813,7 +810,7 @@ class VkFunction(object): # Call any win_to_host conversion calls. unwrap = self.thunk_type == ThunkType.PUBLIC for p in self.params: - if p.needs_input_conversion(conv) and (conv or (unwrap and p.needs_unwrapping())): + if p.needs_input_conversion(conv, unwrap): body += p.copy(Direction.INPUT, conv, unwrap, prefix=params_prefix)
# Build list of parameters containing converted and non-converted parameters. @@ -834,11 +831,8 @@ class VkFunction(object): body += " {0}result = {1}{2}({3});\n".format(params_prefix, func_prefix, self.name, params)
# Call any host_to_win conversion calls. - if conv: - for p in self.params: - if not p.needs_output_conversion(conv): - continue - + for p in self.params: + if p.needs_output_conversion(conv, unwrap): body += p.copy(Direction.OUTPUT, conv, unwrap, prefix=params_prefix)
if needs_alloc: @@ -1483,33 +1477,6 @@ class VkParam(VkVariable):
return VkParam(type_info, const=const, pointer=pointer, name=name, array_len=array_len, dyn_array_len=dyn_array_len, object_type=object_type, optional=optional)
- def set_conversions(self, func): - """ Internal helper function to configure any needed conversion functions. """ - - self.func = func - self.input_conv = None - self.input_unwrap = None - self.output_conv = None - self.output_unwrap = None - - unwrap = func.thunk_type == ThunkType.PUBLIC; - - # Input functions require win to host conversion. - if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]: - if unwrap and self.needs_unwrapping(): - self.input_unwrap = ConversionFunction(self, Direction.INPUT, False, True) - self.input_conv = ConversionFunction(self, Direction.INPUT, True, True) - elif self.needs_conversion(): - self.input_conv = ConversionFunction(self, Direction.INPUT, True, unwrap or not self.needs_unwrapping()) - - # Output functions require host to win conversion. - if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]: - if unwrap and self.needs_unwrapping(): - self.output_conv = ConversionFunction(self, Direction.OUTPUT, False) - self.output_conv = ConversionFunction(self, Direction.OUTPUT, True) - elif self.needs_conversion(): - self.output_conv = ConversionFunction(self, Direction.OUTPUT, True, unwrap or not self.needs_unwrapping()) - def _set_direction(self): """ Internal helper function to set parameter direction (input/output/input_output). """
@@ -1688,14 +1655,23 @@ class VkParam(VkVariable): conversions.extend(m.get_conversions(func))
# Conversion requirements for the 'parent' parameter. - if self.input_unwrap is not None: - conversions.append(self.input_unwrap) - if self.input_conv is not None: - conversions.append(self.input_conv) - if self.output_unwrap is not None: - conversions.append(self.output_unwrap) - if self.output_conv is not None: - conversions.append(self.output_conv) + unwrap = func.thunk_type == ThunkType.PUBLIC; + + # Input functions require win to host conversion. + if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]: + if unwrap and self.needs_unwrapping(): + conversions.append(ConversionFunction(self, Direction.INPUT, False, True)) + conversions.append(ConversionFunction(self, Direction.INPUT, True, True)) + elif self.needs_conversion(): + conversions.append(ConversionFunction(self, Direction.INPUT, True, unwrap or not self.needs_unwrapping())) + + # Output functions require host to win conversion. + if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]: + if unwrap and self.needs_unwrapping(): + conversions.append(ConversionFunction(self, Direction.OUTPUT, False)) + conversions.append(ConversionFunction(self, Direction.OUTPUT, True)) + elif self.needs_conversion(): + conversions.append(ConversionFunction(self, Direction.OUTPUT, True, unwrap or not self.needs_unwrapping()))
return conversions
@@ -1737,11 +1713,19 @@ class VkParam(VkVariable):
return False
- def needs_input_conversion(self, conv): - return (self.input_conv if conv else self.input_unwrap) is not None + def needs_input_conversion(self, conv, unwrap): + if not self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]: + return False + if unwrap and self.needs_unwrapping(): + return True + return conv and self.needs_conversion()
- def needs_output_conversion(self, conv): - return (self.output_conv if conv else self.output_unwrap) is not None + def needs_output_conversion(self, conv, unwrap): + if not self._direction in [Direction.OUTPUT, Direction.INPUT_OUTPUT]: + return False + if unwrap and self.needs_unwrapping(): + return True + return conv and self.needs_conversion()
def spec(self): """ Generate spec file entry for this parameter. """
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 43 ++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 13 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index cc081450164..6d86bb322e8 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -711,7 +711,7 @@ class VkFunction(object): pfn += param.const + " "
pfn += param.type - if conv and param.needs_conversion(): + if conv and param.needs_host_type(): pfn += "_host"
if param.is_pointer(): @@ -780,7 +780,7 @@ class VkFunction(object):
# Declare any tmp parameters for conversion. for p in self.params: - if p.needs_conversion() and conv: + if p.needs_host_type() and conv: if p.is_dynamic_array(): body += " {0}_host *{1}_host;\n".format(p.type, p.name) else: @@ -1206,6 +1206,10 @@ class VkVariable(object):
return self.is_struct() and self.struct.needs_alloc(conv, unwrap)
+ def needs_host_type(self): + return self.is_struct() and self.struct.needs_host_type() + + class VkMember(VkVariable): def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None, dyn_array_len=None, optional=False, values=None, object_type=None, bit_width=None): @@ -1580,7 +1584,7 @@ class VkParam(VkVariable):
proto += self.type name = self.name - if is_thunk and self.needs_conversion(): + if is_thunk and self.needs_host_type(): proto += "_host"
if is_member and self.needs_alignment(): @@ -1687,13 +1691,6 @@ class VkParam(VkVariable): if not self.is_struct(): return False
- # VkSparseImageMemoryRequirements(2) is used by vkGetImageSparseMemoryRequirements(2). - # This function is tricky to wrap, because how to wrap depends on whether - # pSparseMemoryRequirements is NULL or not. Luckily for VkSparseImageMemoryRequirements(2) - # the alignment works out in such a way that no conversion is needed between win32 and Linux. - if self.type in ["VkSparseImageMemoryRequirements", "VkSparseImageMemoryRequirements2"]: - 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(): @@ -1956,6 +1953,13 @@ class VkStruct(Sequence): or if they include other structures which need alignment. """
+ # VkSparseImageMemoryRequirements(2) is used by vkGetImageSparseMemoryRequirements(2). + # This function is tricky to wrap, because how to wrap depends on whether + # pSparseMemoryRequirements is NULL or not. Luckily for VkSparseImageMemoryRequirements(2) + # the alignment works out in such a way that no conversion is needed between win32 and Linux. + if self.name in ["VkSparseImageMemoryRequirements", "VkSparseImageMemoryRequirements2"]: + return False + if self.needs_alignment(): return True
@@ -1987,6 +1991,19 @@ class VkStruct(Sequence):
return False
+ def needs_host_type(self): + # FIXME: Remove once we don't need need it + if self.name in ["VkSparseImageMemoryRequirements", "VkSparseImageMemoryRequirements2"]: + return False + + for m in self.members: + if self.name == m.type: + continue + if m.needs_alignment(): + return True + if m.is_struct() and m.struct.needs_host_type(): + return True + def needs_struct_extensions_conversion(self): """ Checks if structure extensions in pNext chain need conversion. """ ret = False @@ -2037,7 +2054,7 @@ class ConversionFunction(object): else: body += "#if !defined(USE_STRUCT_CONVERSION)\n"
- if self.conv and self.operand.needs_conversion(): + if self.conv and isinstance(self.operand, VkStruct) and self.operand.needs_host_type(): host_type = "{0}_host".format(self.type) else: host_type = self.type @@ -2549,7 +2566,7 @@ class VkGenerator(object): LOGGER.debug("skipping {0} in vulkan_device_funcs".format(vk_func.name)) continue
- f.write(" {0};\n".format(vk_func.pfn(conv=vk_func.needs_conversion()))) + f.write(" {0};\n".format(vk_func.pfn(conv=True))) f.write("};\n\n")
f.write("/* For use by vkInstance and children */\n") @@ -2562,7 +2579,7 @@ 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=vk_func.needs_conversion()))) + f.write(" {0};\n".format(vk_func.pfn(conv=True))) f.write("};\n\n")
f.write("#define ALL_VK_DEVICE_FUNCS() \\n")
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 6d86bb322e8..54a47fda553 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -654,19 +654,6 @@ class VkFunction(object): def returns_longlong(self): return self.type in ["uint64_t", "VkDeviceAddress"]
- 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_unwrapping(self): """ Check if the function needs any input/output type unwrapping. Functions need input/output unwrapping if struct parameters have @@ -1098,9 +1085,6 @@ class VkHandle(object): def is_wrapped(self): return self.native_handle("test") is not None
- def needs_conversion(self): - return False - def needs_unwrapping(self): return self.is_wrapped()
@@ -1384,20 +1368,17 @@ class VkMember(VkVariable): def get_conversions(self, func=None): """ 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() and not self.needs_unwrapping(): - return None - conversions = []
# Collect any conversion for any member structs. if self.is_struct(): struct = self.type_info["data"] for m in struct: + if m.type == struct.name: + continue + m.needs_struct_extensions_conversion() - if m.needs_conversion() or m.needs_unwrapping(): - conversions.extend(m.get_conversions(func)) + conversions.extend(m.get_conversions(func))
struct.needs_struct_extensions_conversion() direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT @@ -1640,9 +1621,6 @@ class VkParam(VkVariable): elif not self.is_handle(): return None
- if not self.needs_conversion() and not self.needs_unwrapping(): - return None - conversions = []
# Collect any member conversions first, so we can guarantee @@ -1653,9 +1631,6 @@ class VkParam(VkVariable): if not m.is_struct(): continue
- if not m.needs_conversion() and not m.needs_unwrapping(): - continue - conversions.extend(m.get_conversions(func))
# Conversion requirements for the 'parent' parameter. @@ -2334,9 +2309,6 @@ class VkGenerator(object): if not func.is_required(): continue
- if not func.needs_conversion() and not func.needs_unwrapping(): - continue - conversions = func.get_conversions() for conv in conversions: # Append if we don't already have this conversion.
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 54a47fda553..0d5e33e2a42 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -1090,7 +1090,7 @@ class VkHandle(object):
class VkVariable(object): def __init__(self, const=False, type_info=None, type=None, name=None, pointer=None, array_len=None, - dyn_array_len=None, object_type=None, optional=False): + dyn_array_len=None, object_type=None, optional=False, returnedonly=False): self.const = const self.type_info = type_info self.type = type @@ -1100,6 +1100,7 @@ class VkVariable(object): self.dyn_array_len = dyn_array_len self.object_type = object_type self.optional = optional + self.returnedonly = returnedonly if type_info: self.set_type_info(type_info)
@@ -1196,9 +1197,11 @@ class VkVariable(object):
class VkMember(VkVariable): def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None, - dyn_array_len=None, optional=False, values=None, object_type=None, bit_width=None): + dyn_array_len=None, optional=False, values=None, object_type=None, bit_width=None, + returnedonly=False): VkVariable.__init__(self, const=const, type=_type, name=name, pointer=pointer, array_len=array_len, - dyn_array_len=dyn_array_len, object_type=object_type, optional=optional) + dyn_array_len=dyn_array_len, object_type=object_type, optional=optional, + returnedonly=returnedonly) self.struct_fwd_decl = struct_fwd_decl self.values = values self.bit_width = bit_width @@ -1217,7 +1220,7 @@ class VkMember(VkVariable): self.name, self.array_len, self.dyn_array_len)
@staticmethod - def from_xml(member): + def from_xml(member, returnedonly): """ Helper function for parsing a member tag within a struct or union. """
name_elem = member.find("name") @@ -1280,8 +1283,9 @@ class VkMember(VkVariable): LOGGER.debug("Found bit field") bit_width = int(name_elem.tail[1:])
- return VkMember(const=const, struct_fwd_decl=struct_fwd_decl, _type=member_type, pointer=pointer, name=name_elem.text, - array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, values=values, object_type=object_type, bit_width=bit_width) + return VkMember(const=const, struct_fwd_decl=struct_fwd_decl, _type=member_type, pointer=pointer, + name=name_elem.text, array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, + values=values, object_type=object_type, bit_width=bit_width, returnedonly=returnedonly)
def copy(self, input, output, direction, conv, unwrap): """ Helper method for use by conversion logic to generate a C-code statement to copy this member. @@ -1804,7 +1808,7 @@ class VkStruct(Sequence):
members = [] for member in struct.findall("member"): - vk_member = VkMember.from_xml(member) + vk_member = VkMember.from_xml(member, returnedonly) members.append(vk_member)
return VkStruct(name, members, returnedonly, structextends, union=union)
From: Jacek Caban jacek@codeweavers.com
Instead of using pre-calculated heuristics. --- dlls/winevulkan/make_vulkan | 285 ++++++++++++++++---------------- dlls/winevulkan/vulkan_thunks.c | 42 +++++ 2 files changed, 189 insertions(+), 138 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 0d5e33e2a42..becd456bbee 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -598,10 +598,7 @@ class VkFunction(object):
conversions = [] for param in self.params: - convs = param.get_conversions(self) - if convs is not None: - conversions.extend(convs) - + conversions.extend(param.get_conversions(self.thunk_type == ThunkType.PUBLIC)) return conversions
def is_alias(self): @@ -797,7 +794,7 @@ class VkFunction(object): # Call any win_to_host conversion calls. unwrap = self.thunk_type == ThunkType.PUBLIC for p in self.params: - if p.needs_input_conversion(conv, unwrap): + if p.needs_conversion(conv, unwrap, Direction.INPUT): body += p.copy(Direction.INPUT, conv, unwrap, prefix=params_prefix)
# Build list of parameters containing converted and non-converted parameters. @@ -819,7 +816,7 @@ class VkFunction(object):
# Call any host_to_win conversion calls. for p in self.params: - if p.needs_output_conversion(conv, unwrap): + if p.needs_conversion(conv, unwrap, Direction.OUTPUT): body += p.copy(Direction.OUTPUT, conv, unwrap, prefix=params_prefix)
if needs_alloc: @@ -1165,29 +1162,11 @@ class VkVariable(object): return not self.handle.is_dispatchable() return False
- def needs_conversion(self): - """ Structures requiring alignment, need conversion between win32 and host. """ - return self.struct.needs_conversion() if self.is_struct() else False - - def needs_unwrapping(self): - """ Structures with wrapped handles need unwrapping. """ - - if self.is_struct(): - return self.struct.needs_unwrapping() - - if self.is_handle(): - return self.handle.is_wrapped() - - if self.is_generic_handle(): - return True - - return False - def needs_alloc(self, conv, unwrap): """ Returns True if conversion needs allocation """ if self.is_dynamic_array(): - if (conv and self.needs_conversion()) or (unwrap and self.needs_unwrapping()): - return True + return self.needs_conversion(conv, unwrap, Direction.INPUT, False) \ + or self.needs_conversion(conv, unwrap, Direction.OUTPUT, False)
return self.is_struct() and self.struct.needs_alloc(conv, unwrap)
@@ -1292,7 +1271,7 @@ class VkMember(VkVariable): - `conv` indicates whether the statement is in a struct alignment conversion path. """
win_type = "win32" if conv else "win64" - if (conv and self.needs_conversion()) or (unwrap and self.needs_unwrapping()): + if self.needs_conversion(conv, unwrap, direction, False): 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)) @@ -1369,7 +1348,7 @@ class VkMember(VkVariable):
return text
- def get_conversions(self, func=None): + def get_conversions(self, unwrap, parent_const): """ Return any conversion description for this member and its children when conversion is needed. """
conversions = [] @@ -1382,19 +1361,18 @@ class VkMember(VkVariable): continue
m.needs_struct_extensions_conversion() - conversions.extend(m.get_conversions(func)) + conversions.extend(m.get_conversions(parent_const, unwrap))
struct.needs_struct_extensions_conversion() direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT elif self.is_handle() or self.is_generic_handle(): direction = Direction.INPUT + else: + return []
- unwrap = not func or func.thunk_type == ThunkType.PUBLIC - if unwrap and self.needs_unwrapping(): - conversions.append(ConversionFunction(self, direction, False, True)) - conversions.append(ConversionFunction(self, direction, True, True)) - elif self.needs_conversion(): - conversions.append(ConversionFunction(self, direction, True, unwrap or not self.needs_unwrapping())) + for conv in [False, True]: + if self.needs_conversion(conv, unwrap, direction, parent_const): + conversions.append(ConversionFunction(self, direction, conv, unwrap))
return conversions
@@ -1407,6 +1385,52 @@ class VkMember(VkVariable): def is_bit_field(self): return self.bit_width is not None
+ def needs_unwrapping(self): + """ Structures with wrapped handles need unwrapping. """ + + if self.is_struct(): + return self.struct.needs_unwrapping() + + if self.is_handle(): + return self.handle.is_wrapped() + + if self.is_generic_handle(): + return True + + return False + + def needs_conversion(self, conv, unwrap, direction, struct_const): + """ Check if member needs conversion. """ + + is_const = self.is_const() if self.is_pointer() else struct_const + + # const members don't needs output conversion unless they are structs with non-const pointers + if direction == Direction.OUTPUT and is_const and not self.is_struct(): + return False + + if direction == Direction.INPUT: + # returnedonly members don't needs input conversions + if not self.is_pointer() and self.returnedonly: + return False + + if self.is_handle(): + if unwrap and self.handle.is_wrapped(): + return True + elif self.is_generic_handle(): + if unwrap: + return True + elif self.is_struct(): + if self.struct.needs_conversion(conv, unwrap, direction, is_const): + return True + + # if pointer member needs output conversion, it also needs input conversion + # to allocate the pointer + if direction == Direction.INPUT and self.is_pointer() and \ + self.needs_conversion(conv, unwrap, Direction.OUTPUT, struct_const): + return True + + return False + def needs_struct_extensions_conversion(self): if not self.is_struct(): return False @@ -1422,7 +1446,6 @@ class VkParam(VkVariable): pointer=pointer, array_len=array_len, dyn_array_len=dyn_array_len, object_type=object_type, optional=optional)
- self._set_direction() self._set_format_string()
def __repr__(self): @@ -1466,37 +1489,6 @@ class VkParam(VkVariable):
return VkParam(type_info, const=const, pointer=pointer, name=name, array_len=array_len, dyn_array_len=dyn_array_len, object_type=object_type, optional=optional)
- 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. """
@@ -1592,14 +1584,6 @@ class VkParam(VkVariable):
return proto
- def direction(self): - """ Returns parameter direction: input, output, input_output. - - Parameter direction in Vulkan is not straight-forward, which this function determines. - """ - - return self._direction - def dispatch_table(self, params_prefix=""): """ Return functions dispatch table pointer for dispatchable objects. """
@@ -1611,7 +1595,7 @@ class VkParam(VkVariable): def format_string(self): return self.format_str
- def get_conversions(self, func): + def get_conversions(self, unwrap): """ 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 @@ -1623,7 +1607,7 @@ class VkParam(VkVariable): for m in self.struct: m.needs_struct_extensions_conversion() elif not self.is_handle(): - return None + return []
conversions = []
@@ -1635,26 +1619,14 @@ class VkParam(VkVariable): if not m.is_struct(): continue
- conversions.extend(m.get_conversions(func)) + conversions.extend(m.get_conversions(unwrap, False))
# Conversion requirements for the 'parent' parameter. - unwrap = func.thunk_type == ThunkType.PUBLIC; - - # Input functions require win to host conversion. - if self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]: - if unwrap and self.needs_unwrapping(): - conversions.append(ConversionFunction(self, Direction.INPUT, False, True)) - conversions.append(ConversionFunction(self, Direction.INPUT, True, True)) - elif self.needs_conversion(): - conversions.append(ConversionFunction(self, Direction.INPUT, True, unwrap or not self.needs_unwrapping())) - - # Output functions require host to win conversion. - if self._direction in [Direction.INPUT_OUTPUT, Direction.OUTPUT]: - if unwrap and self.needs_unwrapping(): - conversions.append(ConversionFunction(self, Direction.OUTPUT, False)) - conversions.append(ConversionFunction(self, Direction.OUTPUT, True)) - elif self.needs_conversion(): - conversions.append(ConversionFunction(self, Direction.OUTPUT, True, unwrap or not self.needs_unwrapping())) + for conv in [False, True]: + if self.needs_conversion(conv, unwrap, Direction.INPUT): + conversions.append(ConversionFunction(self, Direction.INPUT, conv, unwrap)) + if self.needs_conversion(conv, unwrap, Direction.OUTPUT): + conversions.append(ConversionFunction(self, Direction.OUTPUT, conv, unwrap))
return conversions
@@ -1664,17 +1636,40 @@ class VkParam(VkVariable):
return self.handle.is_dispatchable()
- def needs_conversion(self): - """ Returns if parameter needs conversion between win32 and host. """ + def needs_conversion(self, conv, unwrap, direction, parent_const=False): + """ Check if param needs conversion. """
- if not self.is_struct(): + if self.is_struct(): + if self.struct.needs_conversion(conv, unwrap, direction, self.is_const()): + return True + # we needs input conversion of structs containing struct chain even if it's returnedonly + if direction == Direction.INPUT and ("pNext" in self.struct) and \ + self.struct.needs_conversion(conv, unwrap, Direction.OUTPUT, self.is_const()): + return True 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 + if self.is_handle(): + # non-array handles are handled inline in thunks + if not self.is_dynamic_array() and not self.is_static_array(): + return False + + # vkAllocateCommandBuffers is a special case, we use it in our private thunk as an input param + param_direction = (Direction.INPUT if self.is_const() else Direction.OUTPUT) + if self.name == "pCommandBuffers": + param_direction = Direction.INPUT + if direction != param_direction: + return False + + if unwrap and self.handle.is_wrapped(): + return True + + return False
+ def needs_variable(self, conv, unwrap): + if self.needs_conversion(conv, unwrap, Direction.INPUT): + return True + if self.needs_conversion(conv, unwrap, Direction.OUTPUT): + return True return False
def needs_unwrapping(self): @@ -1689,20 +1684,6 @@ class VkParam(VkVariable):
return False
- def needs_input_conversion(self, conv, unwrap): - if not self._direction in [Direction.INPUT, Direction.INPUT_OUTPUT]: - return False - if unwrap and self.needs_unwrapping(): - return True - return conv and self.needs_conversion() - - def needs_output_conversion(self, conv, unwrap): - if not self._direction in [Direction.OUTPUT, Direction.INPUT_OUTPUT]: - return False - if unwrap and self.needs_unwrapping(): - return True - return conv and self.needs_conversion() - def spec(self): """ Generate spec file entry for this parameter. """
@@ -1744,7 +1725,7 @@ class VkParam(VkVariable): LOGGER.debug("TODO: setting NULL VkAllocationCallbacks for {0}".format(self.name)) return "NULL"
- if (unwrap and self.needs_unwrapping()) or (conv and self.needs_conversion()): + if self.needs_variable(conv, unwrap): if self.is_dynamic_array(): return "{0}_host".format(self.name) else: @@ -1892,7 +1873,7 @@ class VkStruct(Sequence): for m in self: if align and m.needs_alignment(): text += " {0};\n".format(m.definition(align=align)) - elif conv and m.needs_conversion(): + elif conv and m.needs_host_type(): text += " {0};\n".format(m.definition(conv=conv)) else: text += " {0};\n".format(m.definition()) @@ -1926,11 +1907,22 @@ 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. - """ + def needs_unwrapping(self): + """ Returns if struct members need unwrapping of handle. """ + + for m in self.members: + if self.name == m.type: + continue + if m.needs_unwrapping(): + return True + return False + + def needs_conversion(self, conv, unwrap, direction, is_const): + """ Check if struct needs conversion. """ + + # VkAllocationCallbacks never needs conversion + if self.name == "VkAllocationCallbacks": + return False
# VkSparseImageMemoryRequirements(2) is used by vkGetImageSparseMemoryRequirements(2). # This function is tricky to wrap, because how to wrap depends on whether @@ -1939,24 +1931,41 @@ class VkStruct(Sequence): if self.name in ["VkSparseImageMemoryRequirements", "VkSparseImageMemoryRequirements2"]: return False
- if self.needs_alignment(): - return True + # FIXME: we can't handle output dynamic arrays yet, remove once we can handle it + if direction == Direction.OUTPUT and self.name in ["VkDeviceFaultInfoEXT", + "VkDeviceFaultAddressInfoEXT", + "VkDeviceFaultVendorInfoEXT"]: + return False + + # pFixedRateFlags field is missing const, but it doesn't need output conversion + if direction == Direction.OUTPUT and self.name == "VkImageCompressionControlEXT": + return False
for m in self.members: if self.name == m.type: continue - if m.needs_conversion(): - return True - return False
- def needs_unwrapping(self): - """ Returns if struct members need unwrapping of handle. """ - - for m in self.members: - if self.name == m.type: + if m.name == "pNext": continue - if m.needs_unwrapping(): + + # for non-pointer members, check for returnedonly and const attributes + if not m.is_pointer() or m.type == "void": + if direction == Direction.INPUT: + if self.returnedonly: + continue + else: + if is_const or m.is_const(): + continue + + # check alignment for 32-bit conversions + if conv and (direction == Direction.INPUT or not is_const): + # we don't check structs here, they will will be traversed by needs_conversion chain anyway + if not m.is_struct() and m.needs_alignment(): + return True + + if m.needs_conversion(conv, unwrap, direction, is_const): return True + return False
def needs_alloc(self, conv, unwrap): @@ -1988,7 +1997,7 @@ class VkStruct(Sequence): ret = False
for e in self.struct_extensions: - if e.required and e.needs_conversion(): + if e.required and e.needs_conversion(True, True, Direction.INPUT, False): LOGGER.error("Unhandled pNext chain alignment conversion for {0}".format(e.name)) ret = True if e.required and e.needs_unwrapping(): @@ -2015,7 +2024,7 @@ class ConversionFunction(object): self.operand = variable.struct if variable.is_struct() else variable.handle self.type = variable.type self.conv = conv - self.unwrap = unwrap + self.unwrap = unwrap or not self.operand.needs_unwrapping() self.needs_alloc = direction != Direction.OUTPUT and variable.needs_alloc(conv, unwrap)
self._set_name() @@ -2333,8 +2342,8 @@ class VkGenerator(object): # Once we decide to support pNext chains conversion everywhere, move this under get_conversions for e in struct.struct_extensions: for m in e: - if m.needs_conversion() or m.needs_unwrapping(): - conversions = m.get_conversions() + if m.needs_conversion(True, True, Direction.INPUT, False): + conversions = m.get_conversions(True, False) for conv in conversions: if not any(c == conv for c in self.conversions): self.conversions.append(conv) diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 5d6835d2290..b52f5f30da0 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -1526,6 +1526,19 @@ static inline void convert_VkAccelerationStructureBuildSizesInfoKHR_win32_to_hos } #endif /* USE_STRUCT_CONVERSION */
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkAccelerationStructureBuildSizesInfoKHR_host_to_win32(const VkAccelerationStructureBuildSizesInfoKHR_host *in, VkAccelerationStructureBuildSizesInfoKHR *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->accelerationStructureSize = in->accelerationStructureSize; + out->updateScratchSize = in->updateScratchSize; + out->buildScratchSize = in->buildScratchSize; +} +#endif /* USE_STRUCT_CONVERSION */ + #if defined(USE_STRUCT_CONVERSION) static inline void convert_VkAccelerationStructureDeviceAddressInfoKHR_win32_to_host(const VkAccelerationStructureDeviceAddressInfoKHR *in, VkAccelerationStructureDeviceAddressInfoKHR_host *out) { @@ -1685,6 +1698,19 @@ static inline void convert_VkDeviceFaultCountsEXT_win32_to_host(const VkDeviceFa } #endif /* USE_STRUCT_CONVERSION */
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkDeviceFaultCountsEXT_host_to_win32(const VkDeviceFaultCountsEXT_host *in, VkDeviceFaultCountsEXT *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->addressInfoCount = in->addressInfoCount; + out->vendorInfoCount = in->vendorInfoCount; + out->vendorBinarySize = in->vendorBinarySize; +} +#endif /* USE_STRUCT_CONVERSION */ + #if defined(USE_STRUCT_CONVERSION) static inline VkDeviceFaultAddressInfoEXT_host *convert_VkDeviceFaultAddressInfoEXT_array_win32_to_host(struct conversion_context *ctx, const VkDeviceFaultAddressInfoEXT *in, uint32_t count) { @@ -1901,6 +1927,19 @@ static inline void convert_VkMicromapBuildSizesInfoEXT_win32_to_host(const VkMic } #endif /* USE_STRUCT_CONVERSION */
+#if defined(USE_STRUCT_CONVERSION) +static inline void convert_VkMicromapBuildSizesInfoEXT_host_to_win32(const VkMicromapBuildSizesInfoEXT_host *in, VkMicromapBuildSizesInfoEXT *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->micromapSize = in->micromapSize; + out->buildScratchSize = in->buildScratchSize; + out->discardable = in->discardable; +} +#endif /* USE_STRUCT_CONVERSION */ + #if defined(USE_STRUCT_CONVERSION) static inline void convert_VkImageFormatProperties_host_to_win32(const VkImageFormatProperties_host *in, VkImageFormatProperties *out) { @@ -14549,6 +14588,7 @@ static NTSTATUS thunk32_vkGetAccelerationStructureBuildSizesKHR(void *args) convert_VkAccelerationStructureBuildGeometryInfoKHR_win32_to_host(params->pBuildInfo, &pBuildInfo_host); convert_VkAccelerationStructureBuildSizesInfoKHR_win32_to_host(params->pSizeInfo, &pSizeInfo_host); wine_device_from_handle(params->device)->funcs.p_vkGetAccelerationStructureBuildSizesKHR(wine_device_from_handle(params->device)->device, params->buildType, &pBuildInfo_host, params->pMaxPrimitiveCounts, &pSizeInfo_host); + convert_VkAccelerationStructureBuildSizesInfoKHR_host_to_win32(&pSizeInfo_host, params->pSizeInfo); return STATUS_SUCCESS; }
@@ -15174,6 +15214,7 @@ static NTSTATUS thunk32_vkGetDeviceFaultInfoEXT(void *args) convert_VkDeviceFaultCountsEXT_win32_to_host(params->pFaultCounts, &pFaultCounts_host); convert_VkDeviceFaultInfoEXT_win32_to_host(&ctx, params->pFaultInfo, &pFaultInfo_host); params->result = wine_device_from_handle(params->device)->funcs.p_vkGetDeviceFaultInfoEXT(wine_device_from_handle(params->device)->device, &pFaultCounts_host, &pFaultInfo_host); + convert_VkDeviceFaultCountsEXT_host_to_win32(&pFaultCounts_host, params->pFaultCounts); free_conversion_context(&ctx); return STATUS_SUCCESS; } @@ -16057,6 +16098,7 @@ static NTSTATUS thunk32_vkGetMicromapBuildSizesEXT(void *args) convert_VkMicromapBuildInfoEXT_win32_to_host(params->pBuildInfo, &pBuildInfo_host); convert_VkMicromapBuildSizesInfoEXT_win32_to_host(params->pSizeInfo, &pSizeInfo_host); wine_device_from_handle(params->device)->funcs.p_vkGetMicromapBuildSizesEXT(wine_device_from_handle(params->device)->device, params->buildType, &pBuildInfo_host, &pSizeInfo_host); + convert_VkMicromapBuildSizesInfoEXT_host_to_win32(&pSizeInfo_host, params->pSizeInfo); return STATUS_SUCCESS; }
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 103 ++++++++++++++---------------------- 1 file changed, 40 insertions(+), 63 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index becd456bbee..017f222fdb8 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -1173,6 +1173,46 @@ class VkVariable(object): def needs_host_type(self): return self.is_struct() and self.struct.needs_host_type()
+ def get_conversions(self, unwrap, parent_const=False): + """ 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 self.is_struct(): + self.struct.needs_struct_extensions_conversion() + for m in self.struct: + if m.type == self.struct.name: + continue + m.needs_struct_extensions_conversion() + elif not self.is_handle(): + return [] + + conversions = [] + + # Collect any member conversions first, so we can guarantee + # those functions will be defined prior to usage by the + # 'parent' param requiring conversion. + if self.is_struct(): + is_const = self.is_const() if self.is_pointer() else parent_const + for m in self.struct: + if m.type == self.struct.name: + continue + if not m.is_struct(): + continue + + conversions.extend(m.get_conversions(unwrap, is_const)) + + # Conversion requirements for the 'parent' parameter. + for conv in [False, True]: + if self.needs_conversion(conv, unwrap, Direction.INPUT, parent_const): + conversions.append(ConversionFunction(self, Direction.INPUT, conv, unwrap)) + if self.needs_conversion(conv, unwrap, Direction.OUTPUT, parent_const): + conversions.append(ConversionFunction(self, Direction.OUTPUT, conv, unwrap)) + + return conversions +
class VkMember(VkVariable): def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None, @@ -1348,34 +1388,6 @@ class VkMember(VkVariable):
return text
- def get_conversions(self, unwrap, parent_const): - """ Return any conversion description for this member and its children when conversion is needed. """ - - conversions = [] - - # Collect any conversion for any member structs. - if self.is_struct(): - struct = self.type_info["data"] - for m in struct: - if m.type == struct.name: - continue - - m.needs_struct_extensions_conversion() - conversions.extend(m.get_conversions(parent_const, unwrap)) - - struct.needs_struct_extensions_conversion() - direction = Direction.OUTPUT if struct.returnedonly else Direction.INPUT - elif self.is_handle() or self.is_generic_handle(): - direction = Direction.INPUT - else: - return [] - - for conv in [False, True]: - if self.needs_conversion(conv, unwrap, direction, parent_const): - conversions.append(ConversionFunction(self, direction, conv, unwrap)) - - return conversions - def is_struct_forward_declaration(self): return self.struct_fwd_decl
@@ -1595,41 +1607,6 @@ class VkParam(VkVariable): def format_string(self): return self.format_str
- def get_conversions(self, unwrap): - """ 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 self.is_struct(): - self.struct.needs_struct_extensions_conversion() - for m in self.struct: - m.needs_struct_extensions_conversion() - elif not self.is_handle(): - return [] - - conversions = [] - - # Collect any member conversions first, so we can guarantee - # those functions will be defined prior to usage by the - # 'parent' param requiring conversion. - if self.is_struct(): - for m in self.struct: - if not m.is_struct(): - continue - - conversions.extend(m.get_conversions(unwrap, False)) - - # Conversion requirements for the 'parent' parameter. - for conv in [False, True]: - if self.needs_conversion(conv, unwrap, Direction.INPUT): - conversions.append(ConversionFunction(self, Direction.INPUT, conv, unwrap)) - if self.needs_conversion(conv, unwrap, Direction.OUTPUT): - conversions.append(ConversionFunction(self, Direction.OUTPUT, conv, unwrap)) - - return conversions - def is_dispatchable(self): if not self.is_handle(): return False