1bf215546Sopenharmony_ci# Copyright © 2017 Intel Corporation
2bf215546Sopenharmony_ci
3bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a copy
4bf215546Sopenharmony_ci# of this software and associated documentation files (the "Software"), to deal
5bf215546Sopenharmony_ci# in the Software without restriction, including without limitation the rights
6bf215546Sopenharmony_ci# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7bf215546Sopenharmony_ci# copies of the Software, and to permit persons to whom the Software is
8bf215546Sopenharmony_ci# furnished to do so, subject to the following conditions:
9bf215546Sopenharmony_ci
10bf215546Sopenharmony_ci# The above copyright notice and this permission notice shall be included in
11bf215546Sopenharmony_ci# all copies or substantial portions of the Software.
12bf215546Sopenharmony_ci
13bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16bf215546Sopenharmony_ci# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18bf215546Sopenharmony_ci# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19bf215546Sopenharmony_ci# SOFTWARE.
20bf215546Sopenharmony_ci
21bf215546Sopenharmony_ci"""Create enum to string functions for vulkan using vk.xml."""
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ciimport argparse
24bf215546Sopenharmony_ciimport functools
25bf215546Sopenharmony_ciimport os
26bf215546Sopenharmony_ciimport re
27bf215546Sopenharmony_ciimport textwrap
28bf215546Sopenharmony_ciimport xml.etree.ElementTree as et
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_cifrom mako.template import Template
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ciCOPYRIGHT = textwrap.dedent(u"""\
33bf215546Sopenharmony_ci    * Copyright © 2017 Intel Corporation
34bf215546Sopenharmony_ci    *
35bf215546Sopenharmony_ci    * Permission is hereby granted, free of charge, to any person obtaining a copy
36bf215546Sopenharmony_ci    * of this software and associated documentation files (the "Software"), to deal
37bf215546Sopenharmony_ci    * in the Software without restriction, including without limitation the rights
38bf215546Sopenharmony_ci    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39bf215546Sopenharmony_ci    * copies of the Software, and to permit persons to whom the Software is
40bf215546Sopenharmony_ci    * furnished to do so, subject to the following conditions:
41bf215546Sopenharmony_ci    *
42bf215546Sopenharmony_ci    * The above copyright notice and this permission notice shall be included in
43bf215546Sopenharmony_ci    * all copies or substantial portions of the Software.
44bf215546Sopenharmony_ci    *
45bf215546Sopenharmony_ci    * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46bf215546Sopenharmony_ci    * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47bf215546Sopenharmony_ci    * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48bf215546Sopenharmony_ci    * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49bf215546Sopenharmony_ci    * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50bf215546Sopenharmony_ci    * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
51bf215546Sopenharmony_ci    * SOFTWARE.""")
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ciC_TEMPLATE = Template(textwrap.dedent(u"""\
54bf215546Sopenharmony_ci    /* Autogenerated file -- do not edit
55bf215546Sopenharmony_ci     * generated by ${file}
56bf215546Sopenharmony_ci     *
57bf215546Sopenharmony_ci     ${copyright}
58bf215546Sopenharmony_ci     */
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci    #include <string.h>
61bf215546Sopenharmony_ci    #include <vulkan/vulkan.h>
62bf215546Sopenharmony_ci    #include <vulkan/vk_android_native_buffer.h>
63bf215546Sopenharmony_ci    #include <vulkan/vk_layer.h>
64bf215546Sopenharmony_ci    #include "util/macros.h"
65bf215546Sopenharmony_ci    #include "vk_enum_to_str.h"
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci    % for enum in enums:
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci      % if enum.guard:
70bf215546Sopenharmony_ci#ifdef ${enum.guard}
71bf215546Sopenharmony_ci      % endif
72bf215546Sopenharmony_ci    const char *
73bf215546Sopenharmony_ci    vk_${enum.name[2:]}_to_str(${enum.name} input)
74bf215546Sopenharmony_ci    {
75bf215546Sopenharmony_ci        switch((int64_t)input) {
76bf215546Sopenharmony_ci    % for v in sorted(enum.values.keys()):
77bf215546Sopenharmony_ci        case ${v}:
78bf215546Sopenharmony_ci            return "${enum.values[v]}";
79bf215546Sopenharmony_ci    % endfor
80bf215546Sopenharmony_ci        case ${enum.max_enum_name}: return "${enum.max_enum_name}";
81bf215546Sopenharmony_ci        default:
82bf215546Sopenharmony_ci            return "Unknown ${enum.name} value.";
83bf215546Sopenharmony_ci        }
84bf215546Sopenharmony_ci    }
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci      % if enum.guard:
87bf215546Sopenharmony_ci#endif
88bf215546Sopenharmony_ci      % endif
89bf215546Sopenharmony_ci    %endfor
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci    size_t vk_structure_type_size(const struct VkBaseInStructure *item)
92bf215546Sopenharmony_ci    {
93bf215546Sopenharmony_ci        switch((int)item->sType) {
94bf215546Sopenharmony_ci    % for struct in structs:
95bf215546Sopenharmony_ci        % if struct.extension is not None and struct.extension.define is not None:
96bf215546Sopenharmony_ci    #ifdef ${struct.extension.define}
97bf215546Sopenharmony_ci        case ${struct.stype}: return sizeof(${struct.name});
98bf215546Sopenharmony_ci    #endif
99bf215546Sopenharmony_ci        % else:
100bf215546Sopenharmony_ci        case ${struct.stype}: return sizeof(${struct.name});
101bf215546Sopenharmony_ci        % endif
102bf215546Sopenharmony_ci    %endfor
103bf215546Sopenharmony_ci        case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: return sizeof(VkLayerInstanceCreateInfo);
104bf215546Sopenharmony_ci        case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO: return sizeof(VkLayerDeviceCreateInfo);
105bf215546Sopenharmony_ci        default:
106bf215546Sopenharmony_ci            unreachable("Undefined struct type.");
107bf215546Sopenharmony_ci        }
108bf215546Sopenharmony_ci    }
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci    const char *
111bf215546Sopenharmony_ci    vk_ObjectType_to_ObjectName(VkObjectType type)
112bf215546Sopenharmony_ci    {
113bf215546Sopenharmony_ci        switch((int)type) {
114bf215546Sopenharmony_ci    % for object_type in sorted(object_types[0].enum_to_name.keys()):
115bf215546Sopenharmony_ci        case ${object_type}:
116bf215546Sopenharmony_ci            return "${object_types[0].enum_to_name[object_type]}";
117bf215546Sopenharmony_ci    % endfor
118bf215546Sopenharmony_ci        default:
119bf215546Sopenharmony_ci            return "Unknown VkObjectType value.";
120bf215546Sopenharmony_ci        }
121bf215546Sopenharmony_ci    }
122bf215546Sopenharmony_ci    """))
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ciH_TEMPLATE = Template(textwrap.dedent(u"""\
125bf215546Sopenharmony_ci    /* Autogenerated file -- do not edit
126bf215546Sopenharmony_ci     * generated by ${file}
127bf215546Sopenharmony_ci     *
128bf215546Sopenharmony_ci     ${copyright}
129bf215546Sopenharmony_ci     */
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci    #ifndef MESA_VK_ENUM_TO_STR_H
132bf215546Sopenharmony_ci    #define MESA_VK_ENUM_TO_STR_H
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci    #include <vulkan/vulkan.h>
135bf215546Sopenharmony_ci    #include <vulkan/vk_android_native_buffer.h>
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci    #ifdef __cplusplus
138bf215546Sopenharmony_ci    extern "C" {
139bf215546Sopenharmony_ci    #endif
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci    % for enum in enums:
142bf215546Sopenharmony_ci      % if enum.guard:
143bf215546Sopenharmony_ci#ifdef ${enum.guard}
144bf215546Sopenharmony_ci      % endif
145bf215546Sopenharmony_ci    const char * vk_${enum.name[2:]}_to_str(${enum.name} input);
146bf215546Sopenharmony_ci      % if enum.guard:
147bf215546Sopenharmony_ci#endif
148bf215546Sopenharmony_ci      % endif
149bf215546Sopenharmony_ci    % endfor
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci    size_t vk_structure_type_size(const struct VkBaseInStructure *item);
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci    const char * vk_ObjectType_to_ObjectName(VkObjectType type);
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci    #ifdef __cplusplus
156bf215546Sopenharmony_ci    } /* extern "C" */
157bf215546Sopenharmony_ci    #endif
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci    #endif"""))
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ciH_DEFINE_TEMPLATE = Template(textwrap.dedent(u"""\
163bf215546Sopenharmony_ci    /* Autogenerated file -- do not edit
164bf215546Sopenharmony_ci     * generated by ${file}
165bf215546Sopenharmony_ci     *
166bf215546Sopenharmony_ci     ${copyright}
167bf215546Sopenharmony_ci     */
168bf215546Sopenharmony_ci
169bf215546Sopenharmony_ci    #ifndef MESA_VK_ENUM_DEFINES_H
170bf215546Sopenharmony_ci    #define MESA_VK_ENUM_DEFINES_H
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci    #include <vulkan/vulkan.h>
173bf215546Sopenharmony_ci    #include <vulkan/vk_android_native_buffer.h>
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci    #ifdef __cplusplus
176bf215546Sopenharmony_ci    extern "C" {
177bf215546Sopenharmony_ci    #endif
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci    % for ext in extensions:
180bf215546Sopenharmony_ci    #define _${ext.name}_number (${ext.number})
181bf215546Sopenharmony_ci    % endfor
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci    % for enum in bitmasks:
184bf215546Sopenharmony_ci      % if enum.bitwidth > 32:
185bf215546Sopenharmony_ci        <% continue %>
186bf215546Sopenharmony_ci      % endif
187bf215546Sopenharmony_ci      % if enum.guard:
188bf215546Sopenharmony_ci#ifdef ${enum.guard}
189bf215546Sopenharmony_ci      % endif
190bf215546Sopenharmony_ci    #define ${enum.all_bits_name()} ${hex(enum.all_bits_value())}u
191bf215546Sopenharmony_ci      % if enum.guard:
192bf215546Sopenharmony_ci#endif
193bf215546Sopenharmony_ci      % endif
194bf215546Sopenharmony_ci    % endfor
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci    % for enum in bitmasks:
197bf215546Sopenharmony_ci      % if enum.bitwidth < 64:
198bf215546Sopenharmony_ci        <% continue %>
199bf215546Sopenharmony_ci      % endif
200bf215546Sopenharmony_ci    /* Redefine bitmask values of ${enum.name} */
201bf215546Sopenharmony_ci      % if enum.guard:
202bf215546Sopenharmony_ci#ifdef ${enum.guard}
203bf215546Sopenharmony_ci      % endif
204bf215546Sopenharmony_ci      % for n, v in enum.name_to_value.items():
205bf215546Sopenharmony_ci    #define ${n} (${hex(v)}ULL)
206bf215546Sopenharmony_ci      % endfor
207bf215546Sopenharmony_ci      % if enum.guard:
208bf215546Sopenharmony_ci#endif
209bf215546Sopenharmony_ci      % endif
210bf215546Sopenharmony_ci    % endfor
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci    #ifdef __cplusplus
213bf215546Sopenharmony_ci    } /* extern "C" */
214bf215546Sopenharmony_ci    #endif
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci    #endif"""))
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ciclass NamedFactory(object):
220bf215546Sopenharmony_ci    """Factory for creating enums."""
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci    def __init__(self, type_):
223bf215546Sopenharmony_ci        self.registry = {}
224bf215546Sopenharmony_ci        self.type = type_
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci    def __call__(self, name, **kwargs):
227bf215546Sopenharmony_ci        try:
228bf215546Sopenharmony_ci            return self.registry[name]
229bf215546Sopenharmony_ci        except KeyError:
230bf215546Sopenharmony_ci            n = self.registry[name] = self.type(name, **kwargs)
231bf215546Sopenharmony_ci        return n
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci    def get(self, name):
234bf215546Sopenharmony_ci        return self.registry.get(name)
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ciclass VkExtension(object):
238bf215546Sopenharmony_ci    """Simple struct-like class representing extensions"""
239bf215546Sopenharmony_ci
240bf215546Sopenharmony_ci    def __init__(self, name, number=None, define=None):
241bf215546Sopenharmony_ci        self.name = name
242bf215546Sopenharmony_ci        self.number = number
243bf215546Sopenharmony_ci        self.define = define
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_cidef CamelCase_to_SHOUT_CASE(s):
247bf215546Sopenharmony_ci   return (s[:1] + re.sub(r'(?<![A-Z])([A-Z])', r'_\1', s[1:])).upper()
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_cidef compute_max_enum_name(s):
250bf215546Sopenharmony_ci    max_enum_name = CamelCase_to_SHOUT_CASE(s)
251bf215546Sopenharmony_ci    last_prefix = max_enum_name.rsplit('_', 1)[-1]
252bf215546Sopenharmony_ci    # Those special prefixes need to be always at the end
253bf215546Sopenharmony_ci    if last_prefix in ['AMD', 'EXT', 'INTEL', 'KHR', 'NV'] :
254bf215546Sopenharmony_ci        max_enum_name = "_".join(max_enum_name.split('_')[:-1])
255bf215546Sopenharmony_ci        max_enum_name = max_enum_name + "_MAX_ENUM_" + last_prefix
256bf215546Sopenharmony_ci    else:
257bf215546Sopenharmony_ci        max_enum_name = max_enum_name + "_MAX_ENUM"
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci    return max_enum_name
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_ciclass VkEnum(object):
262bf215546Sopenharmony_ci    """Simple struct-like class representing a single Vulkan Enum."""
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci    def __init__(self, name, bitwidth=32, values=None):
265bf215546Sopenharmony_ci        self.name = name
266bf215546Sopenharmony_ci        self.max_enum_name = compute_max_enum_name(name)
267bf215546Sopenharmony_ci        self.bitwidth = bitwidth
268bf215546Sopenharmony_ci        self.extension = None
269bf215546Sopenharmony_ci        # Maps numbers to names
270bf215546Sopenharmony_ci        self.values = values or dict()
271bf215546Sopenharmony_ci        self.name_to_value = dict()
272bf215546Sopenharmony_ci        self.guard = None
273bf215546Sopenharmony_ci        self.name_to_alias_list = {}
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci    def all_bits_name(self):
276bf215546Sopenharmony_ci        assert self.name.startswith('Vk')
277bf215546Sopenharmony_ci        assert re.search(r'FlagBits[A-Z]*$', self.name)
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci        return 'VK_ALL_' + CamelCase_to_SHOUT_CASE(self.name[2:])
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci    def all_bits_value(self):
282bf215546Sopenharmony_ci        return functools.reduce(lambda a,b: a | b, self.values.keys(), 0)
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci    def add_value(self, name, value=None,
285bf215546Sopenharmony_ci                  extnum=None, offset=None, alias=None,
286bf215546Sopenharmony_ci                  error=False):
287bf215546Sopenharmony_ci        if alias is not None:
288bf215546Sopenharmony_ci            assert value is None and offset is None
289bf215546Sopenharmony_ci            if alias not in self.name_to_value:
290bf215546Sopenharmony_ci                # We don't have this alias yet.  Just record the alias and
291bf215546Sopenharmony_ci                # we'll deal with it later.
292bf215546Sopenharmony_ci                alias_list = self.name_to_alias_list.setdefault(alias, [])
293bf215546Sopenharmony_ci                alias_list.append(name);
294bf215546Sopenharmony_ci                return
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci            # Use the value from the alias
297bf215546Sopenharmony_ci            value = self.name_to_value[alias]
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci        assert value is not None or extnum is not None
300bf215546Sopenharmony_ci        if value is None:
301bf215546Sopenharmony_ci            value = 1000000000 + (extnum - 1) * 1000 + offset
302bf215546Sopenharmony_ci            if error:
303bf215546Sopenharmony_ci                value = -value
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci        self.name_to_value[name] = value
306bf215546Sopenharmony_ci        if value not in self.values:
307bf215546Sopenharmony_ci            self.values[value] = name
308bf215546Sopenharmony_ci        elif len(self.values[value]) > len(name):
309bf215546Sopenharmony_ci            self.values[value] = name
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci        # Now that the value has been fully added, resolve aliases, if any.
312bf215546Sopenharmony_ci        if name in self.name_to_alias_list:
313bf215546Sopenharmony_ci            for alias in self.name_to_alias_list[name]:
314bf215546Sopenharmony_ci                self.add_value(alias, value)
315bf215546Sopenharmony_ci            del self.name_to_alias_list[name]
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci    def add_value_from_xml(self, elem, extension=None):
318bf215546Sopenharmony_ci        self.extension = extension
319bf215546Sopenharmony_ci        if 'value' in elem.attrib:
320bf215546Sopenharmony_ci            self.add_value(elem.attrib['name'],
321bf215546Sopenharmony_ci                           value=int(elem.attrib['value'], base=0))
322bf215546Sopenharmony_ci        elif 'bitpos' in elem.attrib:
323bf215546Sopenharmony_ci            self.add_value(elem.attrib['name'],
324bf215546Sopenharmony_ci                           value=(1 << int(elem.attrib['bitpos'], base=0)))
325bf215546Sopenharmony_ci        elif 'alias' in elem.attrib:
326bf215546Sopenharmony_ci            self.add_value(elem.attrib['name'], alias=elem.attrib['alias'])
327bf215546Sopenharmony_ci        else:
328bf215546Sopenharmony_ci            error = 'dir' in elem.attrib and elem.attrib['dir'] == '-'
329bf215546Sopenharmony_ci            if 'extnumber' in elem.attrib:
330bf215546Sopenharmony_ci                extnum = int(elem.attrib['extnumber'])
331bf215546Sopenharmony_ci            else:
332bf215546Sopenharmony_ci                extnum = extension.number
333bf215546Sopenharmony_ci            self.add_value(elem.attrib['name'],
334bf215546Sopenharmony_ci                           extnum=extnum,
335bf215546Sopenharmony_ci                           offset=int(elem.attrib['offset']),
336bf215546Sopenharmony_ci                           error=error)
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci    def set_guard(self, g):
339bf215546Sopenharmony_ci        self.guard = g
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ciclass VkChainStruct(object):
343bf215546Sopenharmony_ci    """Simple struct-like class representing a single Vulkan struct identified with a VkStructureType"""
344bf215546Sopenharmony_ci    def __init__(self, name, stype):
345bf215546Sopenharmony_ci        self.name = name
346bf215546Sopenharmony_ci        self.stype = stype
347bf215546Sopenharmony_ci        self.extension = None
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_cidef struct_get_stype(xml_node):
351bf215546Sopenharmony_ci    for member in xml_node.findall('./member'):
352bf215546Sopenharmony_ci        name = member.findall('./name')
353bf215546Sopenharmony_ci        if len(name) > 0 and name[0].text == "sType":
354bf215546Sopenharmony_ci            return member.get('values')
355bf215546Sopenharmony_ci    return None
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ciclass VkObjectType(object):
358bf215546Sopenharmony_ci    """Simple struct-like class representing a single Vulkan object type"""
359bf215546Sopenharmony_ci    def __init__(self, name):
360bf215546Sopenharmony_ci        self.name = name
361bf215546Sopenharmony_ci        self.enum_to_name = dict()
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_cidef parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory,
365bf215546Sopenharmony_ci              obj_type_factory, filename):
366bf215546Sopenharmony_ci    """Parse the XML file. Accumulate results into the factories.
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci    This parser is a memory efficient iterative XML parser that returns a list
369bf215546Sopenharmony_ci    of VkEnum objects.
370bf215546Sopenharmony_ci    """
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci    xml = et.parse(filename)
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci    for enum_type in xml.findall('./enums[@type="enum"]'):
375bf215546Sopenharmony_ci        enum = enum_factory(enum_type.attrib['name'])
376bf215546Sopenharmony_ci        for value in enum_type.findall('./enum'):
377bf215546Sopenharmony_ci            enum.add_value_from_xml(value)
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_ci    # For bitmask we only add the Enum selected for convenience.
380bf215546Sopenharmony_ci    for enum_type in xml.findall('./enums[@type="bitmask"]'):
381bf215546Sopenharmony_ci        bitwidth = int(enum_type.attrib.get('bitwidth', 32))
382bf215546Sopenharmony_ci        enum = bitmask_factory(enum_type.attrib['name'], bitwidth=bitwidth)
383bf215546Sopenharmony_ci        for value in enum_type.findall('./enum'):
384bf215546Sopenharmony_ci            enum.add_value_from_xml(value)
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci    for value in xml.findall('./feature/require/enum[@extends]'):
387bf215546Sopenharmony_ci        extends = value.attrib['extends']
388bf215546Sopenharmony_ci        enum = enum_factory.get(extends)
389bf215546Sopenharmony_ci        if enum is not None:
390bf215546Sopenharmony_ci            enum.add_value_from_xml(value)
391bf215546Sopenharmony_ci        enum = bitmask_factory.get(extends)
392bf215546Sopenharmony_ci        if enum is not None:
393bf215546Sopenharmony_ci            enum.add_value_from_xml(value)
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci    for struct_type in xml.findall('./types/type[@category="struct"]'):
396bf215546Sopenharmony_ci        name = struct_type.attrib['name']
397bf215546Sopenharmony_ci        stype = struct_get_stype(struct_type)
398bf215546Sopenharmony_ci        if stype is not None:
399bf215546Sopenharmony_ci            struct_factory(name, stype=stype)
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci    platform_define = {}
402bf215546Sopenharmony_ci    for platform in xml.findall('./platforms/platform'):
403bf215546Sopenharmony_ci        name = platform.attrib['name']
404bf215546Sopenharmony_ci        define = platform.attrib['protect']
405bf215546Sopenharmony_ci        platform_define[name] = define
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci    for ext_elem in xml.findall('./extensions/extension[@supported="vulkan"]'):
408bf215546Sopenharmony_ci        define = None
409bf215546Sopenharmony_ci        if "platform" in ext_elem.attrib:
410bf215546Sopenharmony_ci            define = platform_define[ext_elem.attrib['platform']]
411bf215546Sopenharmony_ci        extension = ext_factory(ext_elem.attrib['name'],
412bf215546Sopenharmony_ci                                number=int(ext_elem.attrib['number']),
413bf215546Sopenharmony_ci                                define=define)
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci        for value in ext_elem.findall('./require/enum[@extends]'):
416bf215546Sopenharmony_ci            extends = value.attrib['extends']
417bf215546Sopenharmony_ci            enum = enum_factory.get(extends)
418bf215546Sopenharmony_ci            if enum is not None:
419bf215546Sopenharmony_ci                enum.add_value_from_xml(value, extension)
420bf215546Sopenharmony_ci            enum = bitmask_factory.get(extends)
421bf215546Sopenharmony_ci            if enum is not None:
422bf215546Sopenharmony_ci                enum.add_value_from_xml(value, extension)
423bf215546Sopenharmony_ci        for t in ext_elem.findall('./require/type'):
424bf215546Sopenharmony_ci            struct = struct_factory.get(t.attrib['name'])
425bf215546Sopenharmony_ci            if struct is not None:
426bf215546Sopenharmony_ci                struct.extension = extension
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci        if define:
429bf215546Sopenharmony_ci            for value in ext_elem.findall('./require/type[@name]'):
430bf215546Sopenharmony_ci                enum = enum_factory.get(value.attrib['name'])
431bf215546Sopenharmony_ci                if enum is not None:
432bf215546Sopenharmony_ci                    enum.set_guard(define)
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci    obj_types = obj_type_factory("VkObjectType")
435bf215546Sopenharmony_ci    for object_type in xml.findall('./types/type[@category="handle"]'):
436bf215546Sopenharmony_ci        for object_name in object_type.findall('./name'):
437bf215546Sopenharmony_ci            # Convert to int to avoid undefined enums
438bf215546Sopenharmony_ci            enum = object_type.attrib['objtypeenum']
439bf215546Sopenharmony_ci            enum_val = enum_factory.get("VkObjectType").name_to_value[enum]
440bf215546Sopenharmony_ci            obj_types.enum_to_name[enum_val] = object_name.text
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_cidef main():
444bf215546Sopenharmony_ci    parser = argparse.ArgumentParser()
445bf215546Sopenharmony_ci    parser.add_argument('--xml', required=True,
446bf215546Sopenharmony_ci                        help='Vulkan API XML files',
447bf215546Sopenharmony_ci                        action='append',
448bf215546Sopenharmony_ci                        dest='xml_files')
449bf215546Sopenharmony_ci    parser.add_argument('--outdir',
450bf215546Sopenharmony_ci                        help='Directory to put the generated files in',
451bf215546Sopenharmony_ci                        required=True)
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci    args = parser.parse_args()
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_ci    enum_factory = NamedFactory(VkEnum)
456bf215546Sopenharmony_ci    ext_factory = NamedFactory(VkExtension)
457bf215546Sopenharmony_ci    struct_factory = NamedFactory(VkChainStruct)
458bf215546Sopenharmony_ci    obj_type_factory = NamedFactory(VkObjectType)
459bf215546Sopenharmony_ci    bitmask_factory = NamedFactory(VkEnum)
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci    for filename in args.xml_files:
462bf215546Sopenharmony_ci        parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory,
463bf215546Sopenharmony_ci                  obj_type_factory, filename)
464bf215546Sopenharmony_ci    enums = sorted(enum_factory.registry.values(), key=lambda e: e.name)
465bf215546Sopenharmony_ci    extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name)
466bf215546Sopenharmony_ci    structs = sorted(struct_factory.registry.values(), key=lambda e: e.name)
467bf215546Sopenharmony_ci    bitmasks = sorted(bitmask_factory.registry.values(), key=lambda e: e.name)
468bf215546Sopenharmony_ci    object_types = sorted(obj_type_factory.registry.values(), key=lambda e: e.name)
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci    for template, file_ in [(C_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.c')),
471bf215546Sopenharmony_ci                            (H_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.h')),
472bf215546Sopenharmony_ci                            (H_DEFINE_TEMPLATE, os.path.join(args.outdir, 'vk_enum_defines.h'))]:
473bf215546Sopenharmony_ci        with open(file_, 'w', encoding='utf-8') as f:
474bf215546Sopenharmony_ci            f.write(template.render(
475bf215546Sopenharmony_ci                file=os.path.basename(__file__),
476bf215546Sopenharmony_ci                enums=enums,
477bf215546Sopenharmony_ci                extensions=extensions,
478bf215546Sopenharmony_ci                structs=structs,
479bf215546Sopenharmony_ci                bitmasks=bitmasks,
480bf215546Sopenharmony_ci                object_types=object_types,
481bf215546Sopenharmony_ci                copyright=COPYRIGHT))
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ciif __name__ == '__main__':
485bf215546Sopenharmony_ci    main()
486