Path: blob/21.2-virgl/src/vulkan/util/gen_enum_to_str.py
7129 views
# encoding=utf-81# Copyright © 2017 Intel Corporation23# Permission is hereby granted, free of charge, to any person obtaining a copy4# of this software and associated documentation files (the "Software"), to deal5# in the Software without restriction, including without limitation the rights6# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell7# copies of the Software, and to permit persons to whom the Software is8# furnished to do so, subject to the following conditions:910# The above copyright notice and this permission notice shall be included in11# all copies or substantial portions of the Software.1213# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE16# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,18# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE19# SOFTWARE.2021"""Create enum to string functions for vulkan using vk.xml."""2223from __future__ import print_function24import argparse25import os26import textwrap27import xml.etree.ElementTree as et2829from mako.template import Template3031COPYRIGHT = textwrap.dedent(u"""\32* Copyright © 2017 Intel Corporation33*34* Permission is hereby granted, free of charge, to any person obtaining a copy35* of this software and associated documentation files (the "Software"), to deal36* in the Software without restriction, including without limitation the rights37* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell38* copies of the Software, and to permit persons to whom the Software is39* furnished to do so, subject to the following conditions:40*41* The above copyright notice and this permission notice shall be included in42* all copies or substantial portions of the Software.43*44* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR45* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,46* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE47* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER48* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,49* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE50* SOFTWARE.""")5152C_TEMPLATE = Template(textwrap.dedent(u"""\53/* Autogenerated file -- do not edit54* generated by ${file}55*56${copyright}57*/5859#include <string.h>60#include <vulkan/vulkan.h>61#include <vulkan/vk_android_native_buffer.h>62#include <vulkan/vk_layer.h>63#include "util/macros.h"64#include "vk_enum_to_str.h"6566% for enum in enums:6768% if enum.guard:69#ifdef ${enum.guard}70% endif71const char *72vk_${enum.name[2:]}_to_str(${enum.name} input)73{74switch((int64_t)input) {75% for v in sorted(enum.values.keys()):76case ${v}:77return "${enum.values[v]}";78% endfor79default:80unreachable("Undefined enum value.");81}82}8384% if enum.guard:85#endif86% endif87%endfor8889size_t vk_structure_type_size(const struct VkBaseInStructure *item)90{91switch((int)item->sType) {92% for struct in structs:93% if struct.extension is not None and struct.extension.define is not None:94#ifdef ${struct.extension.define}95case ${struct.stype}: return sizeof(${struct.name});96#endif97% else:98case ${struct.stype}: return sizeof(${struct.name});99% endif100%endfor101case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: return sizeof(VkLayerInstanceCreateInfo);102case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO: return sizeof(VkLayerDeviceCreateInfo);103default:104unreachable("Undefined struct type.");105}106}107"""),108output_encoding='utf-8')109110H_TEMPLATE = Template(textwrap.dedent(u"""\111/* Autogenerated file -- do not edit112* generated by ${file}113*114${copyright}115*/116117#ifndef MESA_VK_ENUM_TO_STR_H118#define MESA_VK_ENUM_TO_STR_H119120#include <vulkan/vulkan.h>121#include <vulkan/vk_android_native_buffer.h>122123#ifdef __cplusplus124extern "C" {125#endif126127% for ext in extensions:128#define _${ext.name}_number (${ext.number})129% endfor130131% for enum in enums:132% if enum.guard:133#ifdef ${enum.guard}134% endif135const char * vk_${enum.name[2:]}_to_str(${enum.name} input);136% if enum.guard:137#endif138% endif139% endfor140141size_t vk_structure_type_size(const struct VkBaseInStructure *item);142143#ifdef __cplusplus144} /* extern "C" */145#endif146147#endif"""),148output_encoding='utf-8')149150151class NamedFactory(object):152"""Factory for creating enums."""153154def __init__(self, type_):155self.registry = {}156self.type = type_157158def __call__(self, name, **kwargs):159try:160return self.registry[name]161except KeyError:162n = self.registry[name] = self.type(name, **kwargs)163return n164165def get(self, name):166return self.registry.get(name)167168169class VkExtension(object):170"""Simple struct-like class representing extensions"""171172def __init__(self, name, number=None, define=None):173self.name = name174self.number = number175self.define = define176177178class VkEnum(object):179"""Simple struct-like class representing a single Vulkan Enum."""180181def __init__(self, name, values=None):182self.name = name183self.extension = None184# Maps numbers to names185self.values = values or dict()186self.name_to_value = dict()187self.guard = None188self.name_to_alias_list = {}189190def add_value(self, name, value=None,191extnum=None, offset=None, alias=None,192error=False):193if alias is not None:194assert value is None and offset is None195if alias not in self.name_to_value:196# We don't have this alias yet. Just record the alias and197# we'll deal with it later.198alias_list = self.name_to_alias_list.get(alias, [])199alias_list.append(name);200return201202# Use the value from the alias203value = self.name_to_value[alias]204205assert value is not None or extnum is not None206if value is None:207value = 1000000000 + (extnum - 1) * 1000 + offset208if error:209value = -value210211self.name_to_value[name] = value212if value not in self.values:213self.values[value] = name214elif len(self.values[value]) > len(name):215self.values[value] = name216217# Now that the value has been fully added, resolve aliases, if any.218if name in self.name_to_alias_list:219for alias in self.name_to_alias_list[name]:220add_value(alias, value)221del self.name_to_alias_list[name]222223def add_value_from_xml(self, elem, extension=None):224self.extension = extension225if 'value' in elem.attrib:226self.add_value(elem.attrib['name'],227value=int(elem.attrib['value'], base=0))228elif 'alias' in elem.attrib:229self.add_value(elem.attrib['name'], alias=elem.attrib['alias'])230else:231error = 'dir' in elem.attrib and elem.attrib['dir'] == '-'232if 'extnumber' in elem.attrib:233extnum = int(elem.attrib['extnumber'])234else:235extnum = extension.number236self.add_value(elem.attrib['name'],237extnum=extnum,238offset=int(elem.attrib['offset']),239error=error)240241def set_guard(self, g):242self.guard = g243244245class VkCommand(object):246"""Simple struct-like class representing a single Vulkan command"""247248def __init__(self, name, device_entrypoint=False):249self.name = name250self.device_entrypoint = device_entrypoint251self.extension = None252253254class VkChainStruct(object):255"""Simple struct-like class representing a single Vulkan struct identified with a VkStructureType"""256def __init__(self, name, stype):257self.name = name258self.stype = stype259self.extension = None260261262def struct_get_stype(xml_node):263for member in xml_node.findall('./member'):264name = member.findall('./name')265if len(name) > 0 and name[0].text == "sType":266return member.get('values')267return None268269270def parse_xml(enum_factory, ext_factory, struct_factory, filename):271"""Parse the XML file. Accumulate results into the factories.272273This parser is a memory efficient iterative XML parser that returns a list274of VkEnum objects.275"""276277xml = et.parse(filename)278279for enum_type in xml.findall('./enums[@type="enum"]'):280enum = enum_factory(enum_type.attrib['name'])281for value in enum_type.findall('./enum'):282enum.add_value_from_xml(value)283284for value in xml.findall('./feature/require/enum[@extends]'):285enum = enum_factory.get(value.attrib['extends'])286if enum is not None:287enum.add_value_from_xml(value)288289for struct_type in xml.findall('./types/type[@category="struct"]'):290name = struct_type.attrib['name']291stype = struct_get_stype(struct_type)292if stype is not None:293struct_factory(name, stype=stype)294295platform_define = {}296for platform in xml.findall('./platforms/platform'):297name = platform.attrib['name']298define = platform.attrib['protect']299platform_define[name] = define300301for ext_elem in xml.findall('./extensions/extension[@supported="vulkan"]'):302define = None303if "platform" in ext_elem.attrib:304define = platform_define[ext_elem.attrib['platform']]305extension = ext_factory(ext_elem.attrib['name'],306number=int(ext_elem.attrib['number']),307define=define)308309for value in ext_elem.findall('./require/enum[@extends]'):310enum = enum_factory.get(value.attrib['extends'])311if enum is not None:312enum.add_value_from_xml(value, extension)313for t in ext_elem.findall('./require/type'):314struct = struct_factory.get(t.attrib['name'])315if struct is not None:316struct.extension = extension317318if define:319for value in ext_elem.findall('./require/type[@name]'):320enum = enum_factory.get(value.attrib['name'])321if enum is not None:322enum.set_guard(define)323324325def main():326parser = argparse.ArgumentParser()327parser.add_argument('--xml', required=True,328help='Vulkan API XML files',329action='append',330dest='xml_files')331parser.add_argument('--outdir',332help='Directory to put the generated files in',333required=True)334335args = parser.parse_args()336337enum_factory = NamedFactory(VkEnum)338ext_factory = NamedFactory(VkExtension)339struct_factory = NamedFactory(VkChainStruct)340for filename in args.xml_files:341parse_xml(enum_factory, ext_factory, struct_factory, filename)342enums = sorted(enum_factory.registry.values(), key=lambda e: e.name)343extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name)344structs = sorted(struct_factory.registry.values(), key=lambda e: e.name)345346for template, file_ in [(C_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.c')),347(H_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.h'))]:348with open(file_, 'wb') as f:349f.write(template.render(350file=os.path.basename(__file__),351enums=enums,352extensions=extensions,353structs=structs,354copyright=COPYRIGHT))355356357if __name__ == '__main__':358main()359360361