winevulkan: Generate "in_ext" definition on demand
There are cases in StructConversionFunction.definition where we will generate copy code for extension struct members, without emitting the definition of the "in_ext" variable used in the copy code.
This issue is triggered by mismatches in the condition that guards the generation of the "in_ext" definition, and the condition(s) that govern the generation of the member copy code (e.g., in StructConversionFunction.member_needs_copy and VkMember.needs_conversion).
In order to avoid such mismatches and the burden of having to keep the conditions in sync, this commit generates the definition on demand, by checking if it's actually needed by the member copy code.
Signed-off-by: Alexandros Frantzis alexandros.frantzis@collabora.com
--
Some more details in case a different solution becomes apparent.
An example of the aforementioned issue can be triggered if we make VK_EXT_image_drm_format_modifier an UNEXPOSED extension in make_vulkan:
../wine/dlls/winevulkan/vulkan_thunks.c: In function ‘convert_VkFormatProperties2_win32_to_host’:
../wine/dlls/winevulkan/vulkan_thunks.c:10214:119: error: ‘in_ext’ undeclared (first use in this function); did you mean ‘index’?
10214 | out_ext->pDrmFormatModifierProperties = convert_VkDrmFormatModifierPropertiesEXT_array_win32_to_host(ctx, in_ext->pDrmFormatModifierProperties, in_ext->drmFormatModifierCount);
| ^~~~~~
| index
In this particular case the mismatch happens because for the VkDrmFormatModifierPropertiesListEXT (returnedonly=true) struct in the INPUT direction the current check doesn't emit in_ext:
if self.direction == Direction.OUTPUT or not ext.returnedonly: # Not triggered
body += ident + "{0} *in_ext = ({0} *)in_header;\n".format(in_type)
but self.member_needs_copy(ext, m) below for the "pDrmFormatModifierProperties" member returns True, requiring in_ext. The flow is:
* self.member_needs_copy(ext, m) => True
if m.name != "sType" and struct.returnedonly and not m.needs_conversion(self.conv, self.unwrap, Direction.INPUT, self.const): # Not triggered
return False
return True
* m.needs_conversion(self.conv, self.unwrap, Direction.INPUT, self.const) => 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