2 # Copyright © 2017 Intel Corporation
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:
11 # The above copyright notice and this permission notice shall be included in
12 # all copies or substantial portions of the Software.
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
22 """Create enum to string functions for vulkan using vk.xml."""
24 from __future__
import print_function
28 import xml
.etree
.cElementTree
as et
30 from mako
.template
import Template
32 COPYRIGHT
= textwrap
.dedent(u
"""\
33 * Copyright © 2017 Intel Corporation
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:
42 * The above copyright notice and this permission notice shall be included in
43 * all copies or substantial portions of the Software.
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
53 C_TEMPLATE
= Template(textwrap
.dedent(u
"""\
54 /* Autogenerated file -- do not edit
55 * generated by ${file}
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"
68 vk_${enum.name[2:]}_to_str(${enum.name} input)
71 % for v in sorted(enum.values.keys()):
72 % if enum.values[v] in FOREIGN_ENUM_VALUES:
74 #pragma GCC diagnostic push
75 #pragma GCC diagnostic ignored "-Wswitch"
78 return "${enum.values[v]}";
79 % if enum.values[v] in FOREIGN_ENUM_VALUES:
80 #pragma GCC diagnostic pop
85 unreachable("Undefined enum value.");
89 output_encoding
='utf-8')
91 H_TEMPLATE
= Template(textwrap
.dedent(u
"""\
92 /* Autogenerated file -- do not edit
93 * generated by ${file}
98 #ifndef MESA_VK_ENUM_TO_STR_H
99 #define MESA_VK_ENUM_TO_STR_H
101 #include <vulkan/vulkan.h>
102 #include <vulkan/vk_android_native_buffer.h>
108 % for ext in extensions:
109 #define _${ext.name}_number (${ext.number})
113 const char * vk_${enum.name[2:]}_to_str(${enum.name} input);
121 output_encoding
='utf-8')
123 # These enums are defined outside their respective enum blocks, and thus cause
125 FOREIGN_ENUM_VALUES
= [
126 "VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID",
130 class NamedFactory(object):
131 """Factory for creating enums."""
133 def __init__(self
, type_
):
137 def __call__(self
, name
, **kwargs
):
139 return self
.registry
[name
]
141 n
= self
.registry
[name
] = self
.type(name
, **kwargs
)
145 return self
.registry
.get(name
)
148 class VkExtension(object):
149 """Simple struct-like class representing extensions"""
151 def __init__(self
, name
, number
=None):
156 class VkEnum(object):
157 """Simple struct-like class representing a single Vulkan Enum."""
159 def __init__(self
, name
, values
=None):
161 # Maps numbers to names
162 self
.values
= values
or dict()
163 self
.name_to_value
= dict()
165 def add_value(self
, name
, value
=None,
166 extnum
=None, offset
=None,
168 assert value
is not None or extnum
is not None
170 value
= 1000000000 + (extnum
- 1) * 1000 + offset
174 self
.name_to_value
[name
] = value
175 if value
not in self
.values
:
176 self
.values
[value
] = name
177 elif len(self
.values
[value
]) > len(name
):
178 self
.values
[value
] = name
180 def add_value_from_xml(self
, elem
, extension
=None):
181 if 'value' in elem
.attrib
:
182 self
.add_value(elem
.attrib
['name'],
183 value
=int(elem
.attrib
['value'], base
=0))
184 elif 'alias' in elem
.attrib
:
185 self
.add_value(elem
.attrib
['name'],
186 value
=self
.name_to_value
[elem
.attrib
['alias']])
188 error
= 'dir' in elem
.attrib
and elem
.attrib
['dir'] == '-'
189 if 'extnumber' in elem
.attrib
:
190 extnum
= int(elem
.attrib
['extnumber'])
192 extnum
= extension
.number
193 self
.add_value(elem
.attrib
['name'],
195 offset
=int(elem
.attrib
['offset']),
199 def parse_xml(enum_factory
, ext_factory
, filename
):
200 """Parse the XML file. Accumulate results into the factories.
202 This parser is a memory efficient iterative XML parser that returns a list
206 xml
= et
.parse(filename
)
208 for enum_type
in xml
.findall('./enums[@type="enum"]'):
209 enum
= enum_factory(enum_type
.attrib
['name'])
210 for value
in enum_type
.findall('./enum'):
211 enum
.add_value_from_xml(value
)
213 for value
in xml
.findall('./feature/require/enum[@extends]'):
214 enum
= enum_factory
.get(value
.attrib
['extends'])
216 enum
.add_value_from_xml(value
)
218 for ext_elem
in xml
.findall('./extensions/extension[@supported="vulkan"]'):
219 extension
= ext_factory(ext_elem
.attrib
['name'],
220 number
=int(ext_elem
.attrib
['number']))
222 for value
in ext_elem
.findall('./require/enum[@extends]'):
223 enum
= enum_factory
.get(value
.attrib
['extends'])
225 enum
.add_value_from_xml(value
, extension
)
229 parser
= argparse
.ArgumentParser()
230 parser
.add_argument('--xml', required
=True,
231 help='Vulkan API XML files',
234 parser
.add_argument('--outdir',
235 help='Directory to put the generated files in',
238 args
= parser
.parse_args()
240 enum_factory
= NamedFactory(VkEnum
)
241 ext_factory
= NamedFactory(VkExtension
)
242 for filename
in args
.xml_files
:
243 parse_xml(enum_factory
, ext_factory
, filename
)
244 enums
= sorted(enum_factory
.registry
.values(), key
=lambda e
: e
.name
)
245 extensions
= sorted(ext_factory
.registry
.values(), key
=lambda e
: e
.name
)
247 for template
, file_
in [(C_TEMPLATE
, os
.path
.join(args
.outdir
, 'vk_enum_to_str.c')),
248 (H_TEMPLATE
, os
.path
.join(args
.outdir
, 'vk_enum_to_str.h'))]:
249 with
open(file_
, 'wb') as f
:
250 f
.write(template
.render(
251 file=os
.path
.basename(__file__
),
253 extensions
=extensions
,
255 FOREIGN_ENUM_VALUES
=FOREIGN_ENUM_VALUES
))
258 if __name__
== '__main__':