zink/codegen: support double-loading dynamic properties arrays

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35389>
This commit is contained in:
Hoe Hao Cheng
2025-06-11 21:35:45 +08:00
committed by Marge Bot
parent 4eb50771e4
commit 4d1768aec5
2 changed files with 71 additions and 4 deletions
+31 -3
View File
@@ -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))
+40 -1
View File
@@ -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")]