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},
|
||||
}
|
||||
|
||||
STRUCT_CHAIN_CONVERSIONS = [
|
||||
"VkInstanceCreateInfo",
|
||||
]
|
||||
|
||||
|
||||
class Direction(Enum):
|
||||
""" Parameter direction: input, output, input_output. """
|
||||
|
@ -912,7 +916,7 @@ class VkHandle(object):
|
|||
|
||||
class VkMember(object):
|
||||
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.struct_fwd_decl = struct_fwd_decl
|
||||
self.name = name
|
||||
|
@ -922,6 +926,7 @@ class VkMember(object):
|
|||
self.array_len = array_len
|
||||
self.dyn_array_len = dyn_array_len
|
||||
self.optional = optional
|
||||
self.values = values
|
||||
|
||||
def __eq__(self, other):
|
||||
""" Compare member based on name against a string.
|
||||
|
@ -930,10 +935,7 @@ class VkMember(object):
|
|||
if certain members exist.
|
||||
"""
|
||||
|
||||
if self.name == other:
|
||||
return True
|
||||
|
||||
return False
|
||||
return self.name == other
|
||||
|
||||
def __repr__(self):
|
||||
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
|
||||
array_len = None
|
||||
|
||||
values = member.get("values")
|
||||
|
||||
if member.text:
|
||||
if "const" in member.text:
|
||||
const = True
|
||||
|
@ -993,7 +997,7 @@ class VkMember(object):
|
|||
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,
|
||||
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):
|
||||
""" 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()
|
||||
|
||||
def __eq__(self, other):
|
||||
if self.name != other.name:
|
||||
return False
|
||||
|
||||
return True
|
||||
return self.name == other.name
|
||||
|
||||
def _generate_array_conversion_func(self):
|
||||
""" Helper function for generating a conversion function for array structs. """
|
||||
|
@ -1874,10 +1875,7 @@ class FreeFunction(object):
|
|||
self.name = "free_{0}".format(self.type)
|
||||
|
||||
def __eq__(self, other):
|
||||
if self.name == other.name:
|
||||
return True
|
||||
|
||||
return False
|
||||
return self.name == other.name
|
||||
|
||||
def _generate_array_free_func(self):
|
||||
""" Helper function for cleaning up temporary buffers required for array conversions. """
|
||||
|
@ -1939,12 +1937,119 @@ class FreeFunction(object):
|
|||
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):
|
||||
def __init__(self, registry):
|
||||
self.registry = registry
|
||||
|
||||
# Build a list conversion functions for struct conversion.
|
||||
self.conversions = []
|
||||
self.struct_chain_conversions = []
|
||||
self.host_structs = []
|
||||
for func in self.registry.funcs.values():
|
||||
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):
|
||||
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):
|
||||
f.write("# " if spec_file else "/* ")
|
||||
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("#endif /* USE_STRUCT_CONVERSION */\n\n")
|
||||
|
||||
for conv in self.struct_chain_conversions:
|
||||
f.write(conv.definition())
|
||||
|
||||
# Create thunks for instance and device functions.
|
||||
# Global functions don't go through the thunks.
|
||||
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("\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("struct vulkan_device_funcs\n{\n")
|
||||
for vk_func in self.registry.device_funcs:
|
||||
|
|
|
@ -407,36 +407,15 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
|
|||
VkInstanceCreateInfo *dst)
|
||||
{
|
||||
unsigned int i;
|
||||
VkResult res;
|
||||
|
||||
*dst = *src;
|
||||
|
||||
/* Application and loader can pass in a chain of extensions through pNext.
|
||||
* 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)
|
||||
if ((res = convert_VkInstanceCreateInfo_struct_chain(src->pNext, dst)) < 0)
|
||||
{
|
||||
const VkBaseInStructure *header;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
WARN("Failed to convert VkInstanceCreateInfo pNext chain, res=%d.\n", res);
|
||||
return res;
|
||||
}
|
||||
/* For now don't support anything. */
|
||||
dst->pNext = NULL;
|
||||
|
||||
/* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
|
||||
* 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))
|
||||
{
|
||||
WARN("Extension %s is not supported.\n", debugstr_a(extension_name));
|
||||
free_VkInstanceCreateInfo_struct_chain(dst);
|
||||
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);
|
||||
free_VkInstanceCreateInfo_struct_chain(&create_info_host);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
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 */
|
||||
|
||||
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)
|
||||
{
|
||||
#if defined(USE_STRUCT_CONVERSION)
|
||||
|
|
|
@ -765,6 +765,9 @@ typedef struct 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 */
|
||||
struct vulkan_device_funcs
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue