zink/codegen: support double-loading dynamic properties arrays
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35389>
This commit is contained in:
@@ -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))
|
||||
|
||||
@@ -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")]
|
||||
|
||||
Reference in New Issue
Block a user