From 4d1768aec5b38867945561969289cb04541ce038 Mon Sep 17 00:00:00 2001 From: Hoe Hao Cheng Date: Wed, 11 Jun 2025 21:35:45 +0800 Subject: [PATCH] zink/codegen: support double-loading dynamic properties arrays Part-of: --- src/gallium/drivers/zink/zink_device_info.py | 34 ++++++++++++++-- src/gallium/drivers/zink/zink_extensions.py | 41 +++++++++++++++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/zink/zink_device_info.py b/src/gallium/drivers/zink/zink_device_info.py index 38e379e0f6b..5a3bf4ac009 100644 --- a/src/gallium/drivers/zink/zink_device_info.py +++ b/src/gallium/drivers/zink/zink_device_info.py @@ -671,9 +671,9 @@ zink_get_physical_device_info(struct zink_screen *screen) %if ext.properties_promoted: if (info->have_vulkan${ext.core_since.struct()}) { %for field in registry.get_registry_entry(ext.name).properties_fields: - memcpy(&info->${ext.field("props")}.${field}, - &info->props${ext.core_since.struct()}.${field}, - sizeof(info->${ext.field("props")}.${field})); + memcpy(&info->${ext.field("props")}.${field.name}, + &info->props${ext.core_since.struct()}.${field.name}, + sizeof(info->${ext.field("props")}.${field.name})); %endfor } %endif @@ -701,6 +701,33 @@ zink_get_physical_device_info(struct zink_screen *screen) %endfor } + /* For extensions that require double-loading (first load for getting array + * length and malloc-ing, second load for getting array content) + */ + if (screen->vk.GetPhysicalDeviceProperties2) { + VkPhysicalDeviceProperties2 second_load_props = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 + }; + + %for ext in extensions: + %if ext.needs_double_load: + if (screen->info.have_${ext.name_with_vendor()}) { + screen->info.${ext.field("props")}.pNext = second_load_props.pNext; + second_load_props.pNext = &screen->info.${ext.field("props")}; + %for field in registry.get_registry_entry(ext.name).properties_fields: + %if field.len_field(): + screen->info.${ext.field("props")}.${field.name} = + ralloc_array(screen, ${field.type_name}, screen->info.${ext.field("props")}.${field.len_field()}); + %endif + %endfor + } + %endif + %endfor + + if (second_load_props.pNext) + screen->vk.GetPhysicalDeviceProperties2(screen->pdev, &second_load_props); + } + // generate extension list num_extensions = 0; @@ -909,6 +936,7 @@ if __name__ == "__main__": error_count += 1 print("The extension {} does not provide a properties struct.".format(ext.name)) ext.properties_promoted = entry.properties_promoted + ext.needs_double_load = entry.needs_double_load if entry.promoted_in and entry.promoted_in <= versions[-1].struct_version: ext.core_since = Version((*entry.promoted_in, 0)) diff --git a/src/gallium/drivers/zink/zink_extensions.py b/src/gallium/drivers/zink/zink_extensions.py index b351db8c8f9..2f79fd198a2 100644 --- a/src/gallium/drivers/zink/zink_extensions.py +++ b/src/gallium/drivers/zink/zink_extensions.py @@ -75,6 +75,7 @@ class Extension: guard = False features_promoted = False properties_promoted = False + needs_double_load = False # these are specific to zink_instance.py: @@ -190,6 +191,27 @@ class ExtensionRegistryCommand: def name(self): return self.full_name.lstrip("vk") +class ExtensionPropField: + # name of the property + name = "" + type_name = "" + + # name of the variable that stores the length of this property + # 1. MUST be None for non-arrays + # 2. MUST be "null-terminated" for C strings + prop_len = None + + # whether the property is nullable + is_optional = False + + # returns the name of the field that stores the length of this property + def len_field(self): + if not self.prop_len: + return None + elif self.prop_len == "null-terminated": + return None + return self.prop_len + class ExtensionRegistryEntry: # type of extension - right now it's either "instance" or "device" ext_type = "" @@ -208,6 +230,10 @@ class ExtensionRegistryEntry: properties_struct = None properties_fields = None properties_promoted = False + # if the property field requires dynamic allocated arrays, double-loading is + # required: first properties load for count and malloc'ing, second properties + # load for actual array content + needs_double_load = False # some instance extensions are locked behind certain platforms platform_guard = "" @@ -333,11 +359,24 @@ class ExtensionRegistry: entry.properties_promoted = False for field in vkxml.findall("./types/type[@name='{}']/member".format(struct_name)): + prop_field = ExtensionPropField() + field_name = field.find("name").text + field_type = field.find("./type") + + field_len = None + if field_type.tail.strip() == "*": + field_len = field.get("len") + + if bool(field_len) and field_len != "null-terminated": + entry.needs_double_load = True # we ignore sType and pNext since they are irrelevant if field_name not in ["sType", "pNext"]: - entry.properties_fields.append(field_name) + prop_field.name = field_name + prop_field.type_name = field_type.text + prop_field.prop_len = field_len + entry.properties_fields.append(prop_field) if ext.get("platform") is not None: entry.platform_guard = platform_guards[ext.get("platform")]