import argparse
import os
import textwrap
-import xml.etree.cElementTree as et
+import xml.etree.ElementTree as et
from mako.template import Template
% for enum in enums:
+ % if enum.guard:
+#ifdef ${enum.guard}
+ % endif
const char *
vk_${enum.name[2:]}_to_str(${enum.name} input)
{
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wswitch"
switch(input) {
% for v in sorted(enum.values.keys()):
- % if enum.values[v] in FOREIGN_ENUM_VALUES:
-
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wswitch"
- % endif
case ${v}:
return "${enum.values[v]}";
- % if enum.values[v] in FOREIGN_ENUM_VALUES:
- #pragma GCC diagnostic pop
-
- % endif
% endfor
- default:
- unreachable("Undefined enum value.");
}
+ #pragma GCC diagnostic pop
+ unreachable("Undefined enum value.");
}
+
+ % if enum.guard:
+#endif
+ % endif
+ %endfor
+
+ size_t vk_structure_type_size(const struct VkBaseInStructure *item)
+ {
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wswitch"
+ 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
+ }
+ #pragma GCC diagnostic pop
+ unreachable("Undefined struct type.");
+ }
void vk_load_instance_commands(VkInstance instance,
PFN_vkGetInstanceProcAddr gpa,
% endfor
% for enum in enums:
+ % if enum.guard:
+#ifdef ${enum.guard}
+ % endif
const char * vk_${enum.name[2:]}_to_str(${enum.name} input);
+ % if enum.guard:
+#endif
+ % endif
% endfor
+ size_t vk_structure_type_size(const struct VkBaseInStructure *item);
+
struct vk_instance_dispatch_table {
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
% for cmd in commands:
#endif"""),
output_encoding='utf-8')
-# These enums are defined outside their respective enum blocks, and thus cause
-# -Wswitch warnings.
-FOREIGN_ENUM_VALUES = [
- "VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID",
-]
-
class NamedFactory(object):
"""Factory for creating enums."""
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()
+ self.guard = None
+ self.name_to_alias_list = {}
def add_value(self, name, value=None,
- extnum=None, offset=None,
+ extnum=None, offset=None, alias=None,
error=False):
+ if alias is not None:
+ assert value is None and offset is None
+ if alias not in self.name_to_value:
+ # We don't have this alias yet. Just record the alias and
+ # we'll deal with it later.
+ alias_list = self.name_to_alias_list.get(alias, [])
+ alias_list.append(name);
+ return
+
+ # Use the value from the alias
+ value = self.name_to_value[alias]
+
assert value is not None or extnum is not None
if value is None:
value = 1000000000 + (extnum - 1) * 1000 + offset
elif len(self.values[value]) > len(name):
self.values[value] = name
+ # Now that the value has been fully added, resolve aliases, if any.
+ if name in self.name_to_alias_list:
+ for alias in self.name_to_alias_list[name]:
+ add_value(alias, value)
+ del self.name_to_alias_list[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))
elif 'alias' in elem.attrib:
- self.add_value(elem.attrib['name'],
- value=self.name_to_value[elem.attrib['alias']])
+ self.add_value(elem.attrib['name'], alias=elem.attrib['alias'])
else:
error = 'dir' in elem.attrib and elem.attrib['dir'] == '-'
if 'extnumber' in elem.attrib:
offset=int(elem.attrib['offset']),
error=error)
+ def set_guard(self, g):
+ self.guard = g
+
class VkCommand(object):
"""Simple struct-like class representing a single Vulkan command"""
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
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[name] = define
for ext_elem in xml.findall('./extensions/extension[@supported="vulkan"]'):
- platform = None
+ define = None
if "platform" in ext_elem.attrib:
define = platform_define[ext_elem.attrib['platform']]
extension = ext_factory(ext_elem.attrib['name'],
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]'):
+ enum = enum_factory.get(value.attrib['name'])
+ if enum is not None:
+ enum.set_guard(define)
for t in ext_elem.findall('./require/command'):
command = cmd_factory.get(t.attrib['name'])
command_factory = NamedFactory(VkCommand)
enum_factory = NamedFactory(VkEnum)
ext_factory = NamedFactory(VkExtension)
+ struct_factory = NamedFactory(VkChainStruct)
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)
+ 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'))]:
commands=commands,
enums=enums,
extensions=extensions,
- copyright=COPYRIGHT,
- FOREIGN_ENUM_VALUES=FOREIGN_ENUM_VALUES))
+ structs=structs,
+ copyright=COPYRIGHT))
if __name__ == '__main__':