xref: /aosp_15_r20/external/mesa3d/src/gfxstream/codegen/scripts/reg.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker#!/usr/bin/python3 -i
2*61046927SAndroid Build Coastguard Worker#
3*61046927SAndroid Build Coastguard Worker# Copyright 2013-2023 The Khronos Group Inc.
4*61046927SAndroid Build Coastguard Worker# Copyright 2023-2024 Google Inc.
5*61046927SAndroid Build Coastguard Worker#
6*61046927SAndroid Build Coastguard Worker# SPDX-License-Identifier: Apache-2.0
7*61046927SAndroid Build Coastguard Worker
8*61046927SAndroid Build Coastguard Worker"""Types and classes for manipulating an API registry."""
9*61046927SAndroid Build Coastguard Worker
10*61046927SAndroid Build Coastguard Workerimport copy
11*61046927SAndroid Build Coastguard Workerimport re
12*61046927SAndroid Build Coastguard Workerimport sys
13*61046927SAndroid Build Coastguard Workerimport xml.etree.ElementTree as etree
14*61046927SAndroid Build Coastguard Workerfrom collections import defaultdict, deque, namedtuple
15*61046927SAndroid Build Coastguard Worker
16*61046927SAndroid Build Coastguard Workerfrom generator import GeneratorOptions, OutputGenerator, noneStr, write
17*61046927SAndroid Build Coastguard Worker
18*61046927SAndroid Build Coastguard Workerdef apiNameMatch(str, supported):
19*61046927SAndroid Build Coastguard Worker    """Return whether a required api name matches a pattern specified for an
20*61046927SAndroid Build Coastguard Worker    XML <feature> 'api' attribute or <extension> 'supported' attribute.
21*61046927SAndroid Build Coastguard Worker
22*61046927SAndroid Build Coastguard Worker    - str - API name such as 'vulkan' or 'openxr'. May be None, in which
23*61046927SAndroid Build Coastguard Worker        case it never matches (this should not happen).
24*61046927SAndroid Build Coastguard Worker    - supported - comma-separated list of XML API names. May be None, in
25*61046927SAndroid Build Coastguard Worker        which case str always matches (this is the usual case)."""
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker    if str is not None:
28*61046927SAndroid Build Coastguard Worker        return supported is None or str in supported.split(',')
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker    # Fallthrough case - either str is None or the test failed
31*61046927SAndroid Build Coastguard Worker    return False
32*61046927SAndroid Build Coastguard Worker
33*61046927SAndroid Build Coastguard Workerdef matchAPIProfile(api, elem):
34*61046927SAndroid Build Coastguard Worker    """Return whether an API and profile
35*61046927SAndroid Build Coastguard Worker    like `"gl(core)|gles1(common-lite)"`."""
36*61046927SAndroid Build Coastguard Worker    # Match 'api', if present
37*61046927SAndroid Build Coastguard Worker    elem_api = elem.get('api')
38*61046927SAndroid Build Coastguard Worker    if elem_api:
39*61046927SAndroid Build Coastguard Worker        if api is None:
40*61046927SAndroid Build Coastguard Worker            raise UserWarning("No API requested, but 'api' attribute is present with value '"
41*61046927SAndroid Build Coastguard Worker                              + elem_api + "'")
42*61046927SAndroid Build Coastguard Worker        elif api != elem_api:
43*61046927SAndroid Build Coastguard Worker            # Requested API does not match attribute
44*61046927SAndroid Build Coastguard Worker            return False
45*61046927SAndroid Build Coastguard Worker    return True
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Workerclass BaseInfo:
48*61046927SAndroid Build Coastguard Worker    """Base class for information about a registry feature
49*61046927SAndroid Build Coastguard Worker    (type/group/enum/command/API/extension).
50*61046927SAndroid Build Coastguard Worker
51*61046927SAndroid Build Coastguard Worker    Represents the state of a registry feature, used during API generation.
52*61046927SAndroid Build Coastguard Worker    """
53*61046927SAndroid Build Coastguard Worker
54*61046927SAndroid Build Coastguard Worker    def __init__(self, elem):
55*61046927SAndroid Build Coastguard Worker        self.required = False
56*61046927SAndroid Build Coastguard Worker        """should this feature be defined during header generation
57*61046927SAndroid Build Coastguard Worker        (has it been removed by a profile or version)?"""
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker        self.declared = False
60*61046927SAndroid Build Coastguard Worker        "has this feature been defined already?"
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker        self.elem = elem
63*61046927SAndroid Build Coastguard Worker        "etree Element for this feature"
64*61046927SAndroid Build Coastguard Worker
65*61046927SAndroid Build Coastguard Worker    def resetState(self):
66*61046927SAndroid Build Coastguard Worker        """Reset required/declared to initial values. Used
67*61046927SAndroid Build Coastguard Worker        prior to generating a new API interface."""
68*61046927SAndroid Build Coastguard Worker        self.required = False
69*61046927SAndroid Build Coastguard Worker        self.declared = False
70*61046927SAndroid Build Coastguard Worker
71*61046927SAndroid Build Coastguard Worker    def compareKeys(self, info, key, required = False):
72*61046927SAndroid Build Coastguard Worker        """Return True if self.elem and info.elem have the same attribute
73*61046927SAndroid Build Coastguard Worker           value for key.
74*61046927SAndroid Build Coastguard Worker           If 'required' is not True, also returns True if neither element
75*61046927SAndroid Build Coastguard Worker           has an attribute value for key."""
76*61046927SAndroid Build Coastguard Worker
77*61046927SAndroid Build Coastguard Worker        if required and key not in self.elem.keys():
78*61046927SAndroid Build Coastguard Worker            return False
79*61046927SAndroid Build Coastguard Worker        return self.elem.get(key) == info.elem.get(key)
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker    def compareElem(self, info, infoName):
82*61046927SAndroid Build Coastguard Worker        """Return True if self.elem and info.elem have the same definition.
83*61046927SAndroid Build Coastguard Worker        info - the other object
84*61046927SAndroid Build Coastguard Worker        infoName - 'type' / 'group' / 'enum' / 'command' / 'feature' /
85*61046927SAndroid Build Coastguard Worker                   'extension'"""
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker        if infoName == 'enum':
88*61046927SAndroid Build Coastguard Worker            if self.compareKeys(info, 'extends'):
89*61046927SAndroid Build Coastguard Worker                # Either both extend the same type, or no type
90*61046927SAndroid Build Coastguard Worker                if (self.compareKeys(info, 'value', required = True) or
91*61046927SAndroid Build Coastguard Worker                    self.compareKeys(info, 'bitpos', required = True)):
92*61046927SAndroid Build Coastguard Worker                    # If both specify the same value or bit position,
93*61046927SAndroid Build Coastguard Worker                    # they are equal
94*61046927SAndroid Build Coastguard Worker                    return True
95*61046927SAndroid Build Coastguard Worker                elif (self.compareKeys(info, 'extnumber') and
96*61046927SAndroid Build Coastguard Worker                      self.compareKeys(info, 'offset') and
97*61046927SAndroid Build Coastguard Worker                      self.compareKeys(info, 'dir')):
98*61046927SAndroid Build Coastguard Worker                    # If both specify the same relative offset, they are equal
99*61046927SAndroid Build Coastguard Worker                    return True
100*61046927SAndroid Build Coastguard Worker                elif (self.compareKeys(info, 'alias')):
101*61046927SAndroid Build Coastguard Worker                    # If both are aliases of the same value
102*61046927SAndroid Build Coastguard Worker                    return True
103*61046927SAndroid Build Coastguard Worker                else:
104*61046927SAndroid Build Coastguard Worker                    return False
105*61046927SAndroid Build Coastguard Worker            else:
106*61046927SAndroid Build Coastguard Worker                # The same enum cannot extend two different types
107*61046927SAndroid Build Coastguard Worker                return False
108*61046927SAndroid Build Coastguard Worker        else:
109*61046927SAndroid Build Coastguard Worker            # Non-<enum>s should never be redefined
110*61046927SAndroid Build Coastguard Worker            return False
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker
113*61046927SAndroid Build Coastguard Workerclass TypeInfo(BaseInfo):
114*61046927SAndroid Build Coastguard Worker    """Registry information about a type. No additional state
115*61046927SAndroid Build Coastguard Worker      beyond BaseInfo is required."""
116*61046927SAndroid Build Coastguard Worker
117*61046927SAndroid Build Coastguard Worker    def __init__(self, elem):
118*61046927SAndroid Build Coastguard Worker        BaseInfo.__init__(self, elem)
119*61046927SAndroid Build Coastguard Worker        self.additionalValidity = []
120*61046927SAndroid Build Coastguard Worker        self.removedValidity = []
121*61046927SAndroid Build Coastguard Worker
122*61046927SAndroid Build Coastguard Worker    def getMembers(self):
123*61046927SAndroid Build Coastguard Worker        """Get a collection of all member elements for this type, if any."""
124*61046927SAndroid Build Coastguard Worker        return self.elem.findall('member')
125*61046927SAndroid Build Coastguard Worker
126*61046927SAndroid Build Coastguard Worker    def resetState(self):
127*61046927SAndroid Build Coastguard Worker        BaseInfo.resetState(self)
128*61046927SAndroid Build Coastguard Worker        self.additionalValidity = []
129*61046927SAndroid Build Coastguard Worker        self.removedValidity = []
130*61046927SAndroid Build Coastguard Worker
131*61046927SAndroid Build Coastguard Worker
132*61046927SAndroid Build Coastguard Workerclass GroupInfo(BaseInfo):
133*61046927SAndroid Build Coastguard Worker    """Registry information about a group of related enums
134*61046927SAndroid Build Coastguard Worker    in an <enums> block, generally corresponding to a C "enum" type."""
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker    def __init__(self, elem):
137*61046927SAndroid Build Coastguard Worker        BaseInfo.__init__(self, elem)
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Workerclass EnumInfo(BaseInfo):
141*61046927SAndroid Build Coastguard Worker    """Registry information about an enum"""
142*61046927SAndroid Build Coastguard Worker
143*61046927SAndroid Build Coastguard Worker    def __init__(self, elem):
144*61046927SAndroid Build Coastguard Worker        BaseInfo.__init__(self, elem)
145*61046927SAndroid Build Coastguard Worker        self.type = elem.get('type')
146*61046927SAndroid Build Coastguard Worker        """numeric type of the value of the <enum> tag
147*61046927SAndroid Build Coastguard Worker        ( '' for GLint, 'u' for GLuint, 'ull' for GLuint64 )"""
148*61046927SAndroid Build Coastguard Worker        if self.type is None:
149*61046927SAndroid Build Coastguard Worker            self.type = ''
150*61046927SAndroid Build Coastguard Worker
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Workerclass CmdInfo(BaseInfo):
153*61046927SAndroid Build Coastguard Worker    """Registry information about a command"""
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker    def __init__(self, elem):
156*61046927SAndroid Build Coastguard Worker        BaseInfo.__init__(self, elem)
157*61046927SAndroid Build Coastguard Worker        self.additionalValidity = []
158*61046927SAndroid Build Coastguard Worker        self.removedValidity = []
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker    def getParams(self):
161*61046927SAndroid Build Coastguard Worker        """Get a collection of all param elements for this command, if any."""
162*61046927SAndroid Build Coastguard Worker        return self.elem.findall('param')
163*61046927SAndroid Build Coastguard Worker
164*61046927SAndroid Build Coastguard Worker    def resetState(self):
165*61046927SAndroid Build Coastguard Worker        BaseInfo.resetState(self)
166*61046927SAndroid Build Coastguard Worker        self.additionalValidity = []
167*61046927SAndroid Build Coastguard Worker        self.removedValidity = []
168*61046927SAndroid Build Coastguard Worker
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Workerclass FeatureInfo(BaseInfo):
171*61046927SAndroid Build Coastguard Worker    """Registry information about an API <feature>
172*61046927SAndroid Build Coastguard Worker    or <extension>."""
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker    def __init__(self, elem):
175*61046927SAndroid Build Coastguard Worker        BaseInfo.__init__(self, elem)
176*61046927SAndroid Build Coastguard Worker        self.name = elem.get('name')
177*61046927SAndroid Build Coastguard Worker        "feature name string (e.g. 'VK_KHR_surface')"
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker        self.emit = False
180*61046927SAndroid Build Coastguard Worker        "has this feature been defined already?"
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker        self.sortorder = int(elem.get('sortorder', 0))
183*61046927SAndroid Build Coastguard Worker        """explicit numeric sort key within feature and extension groups.
184*61046927SAndroid Build Coastguard Worker        Defaults to 0."""
185*61046927SAndroid Build Coastguard Worker
186*61046927SAndroid Build Coastguard Worker        # Determine element category (vendor). Only works
187*61046927SAndroid Build Coastguard Worker        # for <extension> elements.
188*61046927SAndroid Build Coastguard Worker        if elem.tag == 'feature':
189*61046927SAndroid Build Coastguard Worker            # Element category (vendor) is meaningless for <feature>
190*61046927SAndroid Build Coastguard Worker            self.category = 'VERSION'
191*61046927SAndroid Build Coastguard Worker            """category, e.g. VERSION or khr/vendor tag"""
192*61046927SAndroid Build Coastguard Worker
193*61046927SAndroid Build Coastguard Worker            self.version = elem.get('name')
194*61046927SAndroid Build Coastguard Worker            """feature name string"""
195*61046927SAndroid Build Coastguard Worker
196*61046927SAndroid Build Coastguard Worker            self.versionNumber = elem.get('number')
197*61046927SAndroid Build Coastguard Worker            """versionNumber - API version number, taken from the 'number'
198*61046927SAndroid Build Coastguard Worker               attribute of <feature>. Extensions do not have API version
199*61046927SAndroid Build Coastguard Worker               numbers and are assigned number 0."""
200*61046927SAndroid Build Coastguard Worker
201*61046927SAndroid Build Coastguard Worker            self.number = 0
202*61046927SAndroid Build Coastguard Worker            self.supported = None
203*61046927SAndroid Build Coastguard Worker        else:
204*61046927SAndroid Build Coastguard Worker            # Extract vendor portion of <APIprefix>_<vendor>_<name>
205*61046927SAndroid Build Coastguard Worker            self.category = self.name.split('_', 2)[1]
206*61046927SAndroid Build Coastguard Worker            self.version = "0"
207*61046927SAndroid Build Coastguard Worker            self.versionNumber = "0"
208*61046927SAndroid Build Coastguard Worker
209*61046927SAndroid Build Coastguard Worker            self.number = int(elem.get('number','0'))
210*61046927SAndroid Build Coastguard Worker            """extension number, used for ordering and for assigning
211*61046927SAndroid Build Coastguard Worker            enumerant offsets. <feature> features do not have extension
212*61046927SAndroid Build Coastguard Worker            numbers and are assigned number 0, as are extensions without
213*61046927SAndroid Build Coastguard Worker            numbers, so sorting works."""
214*61046927SAndroid Build Coastguard Worker
215*61046927SAndroid Build Coastguard Worker            self.supported = elem.get('supported', 'disabled')
216*61046927SAndroid Build Coastguard Worker
217*61046927SAndroid Build Coastguard Workerclass Registry:
218*61046927SAndroid Build Coastguard Worker    """Object representing an API registry, loaded from an XML file."""
219*61046927SAndroid Build Coastguard Worker
220*61046927SAndroid Build Coastguard Worker    def __init__(self, gen=None, genOpts=None):
221*61046927SAndroid Build Coastguard Worker        if gen is None:
222*61046927SAndroid Build Coastguard Worker            # If not specified, give a default object so messaging will work
223*61046927SAndroid Build Coastguard Worker            self.gen = OutputGenerator()
224*61046927SAndroid Build Coastguard Worker        else:
225*61046927SAndroid Build Coastguard Worker            self.gen = gen
226*61046927SAndroid Build Coastguard Worker        "Output generator used to write headers / messages"
227*61046927SAndroid Build Coastguard Worker
228*61046927SAndroid Build Coastguard Worker        if genOpts is None:
229*61046927SAndroid Build Coastguard Worker            # If no generator is provided, we may still need the XML API name
230*61046927SAndroid Build Coastguard Worker            # (for example, in genRef.py).
231*61046927SAndroid Build Coastguard Worker            self.genOpts = GeneratorOptions(apiname = 'vulkan')
232*61046927SAndroid Build Coastguard Worker        else:
233*61046927SAndroid Build Coastguard Worker            self.genOpts = genOpts
234*61046927SAndroid Build Coastguard Worker        "Options controlling features to write and how to format them"
235*61046927SAndroid Build Coastguard Worker
236*61046927SAndroid Build Coastguard Worker        self.gen.registry = self
237*61046927SAndroid Build Coastguard Worker        self.gen.genOpts = self.genOpts
238*61046927SAndroid Build Coastguard Worker        self.gen.genOpts.registry = self
239*61046927SAndroid Build Coastguard Worker
240*61046927SAndroid Build Coastguard Worker        self.tree = None
241*61046927SAndroid Build Coastguard Worker        "ElementTree containing the root `<registry>`"
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker        self.typedict = {}
244*61046927SAndroid Build Coastguard Worker        "dictionary of TypeInfo objects keyed by type name"
245*61046927SAndroid Build Coastguard Worker
246*61046927SAndroid Build Coastguard Worker        self.groupdict = {}
247*61046927SAndroid Build Coastguard Worker        "dictionary of GroupInfo objects keyed by group name"
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker        self.enumdict = {}
250*61046927SAndroid Build Coastguard Worker        "dictionary of EnumInfo objects keyed by enum name"
251*61046927SAndroid Build Coastguard Worker
252*61046927SAndroid Build Coastguard Worker        self.cmddict = {}
253*61046927SAndroid Build Coastguard Worker        "dictionary of CmdInfo objects keyed by command name"
254*61046927SAndroid Build Coastguard Worker
255*61046927SAndroid Build Coastguard Worker        self.apidict = {}
256*61046927SAndroid Build Coastguard Worker        "dictionary of FeatureInfo objects for `<feature>` elements keyed by API name"
257*61046927SAndroid Build Coastguard Worker
258*61046927SAndroid Build Coastguard Worker        self.extensions = []
259*61046927SAndroid Build Coastguard Worker        "list of `<extension>` Elements"
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker        self.extdict = {}
262*61046927SAndroid Build Coastguard Worker        "dictionary of FeatureInfo objects for `<extension>` elements keyed by extension name"
263*61046927SAndroid Build Coastguard Worker
264*61046927SAndroid Build Coastguard Worker        self.emitFeatures = False
265*61046927SAndroid Build Coastguard Worker        """True to actually emit features for a version / extension,
266*61046927SAndroid Build Coastguard Worker        or False to just treat them as emitted"""
267*61046927SAndroid Build Coastguard Worker
268*61046927SAndroid Build Coastguard Worker        self.filename     = None
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker    def loadElementTree(self, tree):
271*61046927SAndroid Build Coastguard Worker        """Load ElementTree into a Registry object and parse it."""
272*61046927SAndroid Build Coastguard Worker        self.tree = tree
273*61046927SAndroid Build Coastguard Worker        self.parseTree()
274*61046927SAndroid Build Coastguard Worker
275*61046927SAndroid Build Coastguard Worker    def loadFile(self, file):
276*61046927SAndroid Build Coastguard Worker        """Load an API registry XML file into a Registry object and parse it"""
277*61046927SAndroid Build Coastguard Worker        self.filename = file
278*61046927SAndroid Build Coastguard Worker        self.tree = etree.parse(file)
279*61046927SAndroid Build Coastguard Worker        self.parseTree()
280*61046927SAndroid Build Coastguard Worker
281*61046927SAndroid Build Coastguard Worker    def setGenerator(self, gen):
282*61046927SAndroid Build Coastguard Worker        """Specify output generator object.
283*61046927SAndroid Build Coastguard Worker
284*61046927SAndroid Build Coastguard Worker        `None` restores the default generator."""
285*61046927SAndroid Build Coastguard Worker        self.gen = gen
286*61046927SAndroid Build Coastguard Worker        self.gen.setRegistry(self)
287*61046927SAndroid Build Coastguard Worker
288*61046927SAndroid Build Coastguard Worker    def addElementInfo(self, elem, info, infoName, dictionary):
289*61046927SAndroid Build Coastguard Worker        """Add information about an element to the corresponding dictionary.
290*61046927SAndroid Build Coastguard Worker
291*61046927SAndroid Build Coastguard Worker        Intended for internal use only.
292*61046927SAndroid Build Coastguard Worker
293*61046927SAndroid Build Coastguard Worker        - elem - `<type>`/`<enums>`/`<enum>`/`<command>`/`<feature>`/`<extension>`/`<spirvextension>`/`<spirvcapability>`/`<format>`/`<syncstage>`/`<syncaccess>`/`<syncpipeline>` Element
294*61046927SAndroid Build Coastguard Worker        - info - corresponding {Type|Group|Enum|Cmd|Feature|Spirv|Format|SyncStage|SyncAccess|SyncPipeline}Info object
295*61046927SAndroid Build Coastguard Worker        - infoName - 'type' / 'group' / 'enum' / 'command' / 'feature' / 'extension' / 'spirvextension' / 'spirvcapability' / 'format' / 'syncstage' / 'syncaccess' / 'syncpipeline'
296*61046927SAndroid Build Coastguard Worker        - dictionary - self.{type|group|enum|cmd|api|ext|format|spirvext|spirvcap|sync}dict
297*61046927SAndroid Build Coastguard Worker
298*61046927SAndroid Build Coastguard Worker        The dictionary key is the element 'name' attribute."""
299*61046927SAndroid Build Coastguard Worker
300*61046927SAndroid Build Coastguard Worker        key = elem.get('name')
301*61046927SAndroid Build Coastguard Worker        if key in dictionary:
302*61046927SAndroid Build Coastguard Worker            if not dictionary[key].compareElem(info, infoName):
303*61046927SAndroid Build Coastguard Worker                return
304*61046927SAndroid Build Coastguard Worker        else:
305*61046927SAndroid Build Coastguard Worker            dictionary[key] = info
306*61046927SAndroid Build Coastguard Worker
307*61046927SAndroid Build Coastguard Worker    def lookupElementInfo(self, fname, dictionary):
308*61046927SAndroid Build Coastguard Worker        """Find a {Type|Enum|Cmd}Info object by name.
309*61046927SAndroid Build Coastguard Worker
310*61046927SAndroid Build Coastguard Worker        Intended for internal use only.
311*61046927SAndroid Build Coastguard Worker
312*61046927SAndroid Build Coastguard Worker        If an object qualified by API name exists, use that.
313*61046927SAndroid Build Coastguard Worker
314*61046927SAndroid Build Coastguard Worker        - fname - name of type / enum / command
315*61046927SAndroid Build Coastguard Worker        - dictionary - self.{type|enum|cmd}dict"""
316*61046927SAndroid Build Coastguard Worker        key = (fname, 'vulkan')
317*61046927SAndroid Build Coastguard Worker        if key in dictionary:
318*61046927SAndroid Build Coastguard Worker            return dictionary[key]
319*61046927SAndroid Build Coastguard Worker        if fname in dictionary:
320*61046927SAndroid Build Coastguard Worker            return dictionary[fname]
321*61046927SAndroid Build Coastguard Worker
322*61046927SAndroid Build Coastguard Worker        return None
323*61046927SAndroid Build Coastguard Worker
324*61046927SAndroid Build Coastguard Worker    def parseTree(self):
325*61046927SAndroid Build Coastguard Worker        """Parse the registry Element, once created"""
326*61046927SAndroid Build Coastguard Worker        # This must be the Element for the root <registry>
327*61046927SAndroid Build Coastguard Worker        if self.tree is None:
328*61046927SAndroid Build Coastguard Worker            raise RuntimeError("Tree not initialized!")
329*61046927SAndroid Build Coastguard Worker        self.reg = self.tree.getroot()
330*61046927SAndroid Build Coastguard Worker
331*61046927SAndroid Build Coastguard Worker        # There is usually one <types> block; more are OK
332*61046927SAndroid Build Coastguard Worker        # Required <type> attributes: 'name' or nested <name> tag contents
333*61046927SAndroid Build Coastguard Worker        self.typedict = {}
334*61046927SAndroid Build Coastguard Worker        for type_elem in self.reg.findall('types/type'):
335*61046927SAndroid Build Coastguard Worker            # If the <type> does not already have a 'name' attribute, set
336*61046927SAndroid Build Coastguard Worker            # it from contents of its <name> tag.
337*61046927SAndroid Build Coastguard Worker            if type_elem.get('name') is None:
338*61046927SAndroid Build Coastguard Worker                name_elem = type_elem.find('name')
339*61046927SAndroid Build Coastguard Worker                if name_elem is None or not name_elem.text:
340*61046927SAndroid Build Coastguard Worker                    raise RuntimeError("Type without a name!")
341*61046927SAndroid Build Coastguard Worker                type_elem.set('name', name_elem.text)
342*61046927SAndroid Build Coastguard Worker            self.addElementInfo(type_elem, TypeInfo(type_elem), 'type', self.typedict)
343*61046927SAndroid Build Coastguard Worker
344*61046927SAndroid Build Coastguard Worker        # Create dictionary of registry enum groups from <enums> tags.
345*61046927SAndroid Build Coastguard Worker        #
346*61046927SAndroid Build Coastguard Worker        # Required <enums> attributes: 'name'. If no name is given, one is
347*61046927SAndroid Build Coastguard Worker        # generated, but that group cannot be identified and turned into an
348*61046927SAndroid Build Coastguard Worker        # enum type definition - it is just a container for <enum> tags.
349*61046927SAndroid Build Coastguard Worker        self.groupdict = {}
350*61046927SAndroid Build Coastguard Worker        for group in self.reg.findall('enums'):
351*61046927SAndroid Build Coastguard Worker            self.addElementInfo(group, GroupInfo(group), 'group', self.groupdict)
352*61046927SAndroid Build Coastguard Worker
353*61046927SAndroid Build Coastguard Worker        # Create dictionary of registry enums from <enum> tags
354*61046927SAndroid Build Coastguard Worker        #
355*61046927SAndroid Build Coastguard Worker        # <enums> tags usually define different namespaces for the values
356*61046927SAndroid Build Coastguard Worker        #   defined in those tags, but the actual names all share the
357*61046927SAndroid Build Coastguard Worker        #   same dictionary.
358*61046927SAndroid Build Coastguard Worker        # Required <enum> attributes: 'name', 'value'
359*61046927SAndroid Build Coastguard Worker        # For containing <enums> which have type="enum" or type="bitmask",
360*61046927SAndroid Build Coastguard Worker        # tag all contained <enum>s are required. This is a stopgap until
361*61046927SAndroid Build Coastguard Worker        # a better scheme for tagging core and extension enums is created.
362*61046927SAndroid Build Coastguard Worker        self.enumdict = {}
363*61046927SAndroid Build Coastguard Worker        for enums in self.reg.findall('enums'):
364*61046927SAndroid Build Coastguard Worker            required = (enums.get('type') is not None)
365*61046927SAndroid Build Coastguard Worker            for enum in enums.findall('enum'):
366*61046927SAndroid Build Coastguard Worker                enumInfo = EnumInfo(enum)
367*61046927SAndroid Build Coastguard Worker                enumInfo.required = required
368*61046927SAndroid Build Coastguard Worker                self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
369*61046927SAndroid Build Coastguard Worker
370*61046927SAndroid Build Coastguard Worker        # Create dictionary of registry commands from <command> tags
371*61046927SAndroid Build Coastguard Worker        # and add 'name' attribute to each <command> tag (where missing)
372*61046927SAndroid Build Coastguard Worker        # based on its <proto><name> element.
373*61046927SAndroid Build Coastguard Worker        #
374*61046927SAndroid Build Coastguard Worker        # There is usually only one <commands> block; more are OK.
375*61046927SAndroid Build Coastguard Worker        # Required <command> attributes: 'name' or <proto><name> tag contents
376*61046927SAndroid Build Coastguard Worker        self.cmddict = {}
377*61046927SAndroid Build Coastguard Worker        # List of commands which alias others. Contains
378*61046927SAndroid Build Coastguard Worker        #   [ aliasName, element ]
379*61046927SAndroid Build Coastguard Worker        # for each alias
380*61046927SAndroid Build Coastguard Worker        cmdAlias = []
381*61046927SAndroid Build Coastguard Worker        for cmd in self.reg.findall('commands/command'):
382*61046927SAndroid Build Coastguard Worker            # If the <command> does not already have a 'name' attribute, set
383*61046927SAndroid Build Coastguard Worker            # it from contents of its <proto><name> tag.
384*61046927SAndroid Build Coastguard Worker            name = cmd.get('name')
385*61046927SAndroid Build Coastguard Worker            if name is None:
386*61046927SAndroid Build Coastguard Worker                name_elem = cmd.find('proto/name')
387*61046927SAndroid Build Coastguard Worker                if name_elem is None or not name_elem.text:
388*61046927SAndroid Build Coastguard Worker                    raise RuntimeError("Command without a name!")
389*61046927SAndroid Build Coastguard Worker                name = cmd.set('name', name_elem.text)
390*61046927SAndroid Build Coastguard Worker            ci = CmdInfo(cmd)
391*61046927SAndroid Build Coastguard Worker            self.addElementInfo(cmd, ci, 'command', self.cmddict)
392*61046927SAndroid Build Coastguard Worker            alias = cmd.get('alias')
393*61046927SAndroid Build Coastguard Worker            if alias:
394*61046927SAndroid Build Coastguard Worker                cmdAlias.append([name, alias, cmd])
395*61046927SAndroid Build Coastguard Worker
396*61046927SAndroid Build Coastguard Worker        # Now loop over aliases, injecting a copy of the aliased command's
397*61046927SAndroid Build Coastguard Worker        # Element with the aliased prototype name replaced with the command
398*61046927SAndroid Build Coastguard Worker        # name - if it exists.
399*61046927SAndroid Build Coastguard Worker        for (name, alias, cmd) in cmdAlias:
400*61046927SAndroid Build Coastguard Worker            if alias in self.cmddict:
401*61046927SAndroid Build Coastguard Worker                aliasInfo = self.cmddict[alias]
402*61046927SAndroid Build Coastguard Worker                cmdElem = copy.deepcopy(aliasInfo.elem)
403*61046927SAndroid Build Coastguard Worker                cmdElem.find('proto/name').text = name
404*61046927SAndroid Build Coastguard Worker                cmdElem.set('name', name)
405*61046927SAndroid Build Coastguard Worker                cmdElem.set('alias', alias)
406*61046927SAndroid Build Coastguard Worker                ci = CmdInfo(cmdElem)
407*61046927SAndroid Build Coastguard Worker                # Replace the dictionary entry for the CmdInfo element
408*61046927SAndroid Build Coastguard Worker                self.cmddict[name] = ci
409*61046927SAndroid Build Coastguard Worker
410*61046927SAndroid Build Coastguard Worker        # Create dictionaries of API and extension interfaces
411*61046927SAndroid Build Coastguard Worker        #   from toplevel <api> and <extension> tags.
412*61046927SAndroid Build Coastguard Worker        self.apidict = {}
413*61046927SAndroid Build Coastguard Worker        for feature in self.reg.findall('feature'):
414*61046927SAndroid Build Coastguard Worker            featureInfo = FeatureInfo(feature)
415*61046927SAndroid Build Coastguard Worker            self.addElementInfo(feature, featureInfo, 'feature', self.apidict)
416*61046927SAndroid Build Coastguard Worker
417*61046927SAndroid Build Coastguard Worker            # Add additional enums defined only in <feature> tags
418*61046927SAndroid Build Coastguard Worker            # to the corresponding enumerated type.
419*61046927SAndroid Build Coastguard Worker            # When seen here, the <enum> element, processed to contain the
420*61046927SAndroid Build Coastguard Worker            # numeric enum value, is added to the corresponding <enums>
421*61046927SAndroid Build Coastguard Worker            # element, as well as adding to the enum dictionary. It is no
422*61046927SAndroid Build Coastguard Worker            # longer removed from the <require> element it is introduced in.
423*61046927SAndroid Build Coastguard Worker            # Instead, generateRequiredInterface ignores <enum> elements
424*61046927SAndroid Build Coastguard Worker            # that extend enumerated types.
425*61046927SAndroid Build Coastguard Worker            #
426*61046927SAndroid Build Coastguard Worker            # For <enum> tags which are actually just constants, if there is
427*61046927SAndroid Build Coastguard Worker            # no 'extends' tag but there is a 'value' or 'bitpos' tag, just
428*61046927SAndroid Build Coastguard Worker            # add an EnumInfo record to the dictionary. That works because
429*61046927SAndroid Build Coastguard Worker            # output generation of constants is purely dependency-based, and
430*61046927SAndroid Build Coastguard Worker            # does not need to iterate through the XML tags.
431*61046927SAndroid Build Coastguard Worker            for elem in feature.findall('require'):
432*61046927SAndroid Build Coastguard Worker                for enum in elem.findall('enum'):
433*61046927SAndroid Build Coastguard Worker                    addEnumInfo = False
434*61046927SAndroid Build Coastguard Worker                    groupName = enum.get('extends')
435*61046927SAndroid Build Coastguard Worker                    if groupName is not None:
436*61046927SAndroid Build Coastguard Worker                        # Add version number attribute to the <enum> element
437*61046927SAndroid Build Coastguard Worker                        enum.set('version', featureInfo.version)
438*61046927SAndroid Build Coastguard Worker                        # Look up the GroupInfo with matching groupName
439*61046927SAndroid Build Coastguard Worker                        if groupName in self.groupdict:
440*61046927SAndroid Build Coastguard Worker                            gi = self.groupdict[groupName]
441*61046927SAndroid Build Coastguard Worker                            gi.elem.append(copy.deepcopy(enum))
442*61046927SAndroid Build Coastguard Worker                        addEnumInfo = True
443*61046927SAndroid Build Coastguard Worker                    elif enum.get('value') or enum.get('bitpos') or enum.get('alias'):
444*61046927SAndroid Build Coastguard Worker                        addEnumInfo = True
445*61046927SAndroid Build Coastguard Worker                    if addEnumInfo:
446*61046927SAndroid Build Coastguard Worker                        enumInfo = EnumInfo(enum)
447*61046927SAndroid Build Coastguard Worker                        self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
448*61046927SAndroid Build Coastguard Worker
449*61046927SAndroid Build Coastguard Worker        self.extensions = self.reg.findall('extensions/extension')
450*61046927SAndroid Build Coastguard Worker        self.extdict = {}
451*61046927SAndroid Build Coastguard Worker        for feature in self.extensions:
452*61046927SAndroid Build Coastguard Worker            featureInfo = FeatureInfo(feature)
453*61046927SAndroid Build Coastguard Worker            self.addElementInfo(feature, featureInfo, 'extension', self.extdict)
454*61046927SAndroid Build Coastguard Worker
455*61046927SAndroid Build Coastguard Worker            # Add additional enums defined only in <extension> tags
456*61046927SAndroid Build Coastguard Worker            # to the corresponding core type.
457*61046927SAndroid Build Coastguard Worker            # Algorithm matches that of enums in a "feature" tag as above.
458*61046927SAndroid Build Coastguard Worker            #
459*61046927SAndroid Build Coastguard Worker            # This code also adds a 'extnumber' attribute containing the
460*61046927SAndroid Build Coastguard Worker            # extension number, used for enumerant value calculation.
461*61046927SAndroid Build Coastguard Worker            for elem in feature.findall('require'):
462*61046927SAndroid Build Coastguard Worker                for enum in elem.findall('enum'):
463*61046927SAndroid Build Coastguard Worker                    addEnumInfo = False
464*61046927SAndroid Build Coastguard Worker                    groupName = enum.get('extends')
465*61046927SAndroid Build Coastguard Worker                    if groupName is not None:
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker                        # Add <extension> block's extension number attribute to
468*61046927SAndroid Build Coastguard Worker                        # the <enum> element unless specified explicitly, such
469*61046927SAndroid Build Coastguard Worker                        # as when redefining an enum in another extension.
470*61046927SAndroid Build Coastguard Worker                        extnumber = enum.get('extnumber')
471*61046927SAndroid Build Coastguard Worker                        if not extnumber:
472*61046927SAndroid Build Coastguard Worker                            enum.set('extnumber', str(featureInfo.number))
473*61046927SAndroid Build Coastguard Worker
474*61046927SAndroid Build Coastguard Worker                        enum.set('extname', featureInfo.name)
475*61046927SAndroid Build Coastguard Worker                        enum.set('supported', noneStr(featureInfo.supported))
476*61046927SAndroid Build Coastguard Worker                        # Look up the GroupInfo with matching groupName
477*61046927SAndroid Build Coastguard Worker                        if groupName in self.groupdict:
478*61046927SAndroid Build Coastguard Worker                            gi = self.groupdict[groupName]
479*61046927SAndroid Build Coastguard Worker                            gi.elem.append(copy.deepcopy(enum))
480*61046927SAndroid Build Coastguard Worker
481*61046927SAndroid Build Coastguard Worker                        addEnumInfo = True
482*61046927SAndroid Build Coastguard Worker                    elif enum.get('value') or enum.get('bitpos') or enum.get('alias'):
483*61046927SAndroid Build Coastguard Worker                        addEnumInfo = True
484*61046927SAndroid Build Coastguard Worker                    if addEnumInfo:
485*61046927SAndroid Build Coastguard Worker                        enumInfo = EnumInfo(enum)
486*61046927SAndroid Build Coastguard Worker                        self.addElementInfo(enum, enumInfo, 'enum', self.enumdict)
487*61046927SAndroid Build Coastguard Worker
488*61046927SAndroid Build Coastguard Worker    def markTypeRequired(self, typename, required):
489*61046927SAndroid Build Coastguard Worker        """Require (along with its dependencies) or remove (but not its dependencies) a type.
490*61046927SAndroid Build Coastguard Worker
491*61046927SAndroid Build Coastguard Worker        - typename - name of type
492*61046927SAndroid Build Coastguard Worker        - required - boolean (to tag features as required or not)
493*61046927SAndroid Build Coastguard Worker        """
494*61046927SAndroid Build Coastguard Worker        # Get TypeInfo object for <type> tag corresponding to typename
495*61046927SAndroid Build Coastguard Worker        typeinfo = self.lookupElementInfo(typename, self.typedict)
496*61046927SAndroid Build Coastguard Worker        if typeinfo is not None:
497*61046927SAndroid Build Coastguard Worker            if required:
498*61046927SAndroid Build Coastguard Worker                # Tag type dependencies in 'alias' and 'required' attributes as
499*61046927SAndroid Build Coastguard Worker                # required. This does not un-tag dependencies in a <remove>
500*61046927SAndroid Build Coastguard Worker                # tag. See comments in markRequired() below for the reason.
501*61046927SAndroid Build Coastguard Worker                for attrib_name in ['requires', 'alias']:
502*61046927SAndroid Build Coastguard Worker                    depname = typeinfo.elem.get(attrib_name)
503*61046927SAndroid Build Coastguard Worker                    if depname:
504*61046927SAndroid Build Coastguard Worker                        # Do not recurse on self-referential structures.
505*61046927SAndroid Build Coastguard Worker                        if typename != depname:
506*61046927SAndroid Build Coastguard Worker                            self.markTypeRequired(depname, required)
507*61046927SAndroid Build Coastguard Worker                # Tag types used in defining this type (e.g. in nested
508*61046927SAndroid Build Coastguard Worker                # <type> tags)
509*61046927SAndroid Build Coastguard Worker                # Look for <type> in entire <command> tree,
510*61046927SAndroid Build Coastguard Worker                # not just immediate children
511*61046927SAndroid Build Coastguard Worker                for subtype in typeinfo.elem.findall('.//type'):
512*61046927SAndroid Build Coastguard Worker                    if typename != subtype.text:
513*61046927SAndroid Build Coastguard Worker                        self.markTypeRequired(subtype.text, required)
514*61046927SAndroid Build Coastguard Worker                # Tag enums used in defining this type, for example in
515*61046927SAndroid Build Coastguard Worker                #   <member><name>member</name>[<enum>MEMBER_SIZE</enum>]</member>
516*61046927SAndroid Build Coastguard Worker                for subenum in typeinfo.elem.findall('.//enum'):
517*61046927SAndroid Build Coastguard Worker                    self.markEnumRequired(subenum.text, required)
518*61046927SAndroid Build Coastguard Worker                # Tag type dependency in 'bitvalues' attributes as
519*61046927SAndroid Build Coastguard Worker                # required. This ensures that the bit values for a flag
520*61046927SAndroid Build Coastguard Worker                # are emitted
521*61046927SAndroid Build Coastguard Worker                depType = typeinfo.elem.get('bitvalues')
522*61046927SAndroid Build Coastguard Worker                if depType:
523*61046927SAndroid Build Coastguard Worker                    self.markTypeRequired(depType, required)
524*61046927SAndroid Build Coastguard Worker                    group = self.lookupElementInfo(depType, self.groupdict)
525*61046927SAndroid Build Coastguard Worker                    if group is not None:
526*61046927SAndroid Build Coastguard Worker                        group.flagType = typeinfo
527*61046927SAndroid Build Coastguard Worker
528*61046927SAndroid Build Coastguard Worker            typeinfo.required = required
529*61046927SAndroid Build Coastguard Worker
530*61046927SAndroid Build Coastguard Worker    def markEnumRequired(self, enumname, required):
531*61046927SAndroid Build Coastguard Worker        """Mark an enum as required or not.
532*61046927SAndroid Build Coastguard Worker
533*61046927SAndroid Build Coastguard Worker        - enumname - name of enum
534*61046927SAndroid Build Coastguard Worker        - required - boolean (to tag features as required or not)"""
535*61046927SAndroid Build Coastguard Worker
536*61046927SAndroid Build Coastguard Worker        enum = self.lookupElementInfo(enumname, self.enumdict)
537*61046927SAndroid Build Coastguard Worker        if enum is not None:
538*61046927SAndroid Build Coastguard Worker            # If the enum is part of a group, and is being removed, then
539*61046927SAndroid Build Coastguard Worker            # look it up in that <enums> tag and remove the Element there,
540*61046927SAndroid Build Coastguard Worker            # so that it is not visible to generators (which traverse the
541*61046927SAndroid Build Coastguard Worker            # <enums> tag elements rather than using the dictionaries).
542*61046927SAndroid Build Coastguard Worker            if not required:
543*61046927SAndroid Build Coastguard Worker                groupName = enum.elem.get('extends')
544*61046927SAndroid Build Coastguard Worker                if groupName is not None:
545*61046927SAndroid Build Coastguard Worker
546*61046927SAndroid Build Coastguard Worker                    # Look up the Info with matching groupName
547*61046927SAndroid Build Coastguard Worker                    if groupName in self.groupdict:
548*61046927SAndroid Build Coastguard Worker                        gi = self.groupdict[groupName]
549*61046927SAndroid Build Coastguard Worker                        gienum = gi.elem.find("enum[@name='" + enumname + "']")
550*61046927SAndroid Build Coastguard Worker                        if gienum is not None:
551*61046927SAndroid Build Coastguard Worker                            # Remove copy of this enum from the group
552*61046927SAndroid Build Coastguard Worker                            gi.elem.remove(gienum)
553*61046927SAndroid Build Coastguard Worker                else:
554*61046927SAndroid Build Coastguard Worker                    # This enum is not an extending enum.
555*61046927SAndroid Build Coastguard Worker                    # The XML tree must be searched for all <enums> that
556*61046927SAndroid Build Coastguard Worker                    # might have it, so we know the parent to delete from.
557*61046927SAndroid Build Coastguard Worker
558*61046927SAndroid Build Coastguard Worker                    enumName = enum.elem.get('name')
559*61046927SAndroid Build Coastguard Worker                    count = 0
560*61046927SAndroid Build Coastguard Worker                    for enums in self.reg.findall('enums'):
561*61046927SAndroid Build Coastguard Worker                        for thisEnum in enums.findall('enum'):
562*61046927SAndroid Build Coastguard Worker                            if thisEnum.get('name') == enumName:
563*61046927SAndroid Build Coastguard Worker                                # Actually remove it
564*61046927SAndroid Build Coastguard Worker                                count = count + 1
565*61046927SAndroid Build Coastguard Worker                                enums.remove(thisEnum)
566*61046927SAndroid Build Coastguard Worker
567*61046927SAndroid Build Coastguard Worker            enum.required = required
568*61046927SAndroid Build Coastguard Worker            # Tag enum dependencies in 'alias' attribute as required
569*61046927SAndroid Build Coastguard Worker            depname = enum.elem.get('alias')
570*61046927SAndroid Build Coastguard Worker            if depname:
571*61046927SAndroid Build Coastguard Worker                self.markEnumRequired(depname, required)
572*61046927SAndroid Build Coastguard Worker
573*61046927SAndroid Build Coastguard Worker    def markCmdRequired(self, cmdname, required):
574*61046927SAndroid Build Coastguard Worker        """Mark a command as required or not.
575*61046927SAndroid Build Coastguard Worker
576*61046927SAndroid Build Coastguard Worker        - cmdname - name of command
577*61046927SAndroid Build Coastguard Worker        - required - boolean (to tag features as required or not)"""
578*61046927SAndroid Build Coastguard Worker        cmd = self.lookupElementInfo(cmdname, self.cmddict)
579*61046927SAndroid Build Coastguard Worker        if cmd is not None:
580*61046927SAndroid Build Coastguard Worker            cmd.required = required
581*61046927SAndroid Build Coastguard Worker            # Tag all parameter types of this command as required.
582*61046927SAndroid Build Coastguard Worker            # This does not remove types of commands in a <remove>
583*61046927SAndroid Build Coastguard Worker            # tag, because many other commands may use the same type.
584*61046927SAndroid Build Coastguard Worker            # We could be more clever and reference count types,
585*61046927SAndroid Build Coastguard Worker            # instead of using a boolean.
586*61046927SAndroid Build Coastguard Worker            if required:
587*61046927SAndroid Build Coastguard Worker                # Look for <type> in entire <command> tree,
588*61046927SAndroid Build Coastguard Worker                # not just immediate children
589*61046927SAndroid Build Coastguard Worker                for type_elem in cmd.elem.findall('.//type'):
590*61046927SAndroid Build Coastguard Worker                    self.markTypeRequired(type_elem.text, required)
591*61046927SAndroid Build Coastguard Worker
592*61046927SAndroid Build Coastguard Worker    def markRequired(self, featurename, feature, required):
593*61046927SAndroid Build Coastguard Worker        """Require or remove features specified in the Element.
594*61046927SAndroid Build Coastguard Worker
595*61046927SAndroid Build Coastguard Worker        - featurename - name of the feature
596*61046927SAndroid Build Coastguard Worker        - feature - Element for `<require>` or `<remove>` tag
597*61046927SAndroid Build Coastguard Worker        - required - boolean (to tag features as required or not)"""
598*61046927SAndroid Build Coastguard Worker        # Loop over types, enums, and commands in the tag
599*61046927SAndroid Build Coastguard Worker        # @@ It would be possible to respect 'api' and 'profile' attributes
600*61046927SAndroid Build Coastguard Worker        #  in individual features, but that is not done yet.
601*61046927SAndroid Build Coastguard Worker        for typeElem in feature.findall('type'):
602*61046927SAndroid Build Coastguard Worker            self.markTypeRequired(typeElem.get('name'), required)
603*61046927SAndroid Build Coastguard Worker        for enumElem in feature.findall('enum'):
604*61046927SAndroid Build Coastguard Worker            self.markEnumRequired(enumElem.get('name'), required)
605*61046927SAndroid Build Coastguard Worker
606*61046927SAndroid Build Coastguard Worker        for cmdElem in feature.findall('command'):
607*61046927SAndroid Build Coastguard Worker            self.markCmdRequired(cmdElem.get('name'), required)
608*61046927SAndroid Build Coastguard Worker
609*61046927SAndroid Build Coastguard Worker    def fillFeatureDictionary(self, interface, featurename, api):
610*61046927SAndroid Build Coastguard Worker        """Capture added interfaces for a `<version>` or `<extension>`.
611*61046927SAndroid Build Coastguard Worker
612*61046927SAndroid Build Coastguard Worker        - interface - Element for `<version>` or `<extension>`, containing
613*61046927SAndroid Build Coastguard Worker          `<require>` and `<remove>` tags
614*61046927SAndroid Build Coastguard Worker        - featurename - name of the feature
615*61046927SAndroid Build Coastguard Worker        - api - string specifying API name being generated
616*61046927SAndroid Build Coastguard Worker        """
617*61046927SAndroid Build Coastguard Worker
618*61046927SAndroid Build Coastguard Worker        # Explicitly initialize known types - errors for unhandled categories
619*61046927SAndroid Build Coastguard Worker        self.gen.featureDictionary[featurename] = {
620*61046927SAndroid Build Coastguard Worker            "enumconstant": {},
621*61046927SAndroid Build Coastguard Worker            "command": {},
622*61046927SAndroid Build Coastguard Worker            "enum": {},
623*61046927SAndroid Build Coastguard Worker            "struct": {},
624*61046927SAndroid Build Coastguard Worker            "handle": {},
625*61046927SAndroid Build Coastguard Worker            "basetype": {},
626*61046927SAndroid Build Coastguard Worker            "include": {},
627*61046927SAndroid Build Coastguard Worker            "define": {},
628*61046927SAndroid Build Coastguard Worker            "bitmask": {},
629*61046927SAndroid Build Coastguard Worker            "union": {},
630*61046927SAndroid Build Coastguard Worker            "funcpointer": {},
631*61046927SAndroid Build Coastguard Worker        }
632*61046927SAndroid Build Coastguard Worker
633*61046927SAndroid Build Coastguard Worker    def requireFeatures(self, interface, featurename, api):
634*61046927SAndroid Build Coastguard Worker        """Process `<require>` tags for a `<version>` or `<extension>`.
635*61046927SAndroid Build Coastguard Worker
636*61046927SAndroid Build Coastguard Worker        - interface - Element for `<version>` or `<extension>`, containing
637*61046927SAndroid Build Coastguard Worker          `<require>` tags
638*61046927SAndroid Build Coastguard Worker        - featurename - name of the feature
639*61046927SAndroid Build Coastguard Worker        - api - string specifying API name being generated
640*61046927SAndroid Build Coastguard Worker        - profile - string specifying API profile being generated"""
641*61046927SAndroid Build Coastguard Worker
642*61046927SAndroid Build Coastguard Worker        # <require> marks things that are required by this version/profile
643*61046927SAndroid Build Coastguard Worker        for feature in interface.findall('require'):
644*61046927SAndroid Build Coastguard Worker            if matchAPIProfile(api, feature):
645*61046927SAndroid Build Coastguard Worker                self.markRequired(featurename, feature, True)
646*61046927SAndroid Build Coastguard Worker
647*61046927SAndroid Build Coastguard Worker    def generateFeature(self, fname, ftype, dictionary, explicit=False):
648*61046927SAndroid Build Coastguard Worker        """Generate a single type / enum group / enum / command,
649*61046927SAndroid Build Coastguard Worker        and all its dependencies as needed.
650*61046927SAndroid Build Coastguard Worker
651*61046927SAndroid Build Coastguard Worker        - fname - name of feature (`<type>`/`<enum>`/`<command>`)
652*61046927SAndroid Build Coastguard Worker        - ftype - type of feature, 'type' | 'enum' | 'command'
653*61046927SAndroid Build Coastguard Worker        - dictionary - of *Info objects - self.{type|enum|cmd}dict
654*61046927SAndroid Build Coastguard Worker        - explicit - True if this is explicitly required by the top-level
655*61046927SAndroid Build Coastguard Worker          XML <require> tag, False if it is a dependency of an explicit
656*61046927SAndroid Build Coastguard Worker          requirement."""
657*61046927SAndroid Build Coastguard Worker
658*61046927SAndroid Build Coastguard Worker        f = self.lookupElementInfo(fname, dictionary)
659*61046927SAndroid Build Coastguard Worker        if f is None:
660*61046927SAndroid Build Coastguard Worker            return
661*61046927SAndroid Build Coastguard Worker
662*61046927SAndroid Build Coastguard Worker        if not f.required:
663*61046927SAndroid Build Coastguard Worker            return
664*61046927SAndroid Build Coastguard Worker
665*61046927SAndroid Build Coastguard Worker        # If feature is not required, or has already been declared, return
666*61046927SAndroid Build Coastguard Worker        if f.declared:
667*61046927SAndroid Build Coastguard Worker            return
668*61046927SAndroid Build Coastguard Worker        # Always mark feature declared, as though actually emitted
669*61046927SAndroid Build Coastguard Worker        f.declared = True
670*61046927SAndroid Build Coastguard Worker
671*61046927SAndroid Build Coastguard Worker        # Determine if this is an alias, and of what, if so
672*61046927SAndroid Build Coastguard Worker        alias = f.elem.get('alias')
673*61046927SAndroid Build Coastguard Worker        # Pull in dependent declaration(s) of the feature.
674*61046927SAndroid Build Coastguard Worker        # For types, there may be one type in the 'requires' attribute of
675*61046927SAndroid Build Coastguard Worker        #   the element, one in the 'alias' attribute, and many in
676*61046927SAndroid Build Coastguard Worker        #   embedded <type> and <enum> tags within the element.
677*61046927SAndroid Build Coastguard Worker        # For commands, there may be many in <type> tags within the element.
678*61046927SAndroid Build Coastguard Worker        # For enums, no dependencies are allowed (though perhaps if you
679*61046927SAndroid Build Coastguard Worker        #   have a uint64 enum, it should require that type).
680*61046927SAndroid Build Coastguard Worker        genProc = None
681*61046927SAndroid Build Coastguard Worker        followupFeature = None
682*61046927SAndroid Build Coastguard Worker        if ftype == 'type':
683*61046927SAndroid Build Coastguard Worker            genProc = self.gen.genType
684*61046927SAndroid Build Coastguard Worker
685*61046927SAndroid Build Coastguard Worker            # Generate type dependencies in 'alias' and 'requires' attributes
686*61046927SAndroid Build Coastguard Worker            if alias:
687*61046927SAndroid Build Coastguard Worker                self.generateFeature(alias, 'type', self.typedict)
688*61046927SAndroid Build Coastguard Worker            requires = f.elem.get('requires')
689*61046927SAndroid Build Coastguard Worker            if requires:
690*61046927SAndroid Build Coastguard Worker                self.generateFeature(requires, 'type', self.typedict)
691*61046927SAndroid Build Coastguard Worker
692*61046927SAndroid Build Coastguard Worker            # Generate types used in defining this type (e.g. in nested
693*61046927SAndroid Build Coastguard Worker            # <type> tags)
694*61046927SAndroid Build Coastguard Worker            # Look for <type> in entire <command> tree,
695*61046927SAndroid Build Coastguard Worker            # not just immediate children
696*61046927SAndroid Build Coastguard Worker            for subtype in f.elem.findall('.//type'):
697*61046927SAndroid Build Coastguard Worker                self.generateFeature(subtype.text, 'type', self.typedict)
698*61046927SAndroid Build Coastguard Worker
699*61046927SAndroid Build Coastguard Worker            # Generate enums used in defining this type, for example in
700*61046927SAndroid Build Coastguard Worker            #   <member><name>member</name>[<enum>MEMBER_SIZE</enum>]</member>
701*61046927SAndroid Build Coastguard Worker            for subtype in f.elem.findall('.//enum'):
702*61046927SAndroid Build Coastguard Worker                self.generateFeature(subtype.text, 'enum', self.enumdict)
703*61046927SAndroid Build Coastguard Worker
704*61046927SAndroid Build Coastguard Worker            # If the type is an enum group, look up the corresponding
705*61046927SAndroid Build Coastguard Worker            # group in the group dictionary and generate that instead.
706*61046927SAndroid Build Coastguard Worker            if f.elem.get('category') == 'enum':
707*61046927SAndroid Build Coastguard Worker                group = self.lookupElementInfo(fname, self.groupdict)
708*61046927SAndroid Build Coastguard Worker                if alias is not None:
709*61046927SAndroid Build Coastguard Worker                    # Now, pass the *aliased* GroupInfo to the genGroup, but
710*61046927SAndroid Build Coastguard Worker                    # with an additional parameter which is the alias name.
711*61046927SAndroid Build Coastguard Worker                    genProc = self.gen.genGroup
712*61046927SAndroid Build Coastguard Worker                    f = self.lookupElementInfo(alias, self.groupdict)
713*61046927SAndroid Build Coastguard Worker                elif group is None:
714*61046927SAndroid Build Coastguard Worker                    return
715*61046927SAndroid Build Coastguard Worker                else:
716*61046927SAndroid Build Coastguard Worker                    genProc = self.gen.genGroup
717*61046927SAndroid Build Coastguard Worker                    f = group
718*61046927SAndroid Build Coastguard Worker
719*61046927SAndroid Build Coastguard Worker                    # @ The enum group is not ready for generation. At this
720*61046927SAndroid Build Coastguard Worker                    # @   point, it contains all <enum> tags injected by
721*61046927SAndroid Build Coastguard Worker                    # @   <extension> tags without any verification of whether
722*61046927SAndroid Build Coastguard Worker                    # @   they are required or not. It may also contain
723*61046927SAndroid Build Coastguard Worker                    # @   duplicates injected by multiple consistent
724*61046927SAndroid Build Coastguard Worker                    # @   definitions of an <enum>.
725*61046927SAndroid Build Coastguard Worker
726*61046927SAndroid Build Coastguard Worker                    # @ Pass over each enum, marking its enumdict[] entry as
727*61046927SAndroid Build Coastguard Worker                    # @ required or not. Mark aliases of enums as required,
728*61046927SAndroid Build Coastguard Worker                    # @ too.
729*61046927SAndroid Build Coastguard Worker
730*61046927SAndroid Build Coastguard Worker                    enums = group.elem.findall('enum')
731*61046927SAndroid Build Coastguard Worker                    # Check for required enums, including aliases
732*61046927SAndroid Build Coastguard Worker                    # LATER - Check for, report, and remove duplicates?
733*61046927SAndroid Build Coastguard Worker                    enumAliases = []
734*61046927SAndroid Build Coastguard Worker                    for elem in enums:
735*61046927SAndroid Build Coastguard Worker                        name = elem.get('name')
736*61046927SAndroid Build Coastguard Worker
737*61046927SAndroid Build Coastguard Worker                        required = False
738*61046927SAndroid Build Coastguard Worker
739*61046927SAndroid Build Coastguard Worker                        extname = elem.get('extname')
740*61046927SAndroid Build Coastguard Worker                        version = elem.get('version')
741*61046927SAndroid Build Coastguard Worker                        if extname is not None:
742*61046927SAndroid Build Coastguard Worker                            # 'supported' attribute was injected when the <enum> element was
743*61046927SAndroid Build Coastguard Worker                            # moved into the <enums> group in Registry.parseTree()
744*61046927SAndroid Build Coastguard Worker                            supported_list = elem.get('supported').split(",")
745*61046927SAndroid Build Coastguard Worker                            if 'vulkan' in supported_list:
746*61046927SAndroid Build Coastguard Worker                                required = True
747*61046927SAndroid Build Coastguard Worker                            elif re.match(self.genOpts.addExtensions, extname) is not None:
748*61046927SAndroid Build Coastguard Worker                                required = True
749*61046927SAndroid Build Coastguard Worker                        elif version is not None:
750*61046927SAndroid Build Coastguard Worker                            required = re.match(self.genOpts.emitversions, version) is not None
751*61046927SAndroid Build Coastguard Worker                        else:
752*61046927SAndroid Build Coastguard Worker                            required = True
753*61046927SAndroid Build Coastguard Worker
754*61046927SAndroid Build Coastguard Worker                        if required:
755*61046927SAndroid Build Coastguard Worker                            # Mark this element as required (in the element, not the EnumInfo)
756*61046927SAndroid Build Coastguard Worker                            elem.set('required', 'true')
757*61046927SAndroid Build Coastguard Worker                            # If it is an alias, track that for later use
758*61046927SAndroid Build Coastguard Worker                            enumAlias = elem.get('alias')
759*61046927SAndroid Build Coastguard Worker                            if enumAlias:
760*61046927SAndroid Build Coastguard Worker                                enumAliases.append(enumAlias)
761*61046927SAndroid Build Coastguard Worker                    for elem in enums:
762*61046927SAndroid Build Coastguard Worker                        name = elem.get('name')
763*61046927SAndroid Build Coastguard Worker                        if name in enumAliases:
764*61046927SAndroid Build Coastguard Worker                            elem.set('required', 'true')
765*61046927SAndroid Build Coastguard Worker            if f is None:
766*61046927SAndroid Build Coastguard Worker                raise RuntimeError("Should not get here")
767*61046927SAndroid Build Coastguard Worker            if f.elem.get('category') == 'bitmask':
768*61046927SAndroid Build Coastguard Worker                followupFeature = f.elem.get('bitvalues')
769*61046927SAndroid Build Coastguard Worker        elif ftype == 'command':
770*61046927SAndroid Build Coastguard Worker            # Generate command dependencies in 'alias' attribute
771*61046927SAndroid Build Coastguard Worker            if alias:
772*61046927SAndroid Build Coastguard Worker                self.generateFeature(alias, 'command', self.cmddict)
773*61046927SAndroid Build Coastguard Worker
774*61046927SAndroid Build Coastguard Worker            genProc = self.gen.genCmd
775*61046927SAndroid Build Coastguard Worker            for type_elem in f.elem.findall('.//type'):
776*61046927SAndroid Build Coastguard Worker                depname = type_elem.text
777*61046927SAndroid Build Coastguard Worker                self.generateFeature(depname, 'type', self.typedict)
778*61046927SAndroid Build Coastguard Worker        elif ftype == 'enum':
779*61046927SAndroid Build Coastguard Worker            # Generate enum dependencies in 'alias' attribute
780*61046927SAndroid Build Coastguard Worker            if alias:
781*61046927SAndroid Build Coastguard Worker                self.generateFeature(alias, 'enum', self.enumdict)
782*61046927SAndroid Build Coastguard Worker            genProc = self.gen.genEnum
783*61046927SAndroid Build Coastguard Worker
784*61046927SAndroid Build Coastguard Worker        # Actually generate the type only if emitting declarations
785*61046927SAndroid Build Coastguard Worker        if self.emitFeatures:
786*61046927SAndroid Build Coastguard Worker            if genProc is None:
787*61046927SAndroid Build Coastguard Worker                raise RuntimeError("genProc is None when we should be emitting")
788*61046927SAndroid Build Coastguard Worker            genProc(f, fname, alias)
789*61046927SAndroid Build Coastguard Worker
790*61046927SAndroid Build Coastguard Worker        if followupFeature:
791*61046927SAndroid Build Coastguard Worker            self.generateFeature(followupFeature, "type", self.typedict)
792*61046927SAndroid Build Coastguard Worker
793*61046927SAndroid Build Coastguard Worker    def generateRequiredInterface(self, interface):
794*61046927SAndroid Build Coastguard Worker        """Generate all interfaces required by an API version or extension.
795*61046927SAndroid Build Coastguard Worker
796*61046927SAndroid Build Coastguard Worker        - interface - Element for `<version>` or `<extension>`"""
797*61046927SAndroid Build Coastguard Worker
798*61046927SAndroid Build Coastguard Worker        # Loop over all features inside all <require> tags.
799*61046927SAndroid Build Coastguard Worker        for features in interface.findall('require'):
800*61046927SAndroid Build Coastguard Worker            for t in features.findall('type'):
801*61046927SAndroid Build Coastguard Worker                self.generateFeature(t.get('name'), 'type', self.typedict, explicit=True)
802*61046927SAndroid Build Coastguard Worker            for e in features.findall('enum'):
803*61046927SAndroid Build Coastguard Worker                # If this is an enum extending an enumerated type, do not
804*61046927SAndroid Build Coastguard Worker                # generate it - this has already been done in reg.parseTree,
805*61046927SAndroid Build Coastguard Worker                # by copying this element into the enumerated type.
806*61046927SAndroid Build Coastguard Worker                enumextends = e.get('extends')
807*61046927SAndroid Build Coastguard Worker                if not enumextends:
808*61046927SAndroid Build Coastguard Worker                    self.generateFeature(e.get('name'), 'enum', self.enumdict, explicit=True)
809*61046927SAndroid Build Coastguard Worker            for c in features.findall('command'):
810*61046927SAndroid Build Coastguard Worker                self.generateFeature(c.get('name'), 'command', self.cmddict, explicit=True)
811*61046927SAndroid Build Coastguard Worker
812*61046927SAndroid Build Coastguard Worker    def apiGen(self):
813*61046927SAndroid Build Coastguard Worker        """Generate interface for specified versions using the current
814*61046927SAndroid Build Coastguard Worker        generator and generator options"""
815*61046927SAndroid Build Coastguard Worker
816*61046927SAndroid Build Coastguard Worker        # Could reset required/declared flags for all features here.
817*61046927SAndroid Build Coastguard Worker        # This has been removed as never used. The initial motivation was
818*61046927SAndroid Build Coastguard Worker        # the idea of calling apiGen() repeatedly for different targets, but
819*61046927SAndroid Build Coastguard Worker        # this has never been done. The 20% or so build-time speedup that
820*61046927SAndroid Build Coastguard Worker        # might result is not worth the effort to make it actually work.
821*61046927SAndroid Build Coastguard Worker        #
822*61046927SAndroid Build Coastguard Worker        # self.apiReset()
823*61046927SAndroid Build Coastguard Worker
824*61046927SAndroid Build Coastguard Worker        # Compile regexps used to select versions & extensions
825*61046927SAndroid Build Coastguard Worker        regVersions = re.compile(self.genOpts.versions)
826*61046927SAndroid Build Coastguard Worker        regEmitVersions = re.compile(self.genOpts.emitversions)
827*61046927SAndroid Build Coastguard Worker        regAddExtensions = re.compile(self.genOpts.addExtensions)
828*61046927SAndroid Build Coastguard Worker        regEmitExtensions = re.compile(self.genOpts.emitExtensions)
829*61046927SAndroid Build Coastguard Worker
830*61046927SAndroid Build Coastguard Worker        # Get all matching API feature names & add to list of FeatureInfo
831*61046927SAndroid Build Coastguard Worker        # Note we used to select on feature version attributes, not names.
832*61046927SAndroid Build Coastguard Worker        features = []
833*61046927SAndroid Build Coastguard Worker        apiMatch = False
834*61046927SAndroid Build Coastguard Worker        for key in self.apidict:
835*61046927SAndroid Build Coastguard Worker            fi = self.apidict[key]
836*61046927SAndroid Build Coastguard Worker            api = fi.elem.get('api')
837*61046927SAndroid Build Coastguard Worker            if apiNameMatch('vulkan', api):
838*61046927SAndroid Build Coastguard Worker                apiMatch = True
839*61046927SAndroid Build Coastguard Worker                if regVersions.match(fi.name):
840*61046927SAndroid Build Coastguard Worker                    # Matches API & version #s being generated. Mark for
841*61046927SAndroid Build Coastguard Worker                    # emission and add to the features[] list .
842*61046927SAndroid Build Coastguard Worker                    # @@ Could use 'declared' instead of 'emit'?
843*61046927SAndroid Build Coastguard Worker                    fi.emit = (regEmitVersions.match(fi.name) is not None)
844*61046927SAndroid Build Coastguard Worker                    features.append(fi)
845*61046927SAndroid Build Coastguard Worker
846*61046927SAndroid Build Coastguard Worker        # Get all matching extensions, in order by their extension number,
847*61046927SAndroid Build Coastguard Worker        # and add to the list of features.
848*61046927SAndroid Build Coastguard Worker        # Start with extensions whose 'supported' attributes match the API
849*61046927SAndroid Build Coastguard Worker        # being generated. Add extensions matching the pattern specified in
850*61046927SAndroid Build Coastguard Worker        # regExtensions, then remove extensions matching the pattern
851*61046927SAndroid Build Coastguard Worker        # specified in regRemoveExtensions
852*61046927SAndroid Build Coastguard Worker        for (extName, ei) in sorted(self.extdict.items(), key=lambda x: x[1].number if x[1].number is not None else '0'):
853*61046927SAndroid Build Coastguard Worker            extName = ei.name
854*61046927SAndroid Build Coastguard Worker            include = False
855*61046927SAndroid Build Coastguard Worker
856*61046927SAndroid Build Coastguard Worker            # Include extension if defaultExtensions is not None and is
857*61046927SAndroid Build Coastguard Worker            # exactly matched by the 'supported' attribute.
858*61046927SAndroid Build Coastguard Worker            if apiNameMatch('vulkan', ei.elem.get('supported')):
859*61046927SAndroid Build Coastguard Worker                include = True
860*61046927SAndroid Build Coastguard Worker
861*61046927SAndroid Build Coastguard Worker            # Include additional extensions if the extension name matches
862*61046927SAndroid Build Coastguard Worker            # the regexp specified in the generator options. This allows
863*61046927SAndroid Build Coastguard Worker            # forcing extensions into an interface even if they are not
864*61046927SAndroid Build Coastguard Worker            # tagged appropriately in the registry.
865*61046927SAndroid Build Coastguard Worker            # However, we still respect the 'supported' attribute.
866*61046927SAndroid Build Coastguard Worker            if regAddExtensions.match(extName) is not None:
867*61046927SAndroid Build Coastguard Worker                if not apiNameMatch('vulkan', ei.elem.get('supported')):
868*61046927SAndroid Build Coastguard Worker                    include = False
869*61046927SAndroid Build Coastguard Worker                else:
870*61046927SAndroid Build Coastguard Worker                    include = True
871*61046927SAndroid Build Coastguard Worker            # If the extension is to be included, add it to the
872*61046927SAndroid Build Coastguard Worker            # extension features list.
873*61046927SAndroid Build Coastguard Worker            if include:
874*61046927SAndroid Build Coastguard Worker                ei.emit = (regEmitExtensions.match(extName) is not None)
875*61046927SAndroid Build Coastguard Worker                features.append(ei)
876*61046927SAndroid Build Coastguard Worker
877*61046927SAndroid Build Coastguard Worker        # Sort the features list, if a sort procedure is defined
878*61046927SAndroid Build Coastguard Worker        if self.genOpts.sortProcedure:
879*61046927SAndroid Build Coastguard Worker            self.genOpts.sortProcedure(features)
880*61046927SAndroid Build Coastguard Worker
881*61046927SAndroid Build Coastguard Worker        # Passes 1+2: loop over requested API versions and extensions tagging
882*61046927SAndroid Build Coastguard Worker        #   types/commands/features as required (in an <require> block) or no
883*61046927SAndroid Build Coastguard Worker        #   longer required (in an <remove> block). <remove>s are processed
884*61046927SAndroid Build Coastguard Worker        #   after all <require>s, so removals win.
885*61046927SAndroid Build Coastguard Worker        # If a profile other than 'None' is being generated, it must
886*61046927SAndroid Build Coastguard Worker        #   match the profile attribute (if any) of the <require> and
887*61046927SAndroid Build Coastguard Worker        #   <remove> tags.
888*61046927SAndroid Build Coastguard Worker        for f in features:
889*61046927SAndroid Build Coastguard Worker            self.fillFeatureDictionary(f.elem, f.name, 'vulkan')
890*61046927SAndroid Build Coastguard Worker            self.requireFeatures(f.elem, f.name, 'vulkan')
891*61046927SAndroid Build Coastguard Worker
892*61046927SAndroid Build Coastguard Worker        # @@May need to strip <spirvcapability> / <spirvextension> <enable>
893*61046927SAndroid Build Coastguard Worker        # tags of these forms:
894*61046927SAndroid Build Coastguard Worker        #   <enable version="VK_API_VERSION_1_0"/>
895*61046927SAndroid Build Coastguard Worker        #   <enable struct="VkPhysicalDeviceFeatures" feature="geometryShader" requires="VK_VERSION_1_0"/>
896*61046927SAndroid Build Coastguard Worker        #   <enable extension="VK_KHR_shader_draw_parameters"/>
897*61046927SAndroid Build Coastguard Worker        #   <enable property="VkPhysicalDeviceVulkan12Properties" member="shaderDenormPreserveFloat16" value="VK_TRUE" requires="VK_VERSION_1_2,VK_KHR_shader_float_controls"/>
898*61046927SAndroid Build Coastguard Worker
899*61046927SAndroid Build Coastguard Worker        # Pass 3: loop over specified API versions and extensions printing
900*61046927SAndroid Build Coastguard Worker        #   declarations for required things which have not already been
901*61046927SAndroid Build Coastguard Worker        #   generated.
902*61046927SAndroid Build Coastguard Worker        self.gen.beginFile(self.genOpts)
903*61046927SAndroid Build Coastguard Worker        for f in features:
904*61046927SAndroid Build Coastguard Worker            emit = self.emitFeatures = f.emit
905*61046927SAndroid Build Coastguard Worker            # Generate the interface (or just tag its elements as having been
906*61046927SAndroid Build Coastguard Worker            # emitted, if they have not been).
907*61046927SAndroid Build Coastguard Worker            self.gen.beginFeature(f.elem, emit)
908*61046927SAndroid Build Coastguard Worker            self.generateRequiredInterface(f.elem)
909*61046927SAndroid Build Coastguard Worker            self.gen.endFeature()
910*61046927SAndroid Build Coastguard Worker        self.gen.endFile()
911