b65bc7f7ef64f166130fce073b7becc6b9be8d5d
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}
61 #include <vulkan/vulkan.h>
62 #include <vulkan/vk_android_native_buffer.h>
63 #include "util/macros.h"
64 #include "vk_enum_to_str.h"
72 vk_${enum.name[2:]}_to_str(${enum.name} input)
74 #pragma GCC diagnostic push
75 #pragma GCC diagnostic ignored "-Wswitch"
77 % for v in sorted(enum.values.keys()):
79 return "${enum.values[v]}";
82 #pragma GCC diagnostic pop
83 unreachable("Undefined enum value.");
91 size_t vk_structure_type_size(const struct VkBaseInStructure *item)
93 #pragma GCC diagnostic push
94 #pragma GCC diagnostic ignored "-Wswitch"
96 % for struct in structs:
97 % if struct.extension is not None and struct.extension.define is not None:
98 #ifdef ${struct.extension.define}
99 case ${struct.stype}: return sizeof(${struct.name});
102 case ${struct.stype}: return sizeof(${struct.name});
106 #pragma GCC diagnostic pop
107 unreachable("Undefined struct type.");
110 void vk_load_instance_commands(VkInstance instance,
111 PFN_vkGetInstanceProcAddr gpa,
112 struct vk_instance_dispatch_table *table)
114 memset(table, 0, sizeof(*table));
115 table->GetInstanceProcAddr = gpa;
116 % for cmd in commands:
117 % if not cmd.device_entrypoint and cmd.name != 'vkGetInstanceProcAddr':
118 % if cmd.extension is not None and cmd.extension.define is not None:
119 #ifdef ${cmd.extension.define}
120 table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(instance, "${cmd.name}");
123 table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(instance, "${cmd.name}");
129 void vk_load_device_commands(VkDevice device,
130 PFN_vkGetDeviceProcAddr gpa,
131 struct vk_device_dispatch_table *table)
133 memset(table, 0, sizeof(*table));
134 table->GetDeviceProcAddr = gpa;
135 % for cmd in commands:
136 % if cmd.device_entrypoint and cmd.name != 'vkGetDeviceProcAddr':
137 % if cmd.extension is not None and cmd.extension.define is not None:
138 #ifdef ${cmd.extension.define}
139 table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(device, "${cmd.name}");
142 table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(device, "${cmd.name}");
148 output_encoding
='utf-8')
150 H_TEMPLATE
= Template(textwrap
.dedent(u
"""\
151 /* Autogenerated file -- do not edit
152 * generated by ${file}
157 #ifndef MESA_VK_ENUM_TO_STR_H
158 #define MESA_VK_ENUM_TO_STR_H
160 #include <vulkan/vulkan.h>
161 #include <vulkan/vk_android_native_buffer.h>
167 % for ext in extensions:
168 #define _${ext.name}_number (${ext.number})
175 const char * vk_${enum.name[2:]}_to_str(${enum.name} input);
181 size_t vk_structure_type_size(const struct VkBaseInStructure *item);
183 struct vk_instance_dispatch_table {
184 PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
185 % for cmd in commands:
186 % if not cmd.device_entrypoint and cmd.name != 'vkGetInstanceProcAddr':
187 % if cmd.extension is not None and cmd.extension.define is not None:
188 #ifdef ${cmd.extension.define}
189 PFN_${cmd.name} ${cmd.name[2:]};
192 PFN_${cmd.name} ${cmd.name[2:]};
198 struct vk_device_dispatch_table {
199 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
200 % for cmd in commands:
201 % if cmd.device_entrypoint and cmd.name != 'vkGetDeviceProcAddr':
202 % if cmd.extension is not None and cmd.extension.define is not None:
203 #ifdef ${cmd.extension.define}
204 PFN_${cmd.name} ${cmd.name[2:]};
207 PFN_${cmd.name} ${cmd.name[2:]};
213 void vk_load_instance_commands(VkInstance instance, PFN_vkGetInstanceProcAddr gpa, struct vk_instance_dispatch_table *table);
214 void vk_load_device_commands(VkDevice device, PFN_vkGetDeviceProcAddr gpa, struct vk_device_dispatch_table *table);
221 output_encoding
='utf-8')
224 class NamedFactory(object):
225 """Factory for creating enums."""
227 def __init__(self
, type_
):
231 def __call__(self
, name
, **kwargs
):
233 return self
.registry
[name
]
235 n
= self
.registry
[name
] = self
.type(name
, **kwargs
)
239 return self
.registry
.get(name
)
242 class VkExtension(object):
243 """Simple struct-like class representing extensions"""
245 def __init__(self
, name
, number
=None, define
=None):
251 class VkEnum(object):
252 """Simple struct-like class representing a single Vulkan Enum."""
254 def __init__(self
, name
, values
=None):
256 self
.extension
= None
257 # Maps numbers to names
258 self
.values
= values
or dict()
259 self
.name_to_value
= dict()
262 def add_value(self
, name
, value
=None,
263 extnum
=None, offset
=None,
265 assert value
is not None or extnum
is not None
267 value
= 1000000000 + (extnum
- 1) * 1000 + offset
271 self
.name_to_value
[name
] = value
272 if value
not in self
.values
:
273 self
.values
[value
] = name
274 elif len(self
.values
[value
]) > len(name
):
275 self
.values
[value
] = name
277 def add_value_from_xml(self
, elem
, extension
=None):
278 self
.extension
= extension
279 if 'value' in elem
.attrib
:
280 self
.add_value(elem
.attrib
['name'],
281 value
=int(elem
.attrib
['value'], base
=0))
282 elif 'alias' in elem
.attrib
:
283 self
.add_value(elem
.attrib
['name'],
284 value
=self
.name_to_value
[elem
.attrib
['alias']])
286 error
= 'dir' in elem
.attrib
and elem
.attrib
['dir'] == '-'
287 if 'extnumber' in elem
.attrib
:
288 extnum
= int(elem
.attrib
['extnumber'])
290 extnum
= extension
.number
291 self
.add_value(elem
.attrib
['name'],
293 offset
=int(elem
.attrib
['offset']),
296 def set_guard(self
, g
):
300 class VkCommand(object):
301 """Simple struct-like class representing a single Vulkan command"""
303 def __init__(self
, name
, device_entrypoint
=False):
305 self
.device_entrypoint
= device_entrypoint
306 self
.extension
= None
309 class VkChainStruct(object):
310 """Simple struct-like class representing a single Vulkan struct identified with a VkStructureType"""
311 def __init__(self
, name
, stype
):
314 self
.extension
= None
317 def struct_get_stype(xml_node
):
318 for member
in xml_node
.findall('./member'):
319 name
= member
.findall('./name')
320 if len(name
) > 0 and name
[0].text
== "sType":
321 return member
.get('values')
325 def parse_xml(cmd_factory
, enum_factory
, ext_factory
, struct_factory
, filename
):
326 """Parse the XML file. Accumulate results into the factories.
328 This parser is a memory efficient iterative XML parser that returns a list
332 xml
= et
.parse(filename
)
334 for enum_type
in xml
.findall('./enums[@type="enum"]'):
335 enum
= enum_factory(enum_type
.attrib
['name'])
336 for value
in enum_type
.findall('./enum'):
337 enum
.add_value_from_xml(value
)
339 for value
in xml
.findall('./feature/require/enum[@extends]'):
340 enum
= enum_factory
.get(value
.attrib
['extends'])
342 enum
.add_value_from_xml(value
)
344 for command
in xml
.findall('./commands/command'):
345 name
= command
.find('./proto/name')
346 first_arg
= command
.find('./param/type')
347 # Some commands are alias KHR -> nonKHR, ignore those
349 cmd_factory(name
.text
,
350 device_entrypoint
=(first_arg
.text
in ('VkDevice', 'VkCommandBuffer', 'VkQueue')))
352 for struct_type
in xml
.findall('./types/type[@category="struct"]'):
353 name
= struct_type
.attrib
['name']
354 stype
= struct_get_stype(struct_type
)
355 if stype
is not None:
356 struct_factory(name
, stype
=stype
)
359 for platform
in xml
.findall('./platforms/platform'):
360 name
= platform
.attrib
['name']
361 define
= platform
.attrib
['protect']
362 platform_define
[name
] = define
364 for ext_elem
in xml
.findall('./extensions/extension[@supported="vulkan"]'):
366 if "platform" in ext_elem
.attrib
:
367 define
= platform_define
[ext_elem
.attrib
['platform']]
368 extension
= ext_factory(ext_elem
.attrib
['name'],
369 number
=int(ext_elem
.attrib
['number']),
372 for value
in ext_elem
.findall('./require/enum[@extends]'):
373 enum
= enum_factory
.get(value
.attrib
['extends'])
375 enum
.add_value_from_xml(value
, extension
)
376 for t
in ext_elem
.findall('./require/type'):
377 struct
= struct_factory
.get(t
.attrib
['name'])
378 if struct
is not None:
379 struct
.extension
= extension
382 for value
in ext_elem
.findall('./require/type[@name]'):
383 enum
= enum_factory
.get(value
.attrib
['name'])
385 enum
.set_guard(define
)
387 for t
in ext_elem
.findall('./require/command'):
388 command
= cmd_factory
.get(t
.attrib
['name'])
389 if command
is not None:
390 command
.extension
= extension
394 parser
= argparse
.ArgumentParser()
395 parser
.add_argument('--xml', required
=True,
396 help='Vulkan API XML files',
399 parser
.add_argument('--outdir',
400 help='Directory to put the generated files in',
403 args
= parser
.parse_args()
405 command_factory
= NamedFactory(VkCommand
)
406 enum_factory
= NamedFactory(VkEnum
)
407 ext_factory
= NamedFactory(VkExtension
)
408 struct_factory
= NamedFactory(VkChainStruct
)
409 for filename
in args
.xml_files
:
410 parse_xml(command_factory
, enum_factory
, ext_factory
, struct_factory
, filename
)
411 commands
= sorted(command_factory
.registry
.values(), key
=lambda e
: e
.name
)
412 enums
= sorted(enum_factory
.registry
.values(), key
=lambda e
: e
.name
)
413 extensions
= sorted(ext_factory
.registry
.values(), key
=lambda e
: e
.name
)
414 structs
= sorted(struct_factory
.registry
.values(), key
=lambda e
: e
.name
)
416 for template
, file_
in [(C_TEMPLATE
, os
.path
.join(args
.outdir
, 'vk_enum_to_str.c')),
417 (H_TEMPLATE
, os
.path
.join(args
.outdir
, 'vk_enum_to_str.h'))]:
418 with
open(file_
, 'wb') as f
:
419 f
.write(template
.render(
420 file=os
.path
.basename(__file__
),
423 extensions
=extensions
,
425 copyright
=COPYRIGHT
))
428 if __name__
== '__main__':