winevulkan: Generate conversion function for VkInstanceCreateInfo structure extensions.
Signed-off-by: Józef Kucia <jkucia@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cc2e8d7cda
commit
a4b9460ad6
|
@ -220,6 +220,10 @@ FUNCTION_OVERRIDES = {
|
||||||
"vkGetPhysicalDevicePresentRectanglesKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
|
"vkGetPhysicalDevicePresentRectanglesKHR" : {"dispatch" : True, "driver" : True, "thunk" : True},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STRUCT_CHAIN_CONVERSIONS = [
|
||||||
|
"VkInstanceCreateInfo",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Direction(Enum):
|
class Direction(Enum):
|
||||||
""" Parameter direction: input, output, input_output. """
|
""" Parameter direction: input, output, input_output. """
|
||||||
|
@ -912,7 +916,7 @@ class VkHandle(object):
|
||||||
|
|
||||||
class VkMember(object):
|
class VkMember(object):
|
||||||
def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None,
|
def __init__(self, const=False, struct_fwd_decl=False,_type=None, pointer=None, name=None, array_len=None,
|
||||||
dyn_array_len=None, optional=False):
|
dyn_array_len=None, optional=False, values=None):
|
||||||
self.const = const
|
self.const = const
|
||||||
self.struct_fwd_decl = struct_fwd_decl
|
self.struct_fwd_decl = struct_fwd_decl
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -922,6 +926,7 @@ class VkMember(object):
|
||||||
self.array_len = array_len
|
self.array_len = array_len
|
||||||
self.dyn_array_len = dyn_array_len
|
self.dyn_array_len = dyn_array_len
|
||||||
self.optional = optional
|
self.optional = optional
|
||||||
|
self.values = values
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
""" Compare member based on name against a string.
|
""" Compare member based on name against a string.
|
||||||
|
@ -930,10 +935,7 @@ class VkMember(object):
|
||||||
if certain members exist.
|
if certain members exist.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.name == other:
|
return self.name == other
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{0} {1} {2} {3} {4} {5} {6}".format(self.const, self.struct_fwd_decl, self.type, self.pointer,
|
return "{0} {1} {2} {3} {4} {5} {6}".format(self.const, self.struct_fwd_decl, self.type, self.pointer,
|
||||||
|
@ -952,6 +954,8 @@ class VkMember(object):
|
||||||
pointer = None
|
pointer = None
|
||||||
array_len = None
|
array_len = None
|
||||||
|
|
||||||
|
values = member.get("values")
|
||||||
|
|
||||||
if member.text:
|
if member.text:
|
||||||
if "const" in member.text:
|
if "const" in member.text:
|
||||||
const = True
|
const = True
|
||||||
|
@ -993,7 +997,7 @@ class VkMember(object):
|
||||||
array_len = name_elem.tail.strip("[]")
|
array_len = name_elem.tail.strip("[]")
|
||||||
|
|
||||||
return VkMember(const=const, struct_fwd_decl=struct_fwd_decl, _type=member_type, pointer=pointer, name=name_elem.text,
|
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)
|
array_len=array_len, dyn_array_len=dyn_array_len, optional=optional, values=values)
|
||||||
|
|
||||||
def copy(self, input, output, direction):
|
def copy(self, input, output, direction):
|
||||||
""" Helper method for use by conversion logic to generate a C-code statement to copy this member. """
|
""" Helper method for use by conversion logic to generate a C-code statement to copy this member. """
|
||||||
|
@ -1739,10 +1743,7 @@ class ConversionFunction(object):
|
||||||
self._set_name()
|
self._set_name()
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if self.name != other.name:
|
return self.name == other.name
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _generate_array_conversion_func(self):
|
def _generate_array_conversion_func(self):
|
||||||
""" Helper function for generating a conversion function for array structs. """
|
""" Helper function for generating a conversion function for array structs. """
|
||||||
|
@ -1874,10 +1875,7 @@ class FreeFunction(object):
|
||||||
self.name = "free_{0}".format(self.type)
|
self.name = "free_{0}".format(self.type)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if self.name == other.name:
|
return self.name == other.name
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _generate_array_free_func(self):
|
def _generate_array_free_func(self):
|
||||||
""" Helper function for cleaning up temporary buffers required for array conversions. """
|
""" Helper function for cleaning up temporary buffers required for array conversions. """
|
||||||
|
@ -1939,12 +1937,119 @@ class FreeFunction(object):
|
||||||
return self._generate_free_func()
|
return self._generate_free_func()
|
||||||
|
|
||||||
|
|
||||||
|
class StructChainConversionFunction(object):
|
||||||
|
def __init__(self, direction, struct):
|
||||||
|
self.direction = direction
|
||||||
|
self.struct = struct
|
||||||
|
self.type = struct.name
|
||||||
|
|
||||||
|
self.name = "convert_{0}_struct_chain".format(self.type)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.name == other.name
|
||||||
|
|
||||||
|
def prototype(self, postfix=""):
|
||||||
|
return "VkResult {0}(const void *pNext, {1} *out_struct) {2}".format(self.name, self.type, postfix).strip()
|
||||||
|
|
||||||
|
def definition(self):
|
||||||
|
body = self.prototype()
|
||||||
|
body += "\n{\n"
|
||||||
|
|
||||||
|
body += " VkBaseOutStructure *out_header = (VkBaseOutStructure *)out_struct;\n";
|
||||||
|
body += " const VkBaseInStructure *in_header;\n\n";
|
||||||
|
|
||||||
|
body += " out_header->pNext = NULL;\n\n"
|
||||||
|
|
||||||
|
body += " for (in_header = pNext; in_header; in_header = in_header->pNext)\n"
|
||||||
|
body += " {\n"
|
||||||
|
body += " switch (in_header->sType)\n"
|
||||||
|
body += " {\n"
|
||||||
|
|
||||||
|
# Ignore to not confuse host loader.
|
||||||
|
body += " case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO:\n"
|
||||||
|
body += " case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO:\n"
|
||||||
|
body += " break;\n\n"
|
||||||
|
|
||||||
|
for e in self.struct.struct_extensions:
|
||||||
|
if not e.required:
|
||||||
|
continue
|
||||||
|
|
||||||
|
stype = next(x for x in e.members if x.name == "sType")
|
||||||
|
|
||||||
|
body += " case {0}:\n".format(stype.values)
|
||||||
|
body += " {\n"
|
||||||
|
|
||||||
|
body += " const {0} *in = (const {0} *)in_header;\n".format(e.name)
|
||||||
|
body += " {0} *out;\n\n".format(e.name)
|
||||||
|
|
||||||
|
body += " if (!(out = heap_alloc(sizeof(*out)))) goto out_of_memory;\n\n"
|
||||||
|
|
||||||
|
for m in e:
|
||||||
|
if m.name == "pNext":
|
||||||
|
body += " out->pNext = NULL;\n"
|
||||||
|
else:
|
||||||
|
body += " " + m.copy("in->", "out->", self.direction)
|
||||||
|
|
||||||
|
body += "\n out_header->pNext = (VkBaseOutStructure *)out;\n"
|
||||||
|
body += " out_header = out_header->pNext;\n"
|
||||||
|
body += " break;\n"
|
||||||
|
body += " }\n\n"
|
||||||
|
|
||||||
|
body += " default:\n"
|
||||||
|
body += " FIXME(\"Application requested a linked structure of type %u.\\n\", in_header->sType);\n"
|
||||||
|
|
||||||
|
body += " }\n"
|
||||||
|
body += " }\n\n"
|
||||||
|
|
||||||
|
body += " return VK_SUCCESS;\n"
|
||||||
|
|
||||||
|
if any(x for x in self.struct.struct_extensions if x.required):
|
||||||
|
body += "\nout_of_memory:\n"
|
||||||
|
body += " free_{0}_struct_chain(out_struct);\n".format(self.type)
|
||||||
|
body += " return VK_ERROR_OUT_OF_HOST_MEMORY;\n"
|
||||||
|
|
||||||
|
body += "}\n\n"
|
||||||
|
return body
|
||||||
|
|
||||||
|
class FreeStructChainFunction(object):
|
||||||
|
def __init__(self, struct):
|
||||||
|
self.struct = struct
|
||||||
|
self.type = struct.name
|
||||||
|
|
||||||
|
self.name = "free_{0}_struct_chain".format(self.type)
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.name == other.name
|
||||||
|
|
||||||
|
def prototype(self, postfix=""):
|
||||||
|
return "void {0}({1} *s) {2}".format(self.name, self.type, postfix).strip()
|
||||||
|
|
||||||
|
def definition(self):
|
||||||
|
body = self.prototype()
|
||||||
|
body += "\n{\n"
|
||||||
|
|
||||||
|
body += " VkBaseOutStructure *header = (void *)s->pNext;\n\n";
|
||||||
|
|
||||||
|
body += " while (header)\n"
|
||||||
|
body += " {\n"
|
||||||
|
body += " void *prev = header;\n"
|
||||||
|
body += " header = header->pNext;\n"
|
||||||
|
body += " heap_free(prev);\n"
|
||||||
|
body += " }\n\n"
|
||||||
|
|
||||||
|
body += " s->pNext = NULL;\n"
|
||||||
|
|
||||||
|
body += "}\n\n"
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
class VkGenerator(object):
|
class VkGenerator(object):
|
||||||
def __init__(self, registry):
|
def __init__(self, registry):
|
||||||
self.registry = registry
|
self.registry = registry
|
||||||
|
|
||||||
# Build a list conversion functions for struct conversion.
|
# Build a list conversion functions for struct conversion.
|
||||||
self.conversions = []
|
self.conversions = []
|
||||||
|
self.struct_chain_conversions = []
|
||||||
self.host_structs = []
|
self.host_structs = []
|
||||||
for func in self.registry.funcs.values():
|
for func in self.registry.funcs.values():
|
||||||
if not func.is_required():
|
if not func.is_required():
|
||||||
|
@ -1966,6 +2071,11 @@ class VkGenerator(object):
|
||||||
if not any(s.name == conv.struct.name for s in self.host_structs):
|
if not any(s.name == conv.struct.name for s in self.host_structs):
|
||||||
self.host_structs.append(conv.struct)
|
self.host_structs.append(conv.struct)
|
||||||
|
|
||||||
|
for struct in self.registry.structs:
|
||||||
|
if struct.name in STRUCT_CHAIN_CONVERSIONS:
|
||||||
|
self.struct_chain_conversions.append(StructChainConversionFunction(Direction.INPUT, struct))
|
||||||
|
self.struct_chain_conversions.append(FreeStructChainFunction(struct))
|
||||||
|
|
||||||
def _generate_copyright(self, f, spec_file=False):
|
def _generate_copyright(self, f, spec_file=False):
|
||||||
f.write("# " if spec_file else "/* ")
|
f.write("# " if spec_file else "/* ")
|
||||||
f.write("Automatically generated from Vulkan vk.xml; DO NOT EDIT!\n")
|
f.write("Automatically generated from Vulkan vk.xml; DO NOT EDIT!\n")
|
||||||
|
@ -1991,6 +2101,9 @@ class VkGenerator(object):
|
||||||
f.write(conv.definition())
|
f.write(conv.definition())
|
||||||
f.write("#endif /* USE_STRUCT_CONVERSION */\n\n")
|
f.write("#endif /* USE_STRUCT_CONVERSION */\n\n")
|
||||||
|
|
||||||
|
for conv in self.struct_chain_conversions:
|
||||||
|
f.write(conv.definition())
|
||||||
|
|
||||||
# Create thunks for instance and device functions.
|
# Create thunks for instance and device functions.
|
||||||
# Global functions don't go through the thunks.
|
# Global functions don't go through the thunks.
|
||||||
for vk_func in self.registry.funcs.values():
|
for vk_func in self.registry.funcs.values():
|
||||||
|
@ -2128,6 +2241,10 @@ class VkGenerator(object):
|
||||||
f.write(struct.definition(align=False, conv=True, postfix="_host"))
|
f.write(struct.definition(align=False, conv=True, postfix="_host"))
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
|
||||||
|
for func in self.struct_chain_conversions:
|
||||||
|
f.write(func.prototype(postfix="DECLSPEC_HIDDEN") + ";\n")
|
||||||
|
f.write("\n")
|
||||||
|
|
||||||
f.write("/* For use by vkDevice and children */\n")
|
f.write("/* For use by vkDevice and children */\n")
|
||||||
f.write("struct vulkan_device_funcs\n{\n")
|
f.write("struct vulkan_device_funcs\n{\n")
|
||||||
for vk_func in self.registry.device_funcs:
|
for vk_func in self.registry.device_funcs:
|
||||||
|
|
|
@ -407,36 +407,15 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
|
||||||
VkInstanceCreateInfo *dst)
|
VkInstanceCreateInfo *dst)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
VkResult res;
|
||||||
|
|
||||||
*dst = *src;
|
*dst = *src;
|
||||||
|
|
||||||
/* Application and loader can pass in a chain of extensions through pNext.
|
if ((res = convert_VkInstanceCreateInfo_struct_chain(src->pNext, dst)) < 0)
|
||||||
* We can't blindly pass these through as often these contain callbacks or
|
|
||||||
* they can even be pass structures for loader / ICD internal use. For now
|
|
||||||
* we ignore everything in pNext chain, but we print FIXMEs.
|
|
||||||
*/
|
|
||||||
if (src->pNext)
|
|
||||||
{
|
{
|
||||||
const VkBaseInStructure *header;
|
WARN("Failed to convert VkInstanceCreateInfo pNext chain, res=%d.\n", res);
|
||||||
|
return res;
|
||||||
for (header = src->pNext; header; header = header->pNext)
|
|
||||||
{
|
|
||||||
switch (header->sType)
|
|
||||||
{
|
|
||||||
case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO:
|
|
||||||
/* Can be used to register new dispatchable object types
|
|
||||||
* to the loader. We should ignore it as it will confuse the
|
|
||||||
* host its loader.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
FIXME("Application requested a linked structure of type %u.\n", header->sType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* For now don't support anything. */
|
|
||||||
dst->pNext = NULL;
|
|
||||||
|
|
||||||
/* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
|
/* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
|
||||||
* filter this data out as well.
|
* filter this data out as well.
|
||||||
|
@ -452,6 +431,7 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
|
||||||
if (!wine_vk_instance_extension_supported(extension_name))
|
if (!wine_vk_instance_extension_supported(extension_name))
|
||||||
{
|
{
|
||||||
WARN("Extension %s is not supported.\n", debugstr_a(extension_name));
|
WARN("Extension %s is not supported.\n", debugstr_a(extension_name));
|
||||||
|
free_VkInstanceCreateInfo_struct_chain(dst);
|
||||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -771,6 +751,7 @@ VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_info,
|
||||||
}
|
}
|
||||||
|
|
||||||
res = vk_funcs->p_vkCreateInstance(&create_info_host, NULL /* allocator */, &object->instance);
|
res = vk_funcs->p_vkCreateInstance(&create_info_host, NULL /* allocator */, &object->instance);
|
||||||
|
free_VkInstanceCreateInfo_struct_chain(&create_info_host);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("Failed to create instance, res=%d\n", res);
|
ERR("Failed to create instance, res=%d\n", res);
|
||||||
|
|
|
@ -1343,6 +1343,43 @@ static inline void free_VkCopyDescriptorSet_array(VkCopyDescriptorSet_host *in,
|
||||||
|
|
||||||
#endif /* USE_STRUCT_CONVERSION */
|
#endif /* USE_STRUCT_CONVERSION */
|
||||||
|
|
||||||
|
VkResult convert_VkInstanceCreateInfo_struct_chain(const void *pNext, VkInstanceCreateInfo *out_struct)
|
||||||
|
{
|
||||||
|
VkBaseOutStructure *out_header = (VkBaseOutStructure *)out_struct;
|
||||||
|
const VkBaseInStructure *in_header;
|
||||||
|
|
||||||
|
out_header->pNext = NULL;
|
||||||
|
|
||||||
|
for (in_header = pNext; in_header; in_header = in_header->pNext)
|
||||||
|
{
|
||||||
|
switch (in_header->sType)
|
||||||
|
{
|
||||||
|
case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO:
|
||||||
|
case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FIXME("Application requested a linked structure of type %u.\n", in_header->sType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_VkInstanceCreateInfo_struct_chain(VkInstanceCreateInfo *s)
|
||||||
|
{
|
||||||
|
VkBaseOutStructure *header = (void *)s->pNext;
|
||||||
|
|
||||||
|
while (header)
|
||||||
|
{
|
||||||
|
void *prev = header;
|
||||||
|
header = header->pNext;
|
||||||
|
heap_free(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
s->pNext = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
VkResult WINAPI wine_vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo, uint32_t *pImageIndex)
|
VkResult WINAPI wine_vkAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo, uint32_t *pImageIndex)
|
||||||
{
|
{
|
||||||
#if defined(USE_STRUCT_CONVERSION)
|
#if defined(USE_STRUCT_CONVERSION)
|
||||||
|
|
|
@ -765,6 +765,9 @@ typedef struct VkCopyDescriptorSet_host
|
||||||
} VkCopyDescriptorSet_host;
|
} VkCopyDescriptorSet_host;
|
||||||
|
|
||||||
|
|
||||||
|
VkResult convert_VkInstanceCreateInfo_struct_chain(const void *pNext, VkInstanceCreateInfo *out_struct) DECLSPEC_HIDDEN;
|
||||||
|
void free_VkInstanceCreateInfo_struct_chain(VkInstanceCreateInfo *s) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* For use by vkDevice and children */
|
/* For use by vkDevice and children */
|
||||||
struct vulkan_device_funcs
|
struct vulkan_device_funcs
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue