[PATCH 1/9] winevulkan: Generate conversion function for VkInstanceCreateInfo structure extensions.
Józef Kucia
jkucia at codeweavers.com
Wed Apr 10 04:59:49 CDT 2019
Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
dlls/winevulkan/make_vulkan | 145 +++++++++++++++++++++++++++++---
dlls/winevulkan/vulkan.c | 31 ++-----
dlls/winevulkan/vulkan_thunks.c | 37 ++++++++
dlls/winevulkan/vulkan_thunks.h | 3 +
4 files changed, 177 insertions(+), 39 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 20643fa1e34c..eb68a7be598f 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -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:
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index f86064c4b661..259d7d18e7c1 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -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);
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c
index e1df2aa72eae..2f0cc6218e22 100644
--- a/dlls/winevulkan/vulkan_thunks.c
+++ b/dlls/winevulkan/vulkan_thunks.c
@@ -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)
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h
index 6d0ed45e3c3d..3b8a93176abd 100644
--- a/dlls/winevulkan/vulkan_thunks.h
+++ b/dlls/winevulkan/vulkan_thunks.h
@@ -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
{
--
2.21.0
More information about the wine-devel
mailing list