1# encoding=utf-8 2# Copyright © 2017 Intel Corporation 3 4# Permission is hereby granted, free of charge, to any person obtaining a copy 5# of this software and associated documentation files (the "Software"), to deal 6# in the Software without restriction, including without limitation the rights 7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8# copies of the Software, and to permit persons to whom the Software is 9# furnished to do so, subject to the following conditions: 10 11# The above copyright notice and this permission notice shall be included in 12# all copies or substantial portions of the Software. 13 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20# SOFTWARE. 21 22"""Create enum to string functions for vulkan using vk.xml.""" 23 24from __future__ import print_function 25import argparse 26import os 27import textwrap 28import xml.etree.cElementTree as et 29 30from mako.template import Template 31 32COPYRIGHT = textwrap.dedent(u"""\ 33 * Copyright © 2017 Intel Corporation 34 * 35 * Permission is hereby granted, free of charge, to any person obtaining a copy 36 * of this software and associated documentation files (the "Software"), to deal 37 * in the Software without restriction, including without limitation the rights 38 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39 * copies of the Software, and to permit persons to whom the Software is 40 * furnished to do so, subject to the following conditions: 41 * 42 * The above copyright notice and this permission notice shall be included in 43 * all copies or substantial portions of the Software. 44 * 45 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 51 * SOFTWARE.""") 52 53C_TEMPLATE = Template(textwrap.dedent(u"""\ 54 /* Autogenerated file -- do not edit 55 * generated by ${file} 56 * 57 ${copyright} 58 */ 59 60 #include <vulkan/vulkan.h> 61 #include <vulkan/vk_android_native_buffer.h> 62 #include "util/macros.h" 63 #include "vk_enum_to_str.h" 64 65 % for enum in enums: 66 67 const char * 68 vk_${enum.name[2:]}_to_str(${enum.name} input) 69 { 70 switch(input) { 71 % for v in sorted(enum.values.keys()): 72 % if enum.values[v] in FOREIGN_ENUM_VALUES: 73 74 #pragma GCC diagnostic push 75 #pragma GCC diagnostic ignored "-Wswitch" 76 % endif 77 case ${v}: 78 return "${enum.values[v]}"; 79 % if enum.values[v] in FOREIGN_ENUM_VALUES: 80 #pragma GCC diagnostic pop 81 82 % endif 83 % endfor 84 default: 85 unreachable("Undefined enum value."); 86 } 87 } 88 %endfor"""), 89 output_encoding='utf-8') 90 91H_TEMPLATE = Template(textwrap.dedent(u"""\ 92 /* Autogenerated file -- do not edit 93 * generated by ${file} 94 * 95 ${copyright} 96 */ 97 98 #ifndef MESA_VK_ENUM_TO_STR_H 99 #define MESA_VK_ENUM_TO_STR_H 100 101 #include <vulkan/vulkan.h> 102 #include <vulkan/vk_android_native_buffer.h> 103 104 % for ext in extensions: 105 #define _${ext.name}_number (${ext.number}) 106 % endfor 107 108 % for enum in enums: 109 const char * vk_${enum.name[2:]}_to_str(${enum.name} input); 110 % endfor 111 112 #endif"""), 113 output_encoding='utf-8') 114 115# These enums are defined outside their respective enum blocks, and thus cause 116# -Wswitch warnings. 117FOREIGN_ENUM_VALUES = [ 118 "VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID", 119] 120 121 122class NamedFactory(object): 123 """Factory for creating enums.""" 124 125 def __init__(self, type_): 126 self.registry = {} 127 self.type = type_ 128 129 def __call__(self, name, **kwargs): 130 try: 131 return self.registry[name] 132 except KeyError: 133 n = self.registry[name] = self.type(name, **kwargs) 134 return n 135 136 def get(self, name): 137 return self.registry.get(name) 138 139 140class VkExtension(object): 141 """Simple struct-like class representing extensions""" 142 143 def __init__(self, name, number=None): 144 self.name = name 145 self.number = number 146 147 148class VkEnum(object): 149 """Simple struct-like class representing a single Vulkan Enum.""" 150 151 def __init__(self, name, values=None): 152 self.name = name 153 # Maps numbers to names 154 self.values = values or dict() 155 156 def add_value(self, name, value=None, 157 extension=None, offset=None, 158 error=False): 159 assert value is not None or extension is not None 160 if value is None: 161 value = 1000000000 + (extension.number - 1) * 1000 + offset 162 if error: 163 value = -value 164 165 if value not in self.values: 166 self.values[value] = name 167 168 169def parse_xml(enum_factory, ext_factory, filename): 170 """Parse the XML file. Accumulate results into the factories. 171 172 This parser is a memory efficient iterative XML parser that returns a list 173 of VkEnum objects. 174 """ 175 176 xml = et.parse(filename) 177 178 for enum_type in xml.findall('./enums[@type="enum"]'): 179 enum = enum_factory(enum_type.attrib['name']) 180 for value in enum_type.findall('./enum'): 181 enum.add_value(value.attrib['name'], 182 value=int(value.attrib['value'])) 183 184 for ext_elem in xml.findall('./extensions/extension[@supported="vulkan"]'): 185 extension = ext_factory(ext_elem.attrib['name'], 186 number=int(ext_elem.attrib['number'])) 187 188 for value in ext_elem.findall('./require/enum[@extends]'): 189 enum = enum_factory.get(value.attrib['extends']) 190 if enum is None: 191 continue 192 if 'value' in value.attrib: 193 enum.add_value(value.attrib['name'], 194 value=int(value.attrib['value'])) 195 else: 196 error = 'dir' in value.attrib and value.attrib['dir'] == '-' 197 enum.add_value(value.attrib['name'], 198 extension=extension, 199 offset=int(value.attrib['offset']), 200 error=error) 201 202 203def main(): 204 parser = argparse.ArgumentParser() 205 parser.add_argument('--xml', required=True, 206 help='Vulkan API XML files', 207 action='append', 208 dest='xml_files') 209 parser.add_argument('--outdir', 210 help='Directory to put the generated files in', 211 required=True) 212 213 args = parser.parse_args() 214 215 enum_factory = NamedFactory(VkEnum) 216 ext_factory = NamedFactory(VkExtension) 217 for filename in args.xml_files: 218 parse_xml(enum_factory, ext_factory, filename) 219 enums = sorted(enum_factory.registry.values(), key=lambda e: e.name) 220 extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name) 221 222 for template, file_ in [(C_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.c')), 223 (H_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.h'))]: 224 with open(file_, 'wb') as f: 225 f.write(template.render( 226 file=os.path.basename(__file__), 227 enums=enums, 228 extensions=extensions, 229 copyright=COPYRIGHT, 230 FOREIGN_ENUM_VALUES=FOREIGN_ENUM_VALUES)) 231 232 233if __name__ == '__main__': 234 main() 235