vulkan/util: generate a helper function to return pNext struct sizes
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Mon, 25 Feb 2019 16:43:15 +0000 (16:43 +0000)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Thu, 2 May 2019 16:02:02 +0000 (17:02 +0100)
This will be used to copy chains of structures so that we can alterate
some of them.

v2: Drop vk_util.h include (Eric)
    Use VkBaseInStructure directly (Eric)

v3: Drop --platforms= param to generator script, instead produce a
    file with #ifdef based what platforms are compiled.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Eric Engestrom <eric.engestrom@intel.com>
src/vulkan/util/gen_enum_to_str.py
src/vulkan/util/meson.build

index 4324ca5b7b7831a83123db33be032334e880fde2..5357278ded109abe6765d76df9d19189b87b597f 100644 (file)
@@ -95,6 +95,23 @@ C_TEMPLATE = Template(textwrap.dedent(u"""\
       % endif
     %endfor
 
       % endif
     %endfor
 
+    size_t vk_structure_type_size(const struct VkBaseInStructure *item)
+    {
+        switch(item->sType) {
+    % for struct in structs:
+        % if struct.extension is not None and struct.extension.define is not None:
+    #ifdef ${struct.extension.define}
+        case ${struct.stype}: return sizeof(${struct.name});
+    #endif
+        % else:
+        case ${struct.stype}: return sizeof(${struct.name});
+        % endif
+    %endfor
+        default:
+            unreachable("Undefined struct type.");
+        }
+    }
+
     void vk_load_instance_commands(VkInstance instance,
                                    PFN_vkGetInstanceProcAddr gpa,
                                    struct vk_instance_dispatch_table *table)
     void vk_load_instance_commands(VkInstance instance,
                                    PFN_vkGetInstanceProcAddr gpa,
                                    struct vk_instance_dispatch_table *table)
@@ -166,6 +183,8 @@ H_TEMPLATE = Template(textwrap.dedent(u"""\
       % endif
     % endfor
 
       % endif
     % endfor
 
+    size_t vk_structure_type_size(const struct VkBaseInStructure *item);
+
     struct vk_instance_dispatch_table {
         PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
     % for cmd in commands:
     struct vk_instance_dispatch_table {
         PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
     % for cmd in commands:
@@ -245,6 +264,7 @@ class VkEnum(object):
 
     def __init__(self, name, values=None):
         self.name = name
 
     def __init__(self, name, values=None):
         self.name = name
+        self.extension = None
         # Maps numbers to names
         self.values = values or dict()
         self.name_to_value = dict()
         # Maps numbers to names
         self.values = values or dict()
         self.name_to_value = dict()
@@ -266,6 +286,7 @@ class VkEnum(object):
             self.values[value] = name
 
     def add_value_from_xml(self, elem, extension=None):
             self.values[value] = name
 
     def add_value_from_xml(self, elem, extension=None):
+        self.extension = extension
         if 'value' in elem.attrib:
             self.add_value(elem.attrib['name'],
                            value=int(elem.attrib['value'], base=0))
         if 'value' in elem.attrib:
             self.add_value(elem.attrib['name'],
                            value=int(elem.attrib['value'], base=0))
@@ -296,7 +317,23 @@ class VkCommand(object):
         self.extension = None
 
 
         self.extension = None
 
 
-def parse_xml(cmd_factory, enum_factory, ext_factory, filename):
+class VkChainStruct(object):
+    """Simple struct-like class representing a single Vulkan struct identified with a VkStructureType"""
+    def __init__(self, name, stype):
+        self.name = name
+        self.stype = stype
+        self.extension = None
+
+
+def struct_get_stype(xml_node):
+    for member in xml_node.findall('./member'):
+        name = member.findall('./name')
+        if len(name) > 0 and name[0].text == "sType":
+            return member.get('values')
+    return None
+
+
+def parse_xml(cmd_factory, enum_factory, ext_factory, struct_factory, filename):
     """Parse the XML file. Accumulate results into the factories.
 
     This parser is a memory efficient iterative XML parser that returns a list
     """Parse the XML file. Accumulate results into the factories.
 
     This parser is a memory efficient iterative XML parser that returns a list
@@ -323,6 +360,12 @@ def parse_xml(cmd_factory, enum_factory, ext_factory, filename):
             cmd_factory(name.text,
                         device_entrypoint=(first_arg.text in ('VkDevice', 'VkCommandBuffer', 'VkQueue')))
 
             cmd_factory(name.text,
                         device_entrypoint=(first_arg.text in ('VkDevice', 'VkCommandBuffer', 'VkQueue')))
 
+    for struct_type in xml.findall('./types/type[@category="struct"]'):
+        name = struct_type.attrib['name']
+        stype = struct_get_stype(struct_type)
+        if stype is not None:
+            struct_factory(name, stype=stype)
+
     platform_define = {}
     for platform in xml.findall('./platforms/platform'):
         name = platform.attrib['name']
     platform_define = {}
     for platform in xml.findall('./platforms/platform'):
         name = platform.attrib['name']
@@ -341,6 +384,10 @@ def parse_xml(cmd_factory, enum_factory, ext_factory, filename):
             enum = enum_factory.get(value.attrib['extends'])
             if enum is not None:
                 enum.add_value_from_xml(value, extension)
             enum = enum_factory.get(value.attrib['extends'])
             if enum is not None:
                 enum.add_value_from_xml(value, extension)
+        for t in ext_elem.findall('./require/type'):
+            struct = struct_factory.get(t.attrib['name'])
+            if struct is not None:
+                struct.extension = extension
 
         if define:
             for value in ext_elem.findall('./require/type[@name]'):
 
         if define:
             for value in ext_elem.findall('./require/type[@name]'):
@@ -369,11 +416,13 @@ def main():
     command_factory = NamedFactory(VkCommand)
     enum_factory = NamedFactory(VkEnum)
     ext_factory = NamedFactory(VkExtension)
     command_factory = NamedFactory(VkCommand)
     enum_factory = NamedFactory(VkEnum)
     ext_factory = NamedFactory(VkExtension)
+    struct_factory = NamedFactory(VkChainStruct)
     for filename in args.xml_files:
     for filename in args.xml_files:
-        parse_xml(command_factory, enum_factory, ext_factory, filename)
+        parse_xml(command_factory, enum_factory, ext_factory, struct_factory, filename)
     commands = sorted(command_factory.registry.values(), key=lambda e: e.name)
     enums = sorted(enum_factory.registry.values(), key=lambda e: e.name)
     extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name)
     commands = sorted(command_factory.registry.values(), key=lambda e: e.name)
     enums = sorted(enum_factory.registry.values(), key=lambda e: e.name)
     extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name)
+    structs = sorted(struct_factory.registry.values(), key=lambda e: e.name)
 
     for template, file_ in [(C_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.c')),
                             (H_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.h'))]:
 
     for template, file_ in [(C_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.c')),
                             (H_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.h'))]:
@@ -383,6 +432,7 @@ def main():
                 commands=commands,
                 enums=enums,
                 extensions=extensions,
                 commands=commands,
                 enums=enums,
                 extensions=extensions,
+                structs=structs,
                 copyright=COPYRIGHT,
                 FOREIGN_ENUM_VALUES=FOREIGN_ENUM_VALUES))
 
                 copyright=COPYRIGHT,
                 FOREIGN_ENUM_VALUES=FOREIGN_ENUM_VALUES))
 
index ca292bbf7d6c2edd7a50423f95c1b5a04bbceb97..db09482e3a72519990efa0e17c3fdf82188a73f4 100644 (file)
@@ -31,8 +31,8 @@ vk_enum_to_str = custom_target(
   input : ['gen_enum_to_str.py', vk_api_xml],
   output : ['vk_enum_to_str.c', 'vk_enum_to_str.h'],
   command : [
   input : ['gen_enum_to_str.py', vk_api_xml],
   output : ['vk_enum_to_str.c', 'vk_enum_to_str.h'],
   command : [
-    prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--outdir',
-    meson.current_build_dir()
+    prog_python, '@INPUT0@', '--xml', '@INPUT1@',
+    '--outdir', meson.current_build_dir()
   ],
 )
 
   ],
 )