Use [u]int32_t in the framework
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / scripts / gen_framework.py
1 # -*- coding: utf-8 -*-
2
3 #-------------------------------------------------------------------------
4 # Vulkan CTS
5 # ----------
6 #
7 # Copyright (c) 2015 Google Inc.
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
12 #
13 #      http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
20 #
21 #-------------------------------------------------------------------------
22
23 import os
24 import re
25 import sys
26 import copy
27 from itertools import chain
28 from collections import OrderedDict
29
30 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
31
32 from build.common import DEQP_DIR
33 from khr_util.format import indentLines, writeInlFile
34
35 VULKAN_H_DIR    = os.path.join(os.path.dirname(__file__), "src")
36 VULKAN_DIR              = os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan")
37
38 INL_HEADER = """\
39 /* WARNING: This is auto-generated file. Do not modify, since changes will
40  * be lost! Modify the generating script instead.
41  */\
42 """
43
44 DEFINITIONS                     = [
45         ("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE",    "size_t"),
46         ("VK_MAX_EXTENSION_NAME_SIZE",                  "size_t"),
47         ("VK_MAX_DRIVER_NAME_SIZE",                             "size_t"),
48         ("VK_MAX_DRIVER_INFO_SIZE",                             "size_t"),
49         ("VK_UUID_SIZE",                                                "size_t"),
50         ("VK_LUID_SIZE",                                                "size_t"),
51         ("VK_MAX_MEMORY_TYPES",                                 "size_t"),
52         ("VK_MAX_MEMORY_HEAPS",                                 "size_t"),
53         ("VK_MAX_DESCRIPTION_SIZE",                             "size_t"),
54         ("VK_MAX_DEVICE_GROUP_SIZE",                    "size_t"),
55         ("VK_ATTACHMENT_UNUSED",                                "uint32_t"),
56         ("VK_SUBPASS_EXTERNAL",                                 "uint32_t"),
57         ("VK_QUEUE_FAMILY_IGNORED",                             "uint32_t"),
58         ("VK_QUEUE_FAMILY_EXTERNAL",                    "uint32_t"),
59         ("VK_REMAINING_MIP_LEVELS",                             "uint32_t"),
60         ("VK_REMAINING_ARRAY_LAYERS",                   "uint32_t"),
61         ("VK_WHOLE_SIZE",                                               "vk::VkDeviceSize"),
62         ("VK_TRUE",                                                             "vk::VkBool32"),
63         ("VK_FALSE",                                                    "vk::VkBool32"),
64 ]
65
66 PLATFORM_TYPES          = [
67         # VK_KHR_xlib_surface
68         (["Display","*"],                                               ["XlibDisplayPtr"],                             "void*"),
69         (["Window"],                                                    ["XlibWindow"],                                 "deUintptr",),
70         (["VisualID"],                                                  ["XlibVisualID"],                               "uint32_t"),
71
72         # VK_KHR_xcb_surface
73         (["xcb_connection_t", "*"],                             ["XcbConnectionPtr"],                   "void*"),
74         (["xcb_window_t"],                                              ["XcbWindow"],                                  "deUintptr"),
75         (["xcb_visualid_t"],                                    ["XcbVisualid"],                                "uint32_t"),
76
77         # VK_KHR_wayland_surface
78         (["struct", "wl_display","*"],                  ["WaylandDisplayPtr"],                  "void*"),
79         (["struct", "wl_surface", "*"],                 ["WaylandSurfacePtr"],                  "void*"),
80
81         # VK_KHR_mir_surface
82         (["MirConnection", "*"],                                ["MirConnectionPtr"],                   "void*"),
83         (["MirSurface", "*"],                                   ["MirSurfacePtr"],                              "void*"),
84
85         # VK_KHR_android_surface
86         (["ANativeWindow", "*"],                                ["AndroidNativeWindowPtr"],             "void*"),
87
88         # VK_KHR_win32_surface
89         (["HINSTANCE"],                                                 ["Win32InstanceHandle"],                "void*"),
90         (["HWND"],                                                              ["Win32WindowHandle"],                  "void*"),
91         (["HANDLE"],                                                    ["Win32Handle"],                                "void*"),
92         (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"),
93         (["AHardwareBuffer", "*"],                              ["AndroidHardwareBufferPtr"],   "void*"),
94         (["HMONITOR"],                                                  ["Win32MonitorHandle"],                 "void*"),
95         (["LPCWSTR"],                                                   ["Win32LPCWSTR"],                               "const void*"),
96
97         # VK_EXT_acquire_xlib_display
98         (["RROutput"],                                                  ["RROutput"],                                   "void*"),
99
100         (["zx_handle_t"],                                               ["zx_handle_t"],                                "int32_t"),
101         (["GgpFrameToken"],                                             ["GgpFrameToken"],                              "int32_t"),
102         (["GgpStreamDescriptor"],                               ["GgpStreamDescriptor"],                "int32_t"),
103         (["CAMetalLayer"],                                              ["CAMetalLayer"],                               "void*"),
104 ]
105
106 PLATFORM_TYPE_NAMESPACE = "pt"
107
108 TYPE_SUBSTITUTIONS              = [
109         ("uint8_t",             "deUint8"),
110         ("uint16_t",    "deUint16"),
111         ("uint64_t",    "deUint64"),
112         ("int8_t",              "deInt8"),
113         ("int16_t",             "deInt16"),
114         ("int64_t",             "deInt64"),
115         ("bool32_t",    "deUint32"),
116         ("size_t",              "deUintptr"),
117
118         # Platform-specific
119         ("DWORD",               "deUint32"),
120         ("HANDLE*",             PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
121 ]
122
123 EXTENSION_POSTFIXES                             = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK", "FUCHSIA", "GGP", "AMD"]
124 EXTENSION_POSTFIXES_STANDARD    = ["KHR", "EXT"]
125
126 def prefixName (prefix, name):
127         name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
128         name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
129         name = name.upper()
130
131         name = name.replace("YCB_CR_", "YCBCR_")
132         name = name.replace("WIN_32_", "WIN32_")
133         name = name.replace("8_BIT_", "8BIT_")
134         name = name.replace("16_BIT_", "16BIT_")
135         name = name.replace("INT_64_", "INT64_")
136         name = name.replace("D_3_D_12_", "D3D12_")
137         name = name.replace("IOSSURFACE_", "IOS_SURFACE_")
138         name = name.replace("MAC_OS", "MACOS_")
139         name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_")
140         name = name.replace("VIEWPORT_W", "VIEWPORT_W_")
141         name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES")
142         name = name.replace("PHYSICAL_DEVICE_SHADER_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES")
143         name = name.replace("_PCIBUS_", "_PCI_BUS_")
144         name = name.replace("ASTCD", "ASTC_D")
145         name = name.replace("AABBNV", "AABB_NV")
146         name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
147         name = name.replace("SMBUILTINS", "SM_BUILTINS")
148         name = name.replace("ASTCHDRFEATURES", "ASTC_HDR_FEATURES")
149         name = name.replace("UINT_8", "UINT8")
150         name = name.replace("VULKAN_11_FEATURES", "VULKAN_1_1_FEATURES")
151         name = name.replace("VULKAN_11_PROPERTIES", "VULKAN_1_1_PROPERTIES")
152         name = name.replace("VULKAN_12_FEATURES", "VULKAN_1_2_FEATURES")
153         name = name.replace("VULKAN_12_PROPERTIES", "VULKAN_1_2_PROPERTIES")
154         name = name.replace("INT_8_", "INT8_")
155         name = name.replace("AABBNV", "AABB_NV")
156         name = name.replace("_H_264_", "_H264_")
157         name = name.replace("_H_265_", "_H265_")
158         name = name.replace("RDMAFEATURES", "RDMA_FEATURES")
159
160
161         return prefix + name
162
163 class Version:
164         def __init__ (self, versionTuple):
165                 self.major = versionTuple[0]
166                 self.minor = versionTuple[1]
167                 self.patch = versionTuple[2]
168
169         def getInHex (self):
170                 if self.patch == 0:
171                         return "VK_API_VERSION_%d_%d" % (self.major, self.minor)
172                 return '0x%Xu' % (hash(self))
173
174         def isStandardVersion (self):
175                 if self.patch != 0:
176                         return False
177                 if self.major != 1:
178                         return False
179                 return True
180
181         def getBestRepresentation (self):
182                 if self.isStandardVersion():
183                         return self.getInHex()
184                 return self.getDefineName()
185
186         def getDefineName (self):
187                 return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch)
188
189         def __hash__ (self):
190                 return (self.major << 22) | (self.minor << 12) | self.patch
191
192         def __eq__ (self, other):
193                 return self.major == other.major and self.minor == other.minor and self.patch == other.patch
194
195         def __str__ (self):
196                 return self.getBestRepresentation()
197
198
199 class Handle:
200         TYPE_DISP               = 0
201         TYPE_NONDISP    = 1
202
203         def __init__ (self, type, name):
204                 self.type               = type
205                 self.name               = name
206                 self.alias              = None
207                 self.isAlias    = False
208
209         def getHandleType (self):
210                 return prefixName("HANDLE_TYPE_", self.name)
211
212         def checkAliasValidity (self):
213                 pass
214
215         def __repr__ (self):
216                 return '%s (%s, %s)' % (self.name, self.alias, self.isAlias)
217
218 class Definition:
219         def __init__ (self, type, name, value):
220                 self.type       = type
221                 self.name       = name
222                 self.value      = value
223                 self.alias      = None
224                 self.isAlias    = False
225
226         def __repr__ (self):
227                 return '%s = %s (%s)' % (self.name, self.value, self.type)
228
229 class Enum:
230         def __init__ (self, name, values):
231                 self.name               = name
232                 self.values             = values
233                 self.alias              = None
234                 self.isAlias    = False
235
236         def checkAliasValidity (self):
237                 if self.alias != None:
238                         if len(self.values) != len(self.alias.values):
239                                 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
240                         for index, value in enumerate(self.values):
241                                 aliasVal = self.alias.values[index]
242                                 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
243                                         raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
244
245         def __repr__ (self):
246                 return '%s (%s) %s' % (self.name, self.alias, self.values)
247
248 class Bitfield:
249         def __init__ (self, name, values):
250                 self.name               = name
251                 self.values             = values
252                 self.alias              = None
253                 self.isAlias    = False
254
255         def checkAliasValidity (self):
256                 if self.alias != None:
257                         if len(self.values) != len(self.alias.values):
258                                 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
259                         for index, value in enumerate(self.values):
260                                 aliasVal = self.alias.values[index]
261                                 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
262                                         raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
263
264         def __repr__ (self):
265                 return '%s (%s)' % (self.name, self.alias)
266
267 class Variable:
268         def __init__ (self, type, name, arraySizeOrFieldWidth):
269                 type            = type.replace('*',' *').replace('&',' &')
270                 for src, dst in TYPE_SUBSTITUTIONS:
271                         type = type.replace(src, dst)
272                 self.type       = type.split(' ')
273                 for platformType, substitute, compat in PLATFORM_TYPES:
274                         range = self.contains(self.type, platformType)
275                         if range != None:
276                                 self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:]
277                                 break
278                 self.name               = name
279                 if len(arraySizeOrFieldWidth) > 0 and arraySizeOrFieldWidth[0] == ':':
280                         self.arraySize  = ''
281                         self.fieldWidth = arraySizeOrFieldWidth
282                 else:
283                         self.arraySize  = arraySizeOrFieldWidth
284                         self.fieldWidth = ''
285
286         def contains(self, big, small):
287                 for i in range(len(big)-len(small)+1):
288                         for j in range(len(small)):
289                                 if big[i+j] != small[j]:
290                                         break
291                         else:
292                                 return i, i+len(small)
293                 return None
294
295         def getType (self):
296                 return ' '.join(self.type).replace(' *','*').replace(' &','&')
297
298         def getAsString (self, separator):
299                 return '%s%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize, self.fieldWidth)
300
301         def getAsStringForArgumentList (self, separator):
302                 return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize)
303
304         def __repr__ (self):
305                 return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize)
306
307         def __eq__ (self, other):
308                 if len(self.type) != len(other.type):
309                         return False
310                 for index, type in enumerate(self.type):
311                         if "*" == type or "&" == type or "const" == type or "volatile" == type:
312                                 if type != other.type[index]:
313                                         return False
314                         elif type != other.type[index] and \
315                                 type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \
316                                 other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD):
317                                 return False
318                 return self.arraySize == other.arraySize
319
320         def __ne__ (self, other):
321                 return not self == other
322
323 class CompositeType:
324         CLASS_STRUCT    = 0
325         CLASS_UNION             = 1
326
327         def __init__ (self, typeClass, name, members, apiVersion = None):
328                 self.typeClass  = typeClass
329                 self.name               = name
330                 self.members    = members
331                 self.alias              = None
332                 self.isAlias    = False
333                 self.apiVersion = apiVersion
334
335         def getClassName (self):
336                 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
337                 return names[self.typeClass]
338
339         def checkAliasValidity (self):
340                 if self.alias != None:
341                         if len(self.members) != len(self.alias.members):
342                                 raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name))
343                         for index, member in enumerate(self.members ):
344                                 break
345                                 #if member != self.alias.members[index]:
346                                         #raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name))
347                                         #raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".")
348         def __repr__ (self):
349                 return '%s (%s)' % (self.name, self.alias)
350
351 class Function:
352         TYPE_PLATFORM           = 0 # Not bound to anything
353         TYPE_INSTANCE           = 1 # Bound to VkInstance
354         TYPE_DEVICE                     = 2 # Bound to VkDevice
355
356         def __init__ (self, name, returnType, arguments, apiVersion = None):
357                 self.name               = name
358                 self.returnType = returnType
359                 self.arguments  = arguments
360                 self.alias              = None
361                 self.isAlias    = False
362                 self.apiVersion = apiVersion
363
364         def getType (self):
365                 # Special functions
366                 if self.name == "vkGetInstanceProcAddr":
367                         return Function.TYPE_PLATFORM
368                 assert len(self.arguments) > 0
369                 firstArgType = self.arguments[0].getType()
370                 if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
371                         return Function.TYPE_INSTANCE
372                 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
373                         return Function.TYPE_DEVICE
374                 else:
375                         return Function.TYPE_PLATFORM
376
377         def checkAliasValidity (self):
378                 if self.alias != None:
379                         if len(self.arguments) != len(self.alias.arguments):
380                                 raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name))
381                         if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)):
382                                 raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name))
383                         for index, argument in enumerate(self.arguments):
384                                 if argument != self.alias.arguments[index]:
385                                         raise Exception("argument %s: \"%s\" of %s is different than \"%s\" of %s." % (index, self.alias.arguments[index].getAsString(' '), self.alias.name, argument.getAsString(' '), self.name))
386
387         def __repr__ (self):
388                 return '%s (%s)' % (self.name, self.alias)
389
390 class Extension:
391         def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, typedefs, versionInCore):
392                 self.name                       = name
393                 self.definitions        = definitions
394                 self.additionalDefs = additionalDefinitions
395                 self.handles            = handles
396                 self.enums                      = enums
397                 self.bitfields          = bitfields
398                 self.compositeTypes     = compositeTypes
399                 self.functions          = functions
400                 self.typedefs           = typedefs
401                 self.versionInCore      = versionInCore
402
403         def __repr__ (self):
404                 return 'EXT:\n%s ->\nENUMS:\n%s\nCOMPOS:\n%s\nFUNCS:\n%s\nBITF:\n%s\nHAND:\n%s\nDEFS:\n%s\n' % (self.name, self.enums, self.compositeTypes, self.functions, self.bitfields, self.handles, self.definitions, self.versionInCore)
405
406 class API:
407         def __init__ (self, versions, definitions, handles, enums, bitfields, bitfields64, compositeTypes, functions, extensions):
408                 self.versions           = versions
409                 self.definitions        = definitions
410                 self.handles            = handles
411                 self.enums                      = enums
412                 self.bitfields          = bitfields
413                 self.bitfields64        = bitfields64
414                 self.compositeTypes     = compositeTypes
415                 self.functions          = functions # \note contains extension functions as well
416                 self.extensions         = extensions
417
418 def readFile (filename):
419         with open(filename, 'rt') as f:
420                 return f.read()
421
422 IDENT_PTRN      = r'[a-zA-Z_][a-zA-Z0-9_]*'
423 WIDTH_PTRN      = r'[:0-9]*'
424 TYPE_PTRN       = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
425
426 def getInterfaceName (function):
427         assert function.name[:2] == "vk"
428         return function.name[2].lower() + function.name[3:]
429
430 def getFunctionTypeName (function):
431         assert function.name[:2] == "vk"
432         return function.name[2:] + "Func"
433
434 def endsWith (str, postfix):
435         return str[-len(postfix):] == postfix
436
437 def splitNameExtPostfix (name):
438         knownExtPostfixes = EXTENSION_POSTFIXES
439         for postfix in knownExtPostfixes:
440                 if endsWith(name, postfix):
441                         return (name[:-len(postfix)], postfix)
442         return (name, "")
443
444 def getBitEnumNameForBitfield (bitfieldName):
445         bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
446         assert bitfieldName[-1] == "s"
447         return bitfieldName[:-1] + "Bits" + postfix
448
449 def getBitfieldNameForBitEnum (bitEnumName):
450         bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
451         assert bitEnumName[-4:] == "Bits"
452         return bitEnumName[:-4] + "s" + postfix
453
454 def parsePreprocDefinedValue (src, name):
455         value = parsePreprocDefinedValueOptional(src, name)
456         if value is None:
457                 raise Exception("No such definition: %s" % name)
458         return value
459
460 def parsePreprocDefinedValueOptional (src, name):
461         definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
462         if definition is None:
463                 return None
464         value = definition.group(1).strip()
465         if value == "UINT32_MAX":
466                 value = "(~0u)"
467         return value
468
469 def parseEnum (name, src):
470         keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,\n}]+)\s*[,\n}]'
471         return Enum(name, re.findall(keyValuePtrn, src))
472
473 # \note Parses raw enums, some are mapped to bitfields later
474 def parseEnums (src):
475         matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
476         enums   = []
477         for enumname, contents, typename in matches:
478                 enums.append(parseEnum(typename, contents))
479         return enums
480
481 def parseCompositeType (type, name, src):
482         typeNamePtrn    = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\]|\s*:\s*[0-9]+)*)\s*;'
483         matches                 = re.findall(typeNamePtrn, src)
484         members                 = [Variable(t.strip(), n.strip(), a.replace(' ', '')) for t, n, a, _ in matches]
485         return CompositeType(type, name, members)
486
487 def parseCompositeTypes (src):
488         typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
489         matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
490         types   = []
491         for type, structname, contents, typename in matches:
492                 types.append(parseCompositeType(typeMap[type], typename, contents))
493         return types
494
495 def parseCompositeTypesByVersion (src, versionsData):
496
497         # find occurence of extension is a place where
498         # we cant assign apiVersion to found structures
499         extPtrn         = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
500         versionEnd      = re.search(extPtrn, src)
501         versions        = [Version((v[2], v[3], 0)) for v in versionsData]
502         versions.append(None)
503
504         # construct list of locations where version definitions start, and add the end of the file to it
505         sectionLocations = [versionDef[1] for versionDef in versionsData]
506         sectionLocations.append(versionEnd.start())
507         sectionLocations.append(len(src))
508
509         # construct function declaration pattern
510         ptrn            = r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;'
511         regPtrn         = re.compile(ptrn)
512         types           = []
513         typeMap         = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
514
515         # iterate over all versions and find all structure definitions
516         for index, v in enumerate(versions):
517                 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
518                 for type, structname, contents, typename in matches:
519                         compositeType = parseCompositeType(typeMap[type], typename, contents)
520                         compositeType.apiVersion = v
521                         types.append(compositeType)
522         return types
523
524 def parseVersions (src):
525         # returns list of tuples each with four items:
526         # 1. string with version token (without ' 1' at the end)
527         # 2. starting point off version specific definitions in vulkan.h.in
528         # 3. major version number
529         # 4. minor version number
530         return [(m.group()[:-2], m.start(), int(m.group(1)), int(m.group(2))) for m in re.finditer('VK_VERSION_([1-9])_([0-9]) 1', src)]
531
532 def parseHandles (src):
533         matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
534         handles = []
535         typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
536         for type, name in matches:
537                 handle = Handle(typeMap[type], name)
538                 handles.append(handle)
539         return handles
540
541 def parseArgList (src):
542         typeNamePtrn    = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*'
543         args                    = []
544         for rawArg in src.split(','):
545                 m = re.search(typeNamePtrn, rawArg)
546                 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
547         return args
548
549 def removeTypeExtPostfix (name):
550         for extPostfix in EXTENSION_POSTFIXES_STANDARD:
551                 if endsWith(name, extPostfix):
552                         return name[0:-len(extPostfix)]
553         return None
554
555 def populateExtensionAliases(allObjects, extensionObjects):
556         for object in extensionObjects:
557                 withoutPostfix = removeTypeExtPostfix(object.name)
558                 if withoutPostfix != None and withoutPostfix in allObjects:
559                         # max 1 alias is assumed by functions in this file
560                         assert allObjects[withoutPostfix].alias == None
561                         allObjects[withoutPostfix].alias = object
562                         object.isAlias = True
563         for object in extensionObjects:
564                 object.checkAliasValidity()
565
566 def populateAliasesWithTypedefs (objects, src):
567         objectsByName = {}
568         for object in objects:
569                 objectsByName[object.name] = object
570                 ptrn    = r'\s*typedef\s+' + object.name + r'\s+([^;]+)'
571                 stash = re.findall(ptrn, src)
572                 if len(stash) == 1:
573                         objExt = copy.deepcopy(object)
574                         objExt.name = stash[0]
575                         object.alias = objExt
576                         objExt.isAlias = True
577                         objects.append(objExt)
578
579 def removeAliasedValues (enum):
580         valueByName = {}
581         for name, value in enum.values:
582                 valueByName[name] = value
583
584         def removeDefExtPostfix (name):
585                 for extPostfix in EXTENSION_POSTFIXES:
586                         if endsWith(name, "_" + extPostfix):
587                                 return name[0:-(len(extPostfix)+1)]
588                 return None
589
590         newValues = []
591         for name, value in enum.values:
592                 withoutPostfix = removeDefExtPostfix(name)
593                 if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value:
594                         continue
595                 newValues.append((name, value))
596         enum.values = newValues
597
598 def parseFunctions (src):
599         ptrn            = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
600         matches         = re.findall(ptrn, src)
601         functions       = []
602         for returnType, name, argList in matches:
603                 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
604         return functions
605
606 def parseFunctionsByVersion (src, versions):
607         # construct list of locations where version definitions start, and add the end of the file to it
608         sectionLocations = [versionDef[1] for versionDef in versions]
609         sectionLocations.append(len(src))
610
611         # construct function declaration pattern
612         ptrn            = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
613         regPtrn         = re.compile(ptrn)
614         functions       = []
615
616         # iterate over all versions and find all function definitions
617         for index, v in enumerate(versions):
618                 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
619                 for returnType, name, argList in matches:
620                         functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), v[0]))
621         return functions
622
623 def splitByExtension (src):
624         ptrn            = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
625         # Construct long pattern that will be used to split whole source by extensions
626         match           = "#define\s+("
627         for part in re.finditer(ptrn, src):
628                  match += part.group(1)+"|"
629         match = match[:-1] + ")\s+1"
630         parts = re.split(match, src)
631
632         # First part is core, following tuples contain extension name and all its definitions
633         byExtension     = [(None, parts[0])]
634         for ndx in range(1, len(parts), 2):
635                 byExtension.append((parts[ndx], parts[ndx+1]))
636         return byExtension
637
638 def parseDefinitions (extensionName, src):
639
640         def skipDefinition (extensionName, definition):
641                 if extensionName == None:
642                         return True
643                 extNameUpper = extensionName.upper()
644                 extNameUpper = extNameUpper.replace("VK_KHR_SYNCHRONIZATION2", "VK_KHR_SYNCHRONIZATION_2")
645                 extNameUpper = extNameUpper.replace("VK_INTEL_SHADER_INTEGER_FUNCTIONS2", "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2")
646                 extNameUpper = extNameUpper.replace("VK_EXT_ROBUSTNESS2", "VK_EXT_ROBUSTNESS_2")
647                 extNameUpper = extNameUpper.replace("VK_EXT_FRAGMENT_DENSITY_MAP2", "VK_EXT_FRAGMENT_DENSITY_MAP_2")
648                 extNameUpper = extNameUpper.replace("VK_AMD_SHADER_CORE_PROPERTIES2", "VK_AMD_SHADER_CORE_PROPERTIES_2")
649                 extNameUpper = extNameUpper.replace("VK_EXT_EXTENDED_DYNAMIC_STATE2", "VK_EXT_EXTENDED_DYNAMIC_STATE_2")
650                 # SPEC_VERSION enums
651                 if definition[0].startswith(extNameUpper) and definition[1].isdigit():
652                         return False
653                 if definition[0].startswith(extNameUpper):
654                         return True
655                 if definition[1].isdigit():
656                         return True
657                 return False
658
659         ptrn            = r'#define\s+([^\s]+)\s+([^\r\n]+)'
660         matches         = re.findall(ptrn, src)
661
662         return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)]
663
664 def parseTypedefs (src):
665
666         ptrn            = r'typedef\s+([^\s]+)\s+([^\r\n]+);'
667         matches         = re.findall(ptrn, src)
668
669         return [Definition(None, match[0], match[1]) for match in matches]
670
671 def parseExtensions (src, versions, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions):
672
673         def getCoreVersion (extensionName, extensionsData):
674                 # returns None when extension was not added to core for any Vulkan version
675                 # returns array containing DEVICE or INSTANCE string followed by the vulkan version in which this extension is core
676                 # note that this function is also called for vulkan 1.0 source for which extName is None
677                 if not extensionName:
678                         return None
679                 ptrn            = extensionName + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)'
680                 coreVersion = re.search(ptrn, extensionsData, re.I)
681                 if coreVersion != None:
682                         return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]]
683                 return None
684
685         extensionsData                  = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
686         splitSrc                                = splitByExtension(src)
687         extensions                              = []
688         functionsByName                 = {function.name: function for function in allFunctions}
689         compositeTypesByName    = {compType.name: compType for compType in allCompositeTypes}
690         enumsByName                             = {enum.name: enum for enum in allEnums}
691         bitfieldsByName                 = {bitfield.name: bitfield for bitfield in allBitfields}
692         handlesByName                   = {handle.name: handle for handle in allHandles}
693         definitionsByName               = {definition.name: definition for definition in allDefinitions}
694
695         for extensionName, extensionSrc in splitSrc:
696                 definitions                     = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValueOptional(extensionSrc, v.getInHex())) for v in versions]
697                 definitions.extend([Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS])
698                 definitions                     = [definition for definition in definitions if definition.value != None]
699                 additionalDefinitions = parseDefinitions(extensionName, extensionSrc)
700                 handles                         = parseHandles(extensionSrc)
701                 functions                       = parseFunctions(extensionSrc)
702                 compositeTypes          = parseCompositeTypes(extensionSrc)
703                 rawEnums                        = parseEnums(extensionSrc)
704                 bitfieldNames           = parseBitfieldNames(extensionSrc)
705                 typedefs                        = parseTypedefs(extensionSrc)
706                 enumBitfieldNames       = [getBitEnumNameForBitfield(name) for name in bitfieldNames]
707                 enums                           = [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
708
709                 extCoreVersion          = getCoreVersion(extensionName, extensionsData)
710                 extFunctions            = [functionsByName[function.name] for function in functions]
711                 extCompositeTypes       = [compositeTypesByName[compositeType.name] for compositeType in compositeTypes]
712                 extEnums                        = [enumsByName[enum.name] for enum in enums]
713                 extBitfields            = [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames]
714                 extHandles                      = [handlesByName[handle.name] for handle in handles]
715                 extDefinitions          = [definitionsByName[definition.name] for definition in definitions]
716
717                 if extCoreVersion != None:
718                         populateExtensionAliases(functionsByName, extFunctions)
719                         populateExtensionAliases(handlesByName, extHandles)
720                         populateExtensionAliases(enumsByName, extEnums)
721                         populateExtensionAliases(bitfieldsByName, extBitfields)
722                         populateExtensionAliases(compositeTypesByName, extCompositeTypes)
723                 extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, typedefs, extCoreVersion))
724         return extensions
725
726 def parseBitfieldNames (src):
727         ptrn            = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
728         matches         = re.findall(ptrn, src)
729
730         return matches
731
732 def parse64bitBitfieldNames (src):
733         ptrn            = r'typedef\s+VkFlags64\s(' + IDENT_PTRN + r')\s*;'
734         matches         = re.findall(ptrn, src)
735
736         return matches
737
738 def parse64bitBitfieldValues (src, bitfieldNamesList):
739
740         bitfields64 = []
741         for bitfieldName in bitfieldNamesList:
742                 ptrn            = r'static const ' + bitfieldName + r'\s*(' + IDENT_PTRN + r')\s*=\s*([a-zA-Z0-9_]+)\s*;'
743                 matches         = re.findall(ptrn, src)
744                 bitfields64.append(Bitfield(bitfieldName, matches))
745
746         return bitfields64
747
748 def parseAPI (src):
749         versionsData    = parseVersions(src)
750         versions                = [Version((v[2], v[3], 0)) for v in versionsData]
751         definitions             = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValue(src, v.getInHex())) for v in versions] +\
752                                           [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
753
754         handles                         = parseHandles(src)
755         rawEnums                        = parseEnums(src)
756         bitfieldNames           = parseBitfieldNames(src)
757         bitfieldEnums           = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
758         bitfield64Names         = parse64bitBitfieldNames(src)
759         bitfields64                     = parse64bitBitfieldValues(src, bitfield64Names)
760         enums                           = []
761         bitfields                       = []
762         compositeTypes          = parseCompositeTypesByVersion(src, versionsData)
763         allFunctions            = parseFunctionsByVersion(src, versionsData)
764
765         for enum in rawEnums:
766                 if enum.name in bitfieldEnums:
767                         bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
768                 else:
769                         enums.append(enum)
770
771         for bitfieldName in bitfieldNames:
772                 if not bitfieldName in [bitfield.name for bitfield in bitfields]:
773                         # Add empty bitfield
774                         bitfields.append(Bitfield(bitfieldName, []))
775
776         extensions = parseExtensions(src, versions, allFunctions, compositeTypes, enums, bitfields, handles, definitions)
777
778         # Populate alias fields
779         populateAliasesWithTypedefs(compositeTypes, src)
780         populateAliasesWithTypedefs(enums, src)
781         populateAliasesWithTypedefs(bitfields, src)
782         populateAliasesWithTypedefs(handles, src)
783
784         for enum in enums:
785                 removeAliasedValues(enum)
786
787         # Make generator to create Deleter<VkAccelerationStructureNV>
788         for f in allFunctions:
789                 if (f.name == 'vkDestroyAccelerationStructureNV'):
790                         f.arguments[1].type[0] = 'VkAccelerationStructureNV'
791
792         # Dealias handles VkAccelerationStructureNV and VkAccelerationStructureKHR
793         for handle in handles:
794                 if handle.name == 'VkAccelerationStructureKHR':
795                         handle.alias = None
796                 if handle.name == 'VkAccelerationStructureNV':
797                         handle.isAlias = False
798         return API(
799                 versions                = versions,
800                 definitions             = definitions,
801                 handles                 = handles,
802                 enums                   = enums,
803                 bitfields               = bitfields,
804                 bitfields64             = bitfields64,
805                 compositeTypes  = compositeTypes,
806                 functions               = allFunctions,
807                 extensions              = extensions)
808
809 def splitUniqueAndDuplicatedEntries (handles):
810         listOfUniqueHandles = []
811         duplicates                      = OrderedDict()
812         for handle in handles:
813                 if handle.alias != None:
814                         duplicates[handle.alias] = handle
815                 if not handle.isAlias:
816                         listOfUniqueHandles.append(handle)
817         return listOfUniqueHandles, duplicates
818
819 def writeHandleType (api, filename):
820         uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles)
821
822         def genHandles ():
823                 yield "\t%s\t= 0," % uniqeHandles[0].getHandleType()
824                 for handle in uniqeHandles[1:]:
825                         yield "\t%s," % handle.getHandleType()
826                 for duplicate in duplicatedHandles:
827                         yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType())
828                 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType())
829
830         def genHandlesBlock ():
831                 yield "enum HandleType"
832                 yield "{"
833
834                 for line in indentLines(genHandles()):
835                         yield line
836
837                 yield "};"
838                 yield ""
839
840         writeInlFile(filename, INL_HEADER, genHandlesBlock())
841
842 def getEnumValuePrefix (enum):
843         prefix = enum.name[0]
844         for i in range(1, len(enum.name)):
845                 if enum.name[i].isupper() and not enum.name[i-1].isupper():
846                         prefix += "_"
847                 prefix += enum.name[i].upper()
848         return prefix
849
850 def parseInt (value):
851         if value[:2] == "0x":
852                 return int(value, 16)
853         else:
854                 return int(value, 10)
855
856 def areEnumValuesLinear (enum):
857         curIndex = 0
858         for name, value in enum.values:
859                 if value[:2] != "VK":
860                         intValue = parseInt(value)
861                         if intValue != curIndex:
862                                 # consider enums containing *_MAX_ENUM = 0x7FFFFFFF as linear
863                                 if intValue == 0x7FFFFFFF:
864                                         return True
865                                 return False
866                         curIndex += 1
867         return True
868
869 def genEnumSrc (enum):
870         yield "enum %s" % enum.name
871         yield "{"
872
873         lines = ["\t%s\t= %s," % v for v in enum.values]
874         if areEnumValuesLinear(enum):
875                 lastItem = "\t%s_LAST," % getEnumValuePrefix(enum)
876                 if parseInt(enum.values[-1][1]) == 0x7FFFFFFF:
877                         # if last enum item is *_MAX_ENUM then we need to make sure
878                         # it stays last entry also if we append *_LAST to generated
879                         # source (without this value of *_LAST won't be correct)
880                         lines.insert(-1, lastItem)
881                 else:
882                         lines.append(lastItem)
883
884         for line in indentLines(lines):
885                 yield line
886
887         yield "};"
888
889 def genBitfieldSrc (bitfield):
890         if len(bitfield.values) > 0:
891                 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
892                 yield "{"
893                 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
894                         yield line
895                 yield "};"
896         yield "typedef uint32_t %s;" % bitfield.name
897
898 def genBitfield64Src (bitfield64):
899         yield "typedef deUint64 %s;" % bitfield64.name
900         if len(bitfield64.values) > 0:
901                 ptrn = "static const " + bitfield64.name + " %s\t= %s;"
902                 for line in indentLines([ptrn % v for v in bitfield64.values]):
903                         yield line
904                 yield ""
905
906 def genCompositeTypeSrc (type):
907         yield "%s %s" % (type.getClassName(), type.name)
908         yield "{"
909         for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]):
910                 yield line
911         yield "};"
912
913 def genHandlesSrc (handles):
914         uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles)
915
916         def genLines (handles):
917                 for handle in uniqeHandles:
918                         if handle.type == Handle.TYPE_DISP:
919                                 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
920                         elif handle.type == Handle.TYPE_NONDISP:
921                                 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
922
923                 for duplicate in duplicatedHandles:
924                         if duplicate.type == Handle.TYPE_DISP:
925                                 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
926                         elif duplicate.type == Handle.TYPE_NONDISP:
927                                 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
928
929         for line in indentLines(genLines(handles)):
930                 yield line
931
932 def stripTrailingComment(str):
933         index = str.find("//")
934         if index == -1:
935                 return str
936         return str[:index]
937
938 def genDefinitionsSrc (definitions):
939         for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, stripTrailingComment(definition.value)) for definition in definitions]:
940                 yield line
941
942 def genDefinitionsAliasSrc (definitions):
943         for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]:
944                 if definition.value != definitions[definition].value and definition.value != definitions[definition].name:
945                         raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value))
946                 yield line
947
948 def genMaxFrameworkVersion (definitions):
949         maxApiVersionMajor = 1
950         maxApiVersionMinor = 0
951         for definition in definitions:
952                 match = re.match("VK_API_VERSION_(\d+)_(\d+)", definition.name)
953                 if match:
954                         apiVersionMajor = int(match.group(1))
955                         apiVersionMinor = int(match.group(2))
956                         if apiVersionMajor > maxApiVersionMajor:
957                                 maxApiVersionMajor = apiVersionMajor
958                                 maxApiVersionMinor = apiVersionMinor
959                         elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
960                                 maxApiVersionMinor = apiVersionMinor
961         yield "#define VK_API_MAX_FRAMEWORK_VERSION\tVK_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
962
963 def writeBasicTypes (api, filename):
964
965         def gen ():
966                 definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
967
968                 for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
969                         yield line
970                 yield ""
971
972                 for line in genHandlesSrc(api.handles):
973                         yield line
974                 yield ""
975
976                 for enum in api.enums:
977                         if not enum.isAlias:
978                                 for line in genEnumSrc(enum):
979                                         yield line
980                         else:
981                                 for enum2 in api.enums:
982                                         if enum2.alias == enum:
983                                                 yield "typedef %s %s;" % (enum2.name, enum.name)
984                         yield ""
985
986                 for bitfield in api.bitfields:
987                         if not bitfield.isAlias:
988                                 for line in genBitfieldSrc(bitfield):
989                                         yield line
990                         else:
991                                 for bitfield2 in api.bitfields:
992                                         if bitfield2.alias == bitfield:
993                                                 yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
994                         yield ""
995
996                 for bitfield64 in api.bitfields64:
997                         for line in genBitfield64Src(bitfield64):
998                                 yield line
999
1000                 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
1001                         yield line
1002
1003                 for ext in api.extensions:
1004                         if ext.additionalDefs != None:
1005                                 for definition in ext.additionalDefs:
1006                                         yield "#define " + definition.name + " " + definition.value
1007
1008         writeInlFile(filename, INL_HEADER, gen())
1009
1010 def writeCompositeTypes (api, filename):
1011         def gen ():
1012                 for type in api.compositeTypes:
1013                         type.checkAliasValidity()
1014
1015                         if not type.isAlias:
1016                                 for line in genCompositeTypeSrc(type):
1017                                         yield line
1018                         else:
1019                                 for type2 in api.compositeTypes:
1020                                         if type2.alias == type:
1021                                                 yield "typedef %s %s;" % (type2.name, type.name)
1022                         yield ""
1023
1024         writeInlFile(filename, INL_HEADER, gen())
1025
1026 def argListToStr (args):
1027         return ", ".join(v.getAsStringForArgumentList(' ') for v in args)
1028
1029 def writeInterfaceDecl (api, filename, functionTypes, concrete):
1030         def genProtos ():
1031                 postfix = "" if concrete else " = 0"
1032                 for function in api.functions:
1033                         if not function.getType() in functionTypes:
1034                                 continue
1035                         if not function.isAlias:
1036                                 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
1037
1038         writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1039
1040 def writeFunctionPtrTypes (api, filename):
1041         def genTypes ():
1042                 for function in api.functions:
1043                         yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
1044
1045         writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1046
1047 def writeFunctionPointers (api, filename, functionTypes):
1048         def FunctionsYielder ():
1049                 for function in api.functions:
1050                         if function.getType() in functionTypes:
1051                                 if function.isAlias:
1052                                         if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1053                                                 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1054                                 else:
1055                                         yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1056
1057         writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1058
1059 def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1060         def makeInitFunctionPointers ():
1061                 for function in api.functions:
1062                         if function.getType() in functionTypes and (cond == None or cond(function)):
1063                                 interfaceName = getInterfaceName(function)
1064                                 if function.isAlias:
1065                                         if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1066                                                 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1067                                 else:
1068                                         yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1069                                         if function.alias != None:
1070                                                 yield "if (!m_vk.%s)" % (getInterfaceName(function))
1071                                                 yield "    m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name)
1072         lines = [line.replace('    ', '\t') for line in indentLines(makeInitFunctionPointers())]
1073         writeInlFile(filename, INL_HEADER, lines)
1074
1075 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1076         def makeFuncPtrInterfaceImpl ():
1077                 for function in api.functions:
1078                         if function.getType() in functionTypes and not function.isAlias:
1079                                 yield ""
1080                                 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
1081                                 yield "{"
1082                                 if function.name == "vkEnumerateInstanceVersion":
1083                                         yield " if (m_vk.enumerateInstanceVersion)"
1084                                         yield "         return m_vk.enumerateInstanceVersion(pApiVersion);"
1085                                         yield ""
1086                                         yield " *pApiVersion = VK_API_VERSION_1_0;"
1087                                         yield " return VK_SUCCESS;"
1088                                 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None:
1089                                         yield " vk::VkPhysicalDeviceProperties props;"
1090                                         yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1091                                         yield " if (props.apiVersion >= VK_API_VERSION_1_1)"
1092                                         yield "         %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1093                                         yield " else"
1094                                         yield "         %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments))
1095                                 else:
1096                                         yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1097                                 yield "}"
1098
1099         writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1100
1101 def writeStrUtilProto (api, filename):
1102         def makeStrUtilProto ():
1103                 for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums if not enum.isAlias]):
1104                         yield line
1105                 yield ""
1106                 for line in indentLines(["inline tcu::Format::Enum<%s>\tget%sStr\t(%s value)\t{ return tcu::Format::Enum<%s>(get%sName, value);\t}" % (e.name, e.name[2:], e.name, e.name, e.name[2:]) for e in api.enums if not e.isAlias]):
1107                         yield line
1108                 yield ""
1109                 for line in indentLines(["inline std::ostream&\toperator<<\t(std::ostream& s, %s value)\t{ return s << get%sStr(value);\t}" % (e.name, e.name[2:]) for e in api.enums if not e.isAlias]):
1110                         yield line
1111                 yield ""
1112                 for line in indentLines(["tcu::Format::Bitfield<32>\tget%sStr\t(%s value);" % (bitfield.name[2:], bitfield.name) for bitfield in api.bitfields if not bitfield.isAlias or bitfield.name=='VkBuildAccelerationStructureFlagsNV']):
1113                         yield line
1114                 yield ""
1115                 for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes if not s.isAlias]):
1116                         yield line
1117
1118         writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1119
1120 def writeStrUtilImpl (api, filename):
1121         def makeStrUtilImpl ():
1122                 for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles if not handle.isAlias]):
1123                         yield line
1124
1125                 yield ""
1126                 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1127                 yield "{"
1128
1129                 for line in indentLines("std::ostream& operator<< (std::ostream& s, %s\tv) { return s << tcu::toHex(v.internal); }" % ''.join(s) for n, s, c in PLATFORM_TYPES):
1130                         yield line
1131
1132                 yield "}"
1133
1134                 for enum in api.enums:
1135                         if enum.isAlias:
1136                                 continue
1137                         yield ""
1138                         yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1139                         yield "{"
1140                         yield "\tswitch (value)"
1141                         yield "\t{"
1142                         for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values if v[:2] != "VK"] + ["\t\tdefault:\treturn DE_NULL;"]):
1143                                 yield line
1144                         yield "\t}"
1145                         yield "}"
1146
1147                 for bitfield in api.bitfields:
1148                         if bitfield.isAlias:
1149                                 if bitfield.name != 'VkBuildAccelerationStructureFlagsNV':
1150                                         continue
1151                         yield ""
1152                         yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
1153                         yield "{"
1154
1155                         if len(bitfield.values) > 0:
1156                                 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1157                                 yield "\t{"
1158                                 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
1159                                         yield line
1160                                 yield "\t};"
1161                                 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1162                         else:
1163                                 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
1164                         yield "}"
1165
1166                 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
1167
1168                 for type in api.compositeTypes:
1169                         if not type.isAlias:
1170                                 yield ""
1171                                 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1172                                 yield "{"
1173                                 yield "\ts << \"%s = {\\n\";" % type.name
1174                                 for member in type.members:
1175                                         memberName      = member.name
1176                                         valFmt          = None
1177                                         newLine         = ""
1178                                         if member.getType() in bitfieldTypeNames:
1179                                                 valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name)
1180                                         elif member.getType() == "const char*" or member.getType() == "char*":
1181                                                 valFmt = "getCharPtrStr(value.%s)" % member.name
1182                                         elif member.getType() == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1183                                                 valFmt = "getWStr(value.%s)" % member.name
1184                                         elif member.arraySize != '':
1185                                                 singleDimensional = not '][' in member.arraySize
1186                                                 if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1187                                                         valFmt = "(const char*)value.%s" % member.name
1188                                                 elif singleDimensional and (member.getType() == 'char' or member.getType() == 'deUint8'):
1189                                                         newLine = "'\\n' << "
1190                                                         valFmt  = "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.getType(), member.name, member.getType(), member.name)
1191                                                 else:
1192                                                         if member.name == "memoryTypes" or member.name == "memoryHeaps":
1193                                                                 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1194                                                         else:
1195                                                                 endIter = "DE_ARRAY_END(value.%s)" % member.name
1196                                                         newLine = "'\\n' << "
1197                                                         valFmt  = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1198                                                 memberName = member.name
1199                                         else:
1200                                                 valFmt = "value.%s" % member.name
1201                                         yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1202                                 yield "\ts << '}';"
1203                                 yield "\treturn s;"
1204                                 yield "}"
1205         writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1206
1207
1208 def writeObjTypeImpl (api, filename):
1209         def makeObjTypeImpl ():
1210
1211                 yield "namespace vk"
1212                 yield "{"
1213
1214                 yield "template<typename T> VkObjectType getObjectType  (void);"
1215
1216                 for line in indentLines(["template<> inline VkObjectType\tgetObjectType<%s>\t(void) { return %s;\t}" % (handle.name, prefixName("VK_OBJECT_TYPE_", handle.name)) for handle in api.handles if not handle.isAlias]):
1217                         yield line
1218
1219                 yield "}"
1220
1221         writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1222
1223 class ConstructorFunction:
1224         def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1225                 self.type               = type
1226                 self.name               = name
1227                 self.objectType = objectType
1228                 self.ifaceArgs  = ifaceArgs
1229                 self.arguments  = arguments
1230
1231 def getConstructorFunctions (api):
1232         funcs = []
1233         ifacesDict = {
1234                 Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")],
1235                 Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")],
1236                 Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")]
1237         }
1238         for function in api.functions:
1239                 if function.isAlias:
1240                         continue
1241                 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1242                         if function.name == "vkCreateDisplayModeKHR":
1243                                 continue # No way to delete display modes (bug?)
1244
1245                         # \todo [pyry] Rather hacky
1246                         ifaceArgs = ifacesDict[function.getType()]
1247                         if function.name == "vkCreateDevice":
1248                                 ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs
1249
1250                         assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"])
1251
1252                         objectType      = function.arguments[-1].type[0] #not getType() but type[0] on purpose
1253                         arguments       = function.arguments[:-1]
1254                         funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments))
1255         return funcs
1256
1257 def addVersionDefines(versionSpectrum):
1258         output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1259         return output
1260
1261 def removeVersionDefines(versionSpectrum):
1262         output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()]
1263         return output
1264
1265 def writeRefUtilProto (api, filename):
1266         functions = getConstructorFunctions(api)
1267
1268         def makeRefUtilProto ():
1269                 unindented = []
1270                 for line in indentLines(["Move<%s>\t%s\t(%s = DE_NULL);" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments)) for function in functions]):
1271                         yield line
1272
1273         writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1274
1275 def writeRefUtilImpl (api, filename):
1276         functions = getConstructorFunctions(api)
1277
1278         def makeRefUtilImpl ():
1279                 yield "namespace refdetails"
1280                 yield "{"
1281                 yield ""
1282
1283                 for function in api.functions:
1284                         if function.getType() == Function.TYPE_DEVICE \
1285                         and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1286                         and not function.name == "vkDestroyDevice" \
1287                         and not function.isAlias:
1288                                 objectType = function.arguments[-2].getType()
1289                                 yield "template<>"
1290                                 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1291                                 yield "{"
1292                                 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
1293                                 yield "}"
1294                                 yield ""
1295
1296                 yield "} // refdetails"
1297                 yield ""
1298
1299                 dtorDict = {
1300                         Function.TYPE_PLATFORM: "object",
1301                         Function.TYPE_INSTANCE: "instance",
1302                         Function.TYPE_DEVICE: "device"
1303                 }
1304
1305                 for function in functions:
1306                         deleterArgsString = ''
1307                         if function.name == "createDevice":
1308                                 # createDevice requires two additional parameters to setup VkDevice deleter
1309                                 deleterArgsString = "vkp, instance, object, " +  function.arguments[-1].name
1310                         else:
1311                                 deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1312
1313                         yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1314                         yield "{"
1315                         yield "\t%s object = 0;" % function.objectType
1316                         yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1317                         yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1318                         yield "}"
1319                         yield ""
1320
1321         writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1322
1323 def writeStructTraitsImpl (api, filename):
1324         def gen ():
1325                 for type in api.compositeTypes:
1326                         if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias and type.name != "VkBaseOutStructure" and type.name != "VkBaseInStructure":
1327                                 yield "template<> VkStructureType getStructureType<%s> (void)" % type.name
1328                                 yield "{"
1329                                 yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name)
1330                                 yield "}"
1331                                 yield ""
1332
1333         writeInlFile(filename, INL_HEADER, gen())
1334
1335 def writeNullDriverImpl (api, filename):
1336         def genNullDriverImpl ():
1337                 specialFuncNames        = [
1338                                 "vkCreateGraphicsPipelines",
1339                                 "vkCreateComputePipelines",
1340                                 "vkCreateRayTracingPipelinesNV",
1341                                 "vkCreateRayTracingPipelinesKHR",
1342                                 "vkGetInstanceProcAddr",
1343                                 "vkGetDeviceProcAddr",
1344                                 "vkEnumeratePhysicalDevices",
1345                                 "vkEnumerateInstanceExtensionProperties",
1346                                 "vkEnumerateDeviceExtensionProperties",
1347                                 "vkGetPhysicalDeviceFeatures",
1348                                 "vkGetPhysicalDeviceFeatures2KHR",
1349                                 "vkGetPhysicalDeviceProperties",
1350                                 "vkGetPhysicalDeviceProperties2KHR",
1351                                 "vkGetPhysicalDeviceQueueFamilyProperties",
1352                                 "vkGetPhysicalDeviceMemoryProperties",
1353                                 "vkGetPhysicalDeviceFormatProperties",
1354                                 "vkGetPhysicalDeviceImageFormatProperties",
1355                                 "vkGetDeviceQueue",
1356                                 "vkGetBufferMemoryRequirements",
1357                                 "vkGetBufferMemoryRequirements2KHR",
1358                                 "vkGetImageMemoryRequirements",
1359                                 "vkGetImageMemoryRequirements2KHR",
1360                                 "vkAllocateMemory",
1361                                 "vkMapMemory",
1362                                 "vkUnmapMemory",
1363                                 "vkAllocateDescriptorSets",
1364                                 "vkFreeDescriptorSets",
1365                                 "vkResetDescriptorPool",
1366                                 "vkAllocateCommandBuffers",
1367                                 "vkFreeCommandBuffers",
1368                                 "vkCreateDisplayModeKHR",
1369                                 "vkCreateSharedSwapchainsKHR",
1370                                 "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1371                                 "vkGetPhysicalDeviceImageFormatProperties2KHR",
1372                                 "vkGetMemoryAndroidHardwareBufferANDROID",
1373                         ]
1374
1375                 coreFunctions           = [f for f in api.functions if not f.isAlias]
1376                 specialFuncs            = [f for f in coreFunctions if f.name in specialFuncNames]
1377                 createFuncs                     = [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1378                 destroyFuncs            = [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1379                 dummyFuncs                      = [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs]
1380
1381                 def getHandle (name):
1382                         for handle in api.handles:
1383                                 if handle.name == name[0]:
1384                                         return handle
1385                         raise Exception("No such handle: %s" % name)
1386
1387                 for function in createFuncs:
1388                         objectType      = function.arguments[-1].type[:-1]
1389                         argsStr         = ", ".join([a.name for a in function.arguments[:-1]])
1390
1391                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1392                         yield "{"
1393                         yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1394
1395                         if getHandle(objectType).type == Handle.TYPE_NONDISP:
1396                                 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1397                         else:
1398                                 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1399                         yield "}"
1400                         yield ""
1401
1402                 for function in destroyFuncs:
1403                         objectArg       = function.arguments[-2]
1404
1405                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1406                         yield "{"
1407                         for arg in function.arguments[:-2]:
1408                                 yield "\tDE_UNREF(%s);" % arg.name
1409
1410                         if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
1411                                 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1412                         else:
1413                                 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1414
1415                         yield "}"
1416                         yield ""
1417
1418                 for function in dummyFuncs:
1419                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1420                         yield "{"
1421                         for arg in function.arguments:
1422                                 yield "\tDE_UNREF(%s);" % arg.name
1423                         if function.returnType != "void":
1424                                 yield "\treturn VK_SUCCESS;"
1425                         yield "}"
1426                         yield ""
1427
1428                 def genFuncEntryTable (type, name):
1429                         funcs = [f for f in api.functions if f.getType() == type]
1430                         refFuncs = {}
1431                         for f in api.functions:
1432                                 if f.alias != None:
1433                                         refFuncs[f.alias] = f
1434
1435                         yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1436                         yield "{"
1437                         for line in indentLines(["\tVK_NULL_FUNC_ENTRY(%s,\t%s)," % (function.name, getInterfaceName(function if not function.isAlias else refFuncs[function])) for function in funcs]):
1438                                 yield line
1439                         yield "};"
1440                         yield ""
1441
1442                 # Func tables
1443                 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1444                         yield line
1445
1446                 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1447                         yield line
1448
1449                 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1450                         yield line
1451
1452         writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1453
1454 def writeTypeUtil (api, filename):
1455         # Structs filled by API queries are not often used in test code
1456         QUERY_RESULT_TYPES = set([
1457                         "VkPhysicalDeviceFeatures",
1458                         "VkPhysicalDeviceLimits",
1459                         "VkFormatProperties",
1460                         "VkImageFormatProperties",
1461                         "VkPhysicalDeviceSparseProperties",
1462                         "VkQueueFamilyProperties",
1463                         "VkMemoryType",
1464                         "VkMemoryHeap",
1465                         "StdVideoH264SpsVuiFlags",
1466                         "StdVideoH264SpsFlags",
1467                         "StdVideoH264PpsFlags",
1468                         "StdVideoDecodeH264PictureInfoFlags",
1469                         "StdVideoDecodeH264ReferenceInfoFlags",
1470                         "StdVideoDecodeH264MvcElementFlags",
1471                         "StdVideoEncodeH264SliceHeaderFlags",
1472                         "StdVideoEncodeH264PictureInfoFlags",
1473                         "StdVideoEncodeH264RefMgmtFlags",
1474                         "StdVideoH265HrdFlags",
1475                         "StdVideoH265VpsFlags",
1476                         "StdVideoH265SpsVuiFlags",
1477                         "StdVideoH265SpsFlags",
1478                         "StdVideoH265PpsFlags",
1479                         "StdVideoDecodeH265PictureInfoFlags",
1480                         "StdVideoDecodeH265ReferenceInfoFlags",
1481                         "StdVideoEncodeH265PictureInfoFlags"
1482                 ])
1483         COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias])
1484
1485         def isSimpleStruct (type):
1486                 def hasArrayMember (type):
1487                         for member in type.members:
1488                                 if member.arraySize != '':
1489                                         return True
1490                         return False
1491
1492                 def hasCompositeMember (type):
1493                         for member in type.members:
1494                                 if member.getType() in COMPOSITE_TYPES:
1495                                         return True
1496                         return False
1497
1498                 return type.typeClass == CompositeType.CLASS_STRUCT and \
1499                 type.members[0].getType() != "VkStructureType" and \
1500                 not type.name in QUERY_RESULT_TYPES and \
1501                 not hasArrayMember(type) and \
1502                 not hasCompositeMember(type)
1503
1504         def gen ():
1505                 for type in api.compositeTypes:
1506                         if not isSimpleStruct(type) or type.isAlias:
1507                                 continue
1508
1509                         name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
1510
1511                         yield ""
1512                         yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
1513                         yield "{"
1514                         yield "\t%s res;" % type.name
1515                         for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1516                                 yield line
1517                         yield "\treturn res;"
1518                         yield "}"
1519
1520         writeInlFile(filename, INL_HEADER, gen())
1521
1522 def writeDriverIds(filename):
1523
1524         driverIdsString = []
1525         driverIdsString.append("static const struct\n"
1526                                          "{\n"
1527                                          "\tstd::string driver;\n"
1528                                          "\tuint32_t id;\n"
1529                                          "} driverIds [] =\n"
1530                                          "{")
1531
1532         vulkanCore = readFile(os.path.join(VULKAN_H_DIR, "vulkan_core.h"))
1533
1534         items = re.search(r'(?:typedef\s+enum\s+VkDriverId\s*{)((.*\n)*)(?:}\s*VkDriverId\s*;)', vulkanCore).group(1).split(',')
1535         driverItems = dict()
1536         for item in items:
1537                 item.strip()
1538                 splitted = item.split('=')
1539                 key = splitted[0].strip()
1540                 value_str = splitted[1].strip()
1541                 try: # is this previously defined value?
1542                         value = driverItems[value_str]
1543                 except:
1544                         value = value_str
1545                         value_str = ""
1546                 if value_str:
1547                         value_str = "\t// " + value_str
1548                 driverItems[key] = value
1549                 if not item == items[-1]:
1550                         driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}," + value_str)
1551                 else:
1552                         driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}" + value_str)
1553                 driverItems[key] = value
1554
1555         driverIdsString.append("};")
1556
1557         writeInlFile(filename, INL_HEADER, driverIdsString)
1558
1559
1560 def writeSupportedExtenions(api, filename):
1561
1562         def writeExtensionsForVersions(map):
1563                 result = []
1564                 for version in map:
1565                         result.append(" if (coreVersion >= " + str(version) + ")")
1566                         result.append(" {")
1567                         for extension in map[version]:
1568                                 result.append('         dst.push_back("' + extension.name + '");')
1569                         result.append(" }")
1570
1571                 return result
1572
1573         instanceMap             = {}
1574         deviceMap               = {}
1575         versionSet              = set()
1576
1577         for ext in api.extensions:
1578                 if ext.versionInCore != None:
1579                         if ext.versionInCore[0] == 'INSTANCE':
1580                                 list = instanceMap.get(Version(ext.versionInCore[1:]))
1581                                 instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1582                         else:
1583                                 list = deviceMap.get(Version(ext.versionInCore[1:]))
1584                                 deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1585                         versionSet.add(Version(ext.versionInCore[1:]))
1586
1587         lines = addVersionDefines(versionSet) + [
1588         "",
1589         "void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""),
1590         "{"] + writeExtensionsForVersions(deviceMap) + [
1591         "}",
1592         "",
1593         "void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""),
1594         "{"] + writeExtensionsForVersions(instanceMap) + [
1595         "}",
1596         ""] + removeVersionDefines(versionSet)
1597         writeInlFile(filename, INL_HEADER, lines)
1598
1599 def writeExtensionFunctions (api, filename):
1600
1601         def isInstanceExtension (ext):
1602                 if ext.name and ext.functions:
1603                         if ext.functions[0].getType() == Function.TYPE_INSTANCE:
1604                                 return True
1605                         else:
1606                                 return False
1607
1608         def isDeviceExtension (ext):
1609                 if ext.name and ext.functions:
1610                         if ext.functions[0].getType() == Function.TYPE_DEVICE:
1611                                 return True
1612                         else:
1613                                 return False
1614
1615         def writeExtensionNameArrays ():
1616                 instanceExtensionNames = []
1617                 deviceExtensionNames = []
1618                 for ext in api.extensions:
1619                         if ext.name and isInstanceExtension(ext):
1620                                 instanceExtensionNames += [ext.name]
1621                         elif ext.name and isDeviceExtension(ext):
1622                                 deviceExtensionNames += [ext.name]
1623                 yield '::std::string instanceExtensionNames[] =\n{'
1624                 for instanceExtName in instanceExtensionNames:
1625                         if (instanceExtName == instanceExtensionNames[len(instanceExtensionNames) - 1]):
1626                                 yield '\t"%s"' % instanceExtName
1627                         else:
1628                                 yield '\t"%s",' % instanceExtName
1629                 yield '};\n'
1630                 yield '::std::string deviceExtensionNames[] =\n{'
1631                 for deviceExtName in deviceExtensionNames:
1632                         if (deviceExtName == deviceExtensionNames[len(deviceExtensionNames) - 1]):
1633                                 yield '\t"%s"' % deviceExtName
1634                         else:
1635                                 yield '\t"%s",' % deviceExtName
1636                 yield '};'
1637
1638         def writeExtensionFunctions (functionType):
1639                 isFirstWrite = True
1640                 dg_list = []    # Device groups functions need special casing, as Vulkan 1.0 keeps them in VK_KHR_device_groups whereas 1.1 moved them into VK_KHR_swapchain
1641                 if functionType == Function.TYPE_INSTANCE:
1642                         yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1643                         dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
1644                 elif functionType == Function.TYPE_DEVICE:
1645                         yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1646                         dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
1647                 for ext in api.extensions:
1648                         funcNames = []
1649                         if ext.name:
1650                                 for func in ext.functions:
1651                                         if func.getType() == functionType:
1652                                                 # only add functions with same vendor as extension
1653                                                 # this is a workaroudn for entrypoints requiring more
1654                                                 # than one excetions and lack of the dependency in vulkan_core.h
1655                                                 vendor = ext.name.split('_')[1]
1656                                                 if func.name.endswith(vendor):
1657                                                         funcNames.append(func.name)
1658                         if ext.name:
1659                                 yield '\tif (extName == "%s")' % ext.name
1660                                 yield '\t{'
1661                                 for funcName in funcNames:
1662                                         if funcName in dg_list:
1663                                                 yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
1664                                         else:
1665                                                 yield '\t\tfunctions.push_back("%s");' % funcName
1666                                 if ext.name == "VK_KHR_device_group":
1667                                         for dg_func in dg_list:
1668                                                 yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
1669                                 yield '\t\treturn;'
1670                                 yield '\t}'
1671                                 isFirstWrite = False
1672                 if not isFirstWrite:
1673                         yield '\tDE_FATAL("Extension name not found");'
1674                         yield '}'
1675
1676         lines = ['']
1677         for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
1678                 lines += [line]
1679         lines += ['']
1680         for line in writeExtensionFunctions(Function.TYPE_DEVICE):
1681                 lines += [line]
1682         lines += ['']
1683         for line in writeExtensionNameArrays():
1684                 lines += [line]
1685
1686         writeInlFile(filename, INL_HEADER, lines)
1687
1688 def writeCoreFunctionalities(api, filename):
1689         functionOriginValues    = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1690         lines                                   = addVersionDefines(api.versions) + [
1691         "",
1692         'enum FunctionOrigin', '{'] + [line for line in indentLines([
1693         '\t' + functionOriginValues[0] + '\t= 0,',
1694         '\t' + functionOriginValues[1] + ',',
1695         '\t' + functionOriginValues[2]])] + [
1696         "};",
1697         "",
1698         "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1699         "typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1700         "typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;",
1701         "",
1702         "void initApisMap (ApisMap& apis)",
1703         "{",
1704         "       apis.clear();"] + [
1705         "       apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + str(v) + ", FunctionInfosList()));" for v in api.versions] + [
1706         ""]
1707
1708         apiVersions = []
1709         for index, v in enumerate(api.versions):
1710                 funcs = []
1711                 apiVersions.append("VK_VERSION_{0}_{1}".format(v.major, v.minor))
1712                 # iterate over all functions that are core in latest vulkan version
1713                 # note that first item in api.extension array are actually all definitions that are in vulkan.h.in before section with extensions
1714                 for fun in api.extensions[0].functions:
1715                         if fun.apiVersion in apiVersions:
1716                                 funcs.append('  apis[' + str(v) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));')
1717                 lines = lines + [line for line in indentLines(funcs)] + [""]
1718
1719         lines = lines + ["}", ""] + removeVersionDefines(api.versions)
1720         writeInlFile(filename, INL_HEADER, lines)
1721
1722 def writeDeviceFeatures2(api, filename):
1723         # list of structures that should be tested with getPhysicalDeviceFeatures2
1724         # this is not posible to determine from vulkan_core.h, if new feature structures
1725         # are added they should be manualy added to this list
1726         testedStructures = [
1727                 'VkPhysicalDeviceConditionalRenderingFeaturesEXT',
1728                 'VkPhysicalDeviceScalarBlockLayoutFeatures',
1729                 'VkPhysicalDevicePerformanceQueryFeaturesKHR',
1730                 'VkPhysicalDevice16BitStorageFeatures',
1731                 'VkPhysicalDeviceMultiviewFeatures',
1732                 'VkPhysicalDeviceProtectedMemoryFeatures',
1733                 'VkPhysicalDeviceSamplerYcbcrConversionFeatures',
1734                 'VkPhysicalDeviceVariablePointersFeatures',
1735                 'VkPhysicalDevice8BitStorageFeatures',
1736                 'VkPhysicalDeviceShaderAtomicInt64Features',
1737                 'VkPhysicalDeviceShaderFloat16Int8Features',
1738                 'VkPhysicalDeviceBufferDeviceAddressFeaturesEXT',
1739                 'VkPhysicalDeviceBufferDeviceAddressFeatures',
1740                 'VkPhysicalDeviceDescriptorIndexingFeatures',
1741                 'VkPhysicalDeviceTimelineSemaphoreFeatures',
1742                 'VkPhysicalDeviceFragmentDensityMapFeaturesEXT',
1743                 'VkPhysicalDeviceFragmentDensityMap2FeaturesEXT'
1744         ]
1745         # helper class used to encapsulate all data needed during generation
1746         class StructureDetail:
1747                 def __init__ (self, name):
1748                         nameResult                      = re.search('(.*)Features(.*)', name[len('VkPhysicalDevice'):])
1749                         nameSplitUp                     = ''
1750                         # generate structure type name from structure name
1751                         # note that sometimes digits are separated with '_':
1752                         # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT
1753                         # but mostly they are not:
1754                         # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES
1755                         if (nameResult.group(1) == 'FragmentDensityMap2'):
1756                                 nameSplitUp             = ['FRAGMENT', 'DENSITY', 'MAP', '2', 'FEATURES']
1757                         else:
1758                                 nameSplit               = re.findall(r'[1-9A-Z]+(?:[a-z1-9]+|[A-Z]*(?=[A-Z]|$))', nameResult.group(1))
1759                                 nameSplitUp             = map(str.upper, nameSplit)
1760                                 nameSplitUp             = list(nameSplitUp) + ['FEATURES']
1761                         # check if there is extension suffix
1762                         if (len(nameResult.group(2)) != 0):
1763                                 nameSplitUp.append(nameResult.group(2))
1764                         self.name                       = name
1765                         self.sType                      = 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_' + '_'.join(nameSplitUp)
1766                         self.instanceName       = 'd' + name[11:]
1767                         self.flagName           = 'is' + name[16:]
1768                         self.extension          = None
1769                         self.major                      = None
1770                         self.minor                      = None
1771                         self.members            = []
1772         # helper extension class used in algorith below
1773         class StructureFoundContinueToNextOne(Exception):
1774                 pass
1775         testedStructureDetail = [StructureDetail(struct) for struct in testedStructures]
1776         # iterate over all searched structures and find extensions that enable them
1777         for structureDetail in testedStructureDetail:
1778                 try:
1779                         # iterate over all extensions
1780                         for extension in api.extensions[1:]:
1781                                 # check composite types and typedefs in case extension is part of core
1782                                 for structureList in [extension.compositeTypes, extension.typedefs]:
1783                                         # iterate over all structures added by extension
1784                                         for extensionStructure in structureList:
1785                                                 # compare checked structure name to name of structure from extension
1786                                                 if structureDetail.name == extensionStructure.name:
1787                                                         structureDetail.extension = extension.name
1788                                                         if extension.versionInCore is not None:
1789                                                                 structureDetail.major = extension.versionInCore[1]
1790                                                                 structureDetail.minor = extension.versionInCore[2]
1791                                                         raise StructureFoundContinueToNextOne
1792                 except StructureFoundContinueToNextOne:
1793                         continue
1794         for structureDetail in testedStructureDetail:
1795                 for compositeType in api.compositeTypes:
1796                         if structureDetail.name != compositeType.name:
1797                                 continue
1798                         structureMembers = compositeType.members[2:]
1799                         structureDetail.members = [m.name for m in structureMembers]
1800                         if structureDetail.major is not None:
1801                                 break
1802                         # if structure was not added with extension then check if
1803                         # it was added directly with one of vulkan versions
1804                         apiVersion = compositeType.apiVersion
1805                         if apiVersion is None:
1806                                 continue
1807                         structureDetail.major = apiVersion.major
1808                         structureDetail.minor = apiVersion.minor
1809                         break
1810         # generate file content
1811         structureDefinitions = []
1812         featureEnabledFlags = []
1813         clearStructures = []
1814         structureChain = []
1815         logStructures = []
1816         verifyStructures = []
1817         for index, structureDetail in enumerate(testedStructureDetail):
1818                 # create two instances of each structure
1819                 nameSpacing = '\t' * int((55 - len(structureDetail.name)) / 4)
1820                 structureDefinitions.append(structureDetail.name + nameSpacing + structureDetail.instanceName + '[count];')
1821                 # create flags that check if proper extension or vulkan version is available
1822                 condition       = ''
1823                 extension       = structureDetail.extension
1824                 major           = structureDetail.major
1825                 if extension is not None:
1826                         condition = ' checkExtension(properties, "' + extension + '")'
1827                 if major is not None:
1828                         if condition != '':
1829                                 condition += '\t' * int((39 - len(extension)) / 4) + '|| '
1830                         else:
1831                                 condition += '\t' * 17 + '   '
1832                         condition += 'context.contextSupports(vk::ApiVersion(' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
1833                 condition += ';'
1834                 nameSpacing = '\t' * int((40 - len(structureDetail.flagName)) / 4)
1835                 featureEnabledFlags.append('const bool ' + structureDetail.flagName + nameSpacing + '=' + condition)
1836                 # clear memory of each structure
1837                 nameSpacing = '\t' * int((43 - len(structureDetail.instanceName)) / 4)
1838                 clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx],' + nameSpacing + '0xFF * ndx, sizeof(' + structureDetail.name + '));')
1839                 # construct structure chain
1840                 nextInstanceName = 'DE_NULL';
1841                 if index < len(testedStructureDetail)-1:
1842                         nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
1843                 structureChain.append('\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.sType + ';')
1844                 structureChain.append('\t' + structureDetail.instanceName + '[ndx].pNext = ' + nextInstanceName + ';\n')
1845                 # construct log section
1846                 logStructures.append('if (' + structureDetail.flagName + ')')
1847                 logStructures.append('\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;')
1848                 #construct verification section
1849                 verifyStructures.append('if (' + structureDetail.flagName + ' &&')
1850                 for index, m in enumerate(structureDetail.members):
1851                         prefix = '\t(' if index == 0 else '\t '
1852                         postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
1853                         verifyStructures.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
1854                 verifyStructures.append('{\n\t\tTCU_FAIL("Mismatch between ' + structureDetail.name + '");\n}')
1855         # construct file content
1856         stream = []
1857         stream.extend(structureDefinitions)
1858         stream.append('')
1859         stream.extend(featureEnabledFlags)
1860         stream.append('\nfor (int ndx = 0; ndx < count; ++ndx)\n{')
1861         stream.extend(clearStructures)
1862         stream.append('')
1863         stream.extend(structureChain)
1864         stream.append('\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
1865                                   '\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
1866                                   '\textFeatures.pNext = &' + testedStructureDetail[0].instanceName + '[ndx];\n'
1867                                   '\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);\n}\n')
1868         stream.extend(logStructures)
1869         stream.append('')
1870         stream.extend(verifyStructures)
1871         writeInlFile(filename, INL_HEADER, stream)
1872
1873 def generateDeviceFeaturesDefs(src):
1874         # look for definitions
1875         ptrnSType       = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_FEATURES(\w*)\s*='
1876         matches         = re.findall(ptrnSType, src, re.M)
1877         matches         = sorted(matches, key=lambda m: m[0])
1878         # construct final list
1879         defs = []
1880         for sType, sSuffix in matches:
1881                 structName                      = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1882                 ptrnStructName          = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Features' + sSuffix.replace('_', '') + ')'
1883                 matchStructName         = re.search(ptrnStructName, src, re.IGNORECASE)
1884                 if matchStructName:
1885                         # handle special cases
1886                         if sType == "EXCLUSIVE_SCISSOR":
1887                                 sType = "SCISSOR_EXCLUSIVE"
1888                         elif sType == "ASTC_DECODE":
1889                                 sType = "ASTC_DECODE_MODE"
1890                         if sType in {'VULKAN_1_1', 'VULKAN_1_2'}:
1891                                 continue
1892                         # end handling special cases
1893                         ptrnExtensionName       = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_EXTENSION_NAME).+$'
1894                         matchExtensionName      = re.search(ptrnExtensionName, src, re.M)
1895                         ptrnSpecVersion         = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_SPEC_VERSION).+$'
1896                         matchSpecVersion        = re.search(ptrnSpecVersion, src, re.M)
1897                         defs.append( (sType, '', sSuffix, matchStructName.group(1), \
1898                                                         matchExtensionName.group(0)     if matchExtensionName   else None,
1899                                                         matchExtensionName.group(1)     if matchExtensionName   else None,
1900                                                         matchSpecVersion.group(1)       if matchSpecVersion             else '0') )
1901         return defs
1902
1903 def generateDevicePropertiesDefs(src):
1904         # look for definitions
1905         ptrnSType       = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
1906         matches         = re.findall(ptrnSType, src, re.M)
1907         matches         = sorted(matches, key=lambda m: m[0])
1908         # construct final list
1909         defs = []
1910         for sType, sSuffix in matches:
1911                 # handle special cases
1912                 if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
1913                         continue
1914                 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
1915                 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
1916                 sVerSuffix = ''
1917                 sExtSuffix = sSuffix
1918                 suffixStart = sSuffix.rfind('_')
1919                 if suffixStart > 0:
1920                         sVerSuffix = sSuffix[:suffixStart]
1921                         sExtSuffix = sSuffix[suffixStart:]
1922                 # handle special case
1923                 if sType == "ID":
1924                         structName      = sType
1925                 else:
1926                         structName      = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1927                 ptrnStructName          = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
1928                 matchStructName         = re.search(ptrnStructName, src, re.M)
1929                 if matchStructName:
1930                         extType = sType
1931                         if extType == "MAINTENANCE_3":
1932                                 extType = "MAINTENANCE3"
1933                         elif extType == "DISCARD_RECTANGLE":
1934                                 extType = "DISCARD_RECTANGLES"
1935                         elif extType == "DRIVER":
1936                                 extType = "DRIVER_PROPERTIES"
1937                         elif extType == "POINT_CLIPPING":
1938                                 extType = "MAINTENANCE2"
1939                         elif extType == "SHADER_CORE":
1940                                 extType = "SHADER_CORE_PROPERTIES"
1941                         elif extType == "DRM":
1942                                 extType = "PHYSICAL_DEVICE_DRM"
1943                         # end handling special cases
1944                         ptrnExtensionName       = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
1945                         matchExtensionName      = re.search(ptrnExtensionName, src, re.M)
1946                         ptrnSpecVersion         = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
1947                         matchSpecVersion        = re.search(ptrnSpecVersion, src, re.M)
1948                         defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
1949                                                         matchExtensionName.group(0)     if matchExtensionName   else None,
1950                                                         matchExtensionName.group(1)     if matchExtensionName   else None,
1951                                                         matchSpecVersion.group  (1)     if matchSpecVersion             else '0') )
1952         return defs
1953
1954 def writeDeviceFeatures(api, dfDefs, filename):
1955         # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
1956         # and construct dictionary with all of their attributes
1957         blobMembers = {}
1958         blobStructs = {}
1959         blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
1960         for structureType in api.compositeTypes:
1961                 match = blobPattern.match(structureType.name)
1962                 if match:
1963                         allMembers = [member.name for member in structureType.members]
1964                         vkVersion = match.group(1)
1965                         blobMembers[vkVersion] = allMembers[2:]
1966                         blobStructs[vkVersion] = set()
1967         initFromBlobDefinitions = []
1968         emptyInitDefinitions = []
1969         # iterate over all feature structures
1970         allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
1971         nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
1972         for structureType in api.compositeTypes:
1973                 # skip structures that are not feature structures
1974                 if not allFeaturesPattern.match(structureType.name):
1975                         continue
1976                 # skip structures that were previously identified as blobs
1977                 if blobPattern.match(structureType.name):
1978                         continue
1979                 if structureType.isAlias:
1980                         continue
1981                 # skip sType and pNext and just grab third and next attributes
1982                 structureMembers = structureType.members[2:]
1983                 notPartOfBlob = True
1984                 if nonExtFeaturesPattern.match(structureType.name):
1985                         # check if this member is part of any of the blobs
1986                         for blobName, blobMemberList in blobMembers.items():
1987                                 # if just one member is not part of this blob go to the next blob
1988                                 # (we asume that all members are part of blob - no need to check all)
1989                                 if structureMembers[0].name not in blobMemberList:
1990                                         continue
1991                                 # add another feature structure name to this blob
1992                                 blobStructs[blobName].add(structureType)
1993                                 # add specialization for this feature structure
1994                                 memberCopying = ""
1995                                 for member in structureMembers:
1996                                         memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
1997                                 wholeFunction = \
1998                                         "template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
1999                                         "{{\n" \
2000                                         "{1}" \
2001                                         "}}".format(structureType.name, memberCopying)
2002                                 initFromBlobDefinitions.append(wholeFunction)
2003                                 notPartOfBlob = False
2004                                 # assuming that all members are part of blob, goto next
2005                                 break
2006                 # add empty template definition as on Fedora there are issue with
2007                 # linking using just generic template - all specializations are needed
2008                 if notPartOfBlob:
2009                         emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2010                         emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2011         extensionDefines = []
2012         makeFeatureDescDefinitions = []
2013         featureStructWrappers = []
2014         for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dfDefs):
2015                 extensionNameDefinition = extName
2016                 if not extensionNameDefinition:
2017                         extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2018                 # construct defines with names
2019                 if extLine:
2020                         extensionDefines.append(extLine)
2021                 else:
2022                         extensionDefines.append('#define {0} "not_existent_feature"'.format(extensionNameDefinition))
2023                 # handle special cases
2024                 if sType == "SCISSOR_EXCLUSIVE":
2025                         sType = "EXCLUSIVE_SCISSOR"
2026                 elif sType == "ASTC_DECODE_MODE":
2027                         sType = "ASTC_DECODE"
2028                 # end handling special cases
2029                 # construct makeFeatureDesc template function definitions
2030                 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2031                 makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2032                         "{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dfDefs)-idx))
2033                 # construct CreateFeatureStruct wrapper block
2034                 featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2035         # construct method that will check if structure sType is part of blob
2036         blobChecker = "bool isPartOfBlobFeatures (VkStructureType sType)\n{\n" \
2037                                   "\tconst std::vector<VkStructureType> sTypeVect =" \
2038                                   "\t{\n"
2039         # iterate over blobs with list of structures
2040         for blobName in sorted(blobStructs.keys()):
2041                 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2042                 # iterate over all feature structures in current blob
2043                 structuresList = list(blobStructs[blobName])
2044                 structuresList = sorted(structuresList, key=lambda s: s.name)
2045                 for structType in structuresList:
2046                         # find definition of this structure in dfDefs
2047                         structName = structType.name
2048                         # handle special cases
2049                         if structName == 'VkPhysicalDeviceShaderDrawParameterFeatures':
2050                                 structName = 'VkPhysicalDeviceShaderDrawParametersFeatures'
2051                         # end handling special cases
2052                         structDef = [s for s in dfDefs if s[3] == structName][0]
2053                         sType = structDef[0]
2054                         sSuffix = structDef[1] + structDef[2]
2055                         # handle special cases
2056                         if sType == "SCISSOR_EXCLUSIVE":
2057                                 sType = "EXCLUSIVE_SCISSOR"
2058                         # end handling special cases
2059                         sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2060                         blobChecker += "\t\t{0},\n".format(sTypeName)
2061         blobChecker += "\t};\n" \
2062                                    "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2063                                    "}\n"
2064         # combine all definition lists
2065         stream = [
2066         '#include "vkDeviceFeatures.hpp"\n',
2067         'namespace vk\n{']
2068         stream.extend(extensionDefines)
2069         stream.append('\n')
2070         stream.extend(initFromBlobDefinitions)
2071         stream.append('\n// generic template is not enough for some compilers')
2072         stream.extend(emptyInitDefinitions)
2073         stream.append('\n')
2074         stream.extend(makeFeatureDescDefinitions)
2075         stream.append('\n')
2076         stream.append('static const FeatureStructCreationData featureStructCreationArray[] =\n{')
2077         stream.extend(featureStructWrappers)
2078         stream.append('};\n')
2079         stream.append(blobChecker)
2080         stream.append('} // vk\n')
2081         writeInlFile(filename, INL_HEADER, stream)
2082
2083 def writeDeviceProperties(api, dpDefs, filename):
2084         # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2085         # and construct dictionary with all of their attributes
2086         blobMembers = {}
2087         blobStructs = {}
2088         blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2089         for structureType in api.compositeTypes:
2090                 match = blobPattern.match(structureType.name)
2091                 if match:
2092                         allMembers = [member.name for member in structureType.members]
2093                         vkVersion = match.group(1)
2094                         blobMembers[vkVersion] = allMembers[2:]
2095                         blobStructs[vkVersion] = set()
2096         initFromBlobDefinitions = []
2097         emptyInitDefinitions = []
2098         # iterate over all property structures
2099         allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2100         nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2101         for structureType in api.compositeTypes:
2102                 # skip structures that are not property structures
2103                 if not allPropertiesPattern.match(structureType.name):
2104                         continue
2105                 # skip structures that were previously identified as blobs
2106                 if blobPattern.match(structureType.name):
2107                         continue
2108                 if structureType.isAlias:
2109                         continue
2110                 # skip sType and pNext and just grab third and next attributes
2111                 structureMembers = structureType.members[2:]
2112                 notPartOfBlob = True
2113                 if nonExtPropertiesPattern.match(structureType.name):
2114                         # check if this member is part of any of the blobs
2115                         for blobName, blobMemberList in blobMembers.items():
2116                                 # if just one member is not part of this blob go to the next blob
2117                                 # (we asume that all members are part of blob - no need to check all)
2118                                 if structureMembers[0].name not in blobMemberList:
2119                                         continue
2120                                 # add another property structure name to this blob
2121                                 blobStructs[blobName].add(structureType)
2122                                 # add specialization for this property structure
2123                                 memberCopying = ""
2124                                 for member in structureMembers:
2125                                         if not member.arraySize:
2126                                                 # handle special case
2127                                                 if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2128                                                         blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2129                                                         memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2130                                                 # end handling special case
2131                                                 else:
2132                                                         memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2133                                         else:
2134                                                 memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type[0], member.arraySize[1:-1])
2135                                 wholeFunction = \
2136                                         "template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2137                                         "{{\n" \
2138                                         "{1}" \
2139                                         "}}".format(structureType.name, memberCopying)
2140                                 initFromBlobDefinitions.append(wholeFunction)
2141                                 notPartOfBlob = False
2142                                 # assuming that all members are part of blob, goto next
2143                                 break
2144                 # add empty template definition as on Fedora there are issue with
2145                 # linking using just generic template - all specializations are needed
2146                 if notPartOfBlob:
2147                         emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2148                         emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2149         extensionDefines = []
2150         makePropertyDescDefinitions = []
2151         propertyStructWrappers = []
2152         for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dpDefs):
2153                 extensionNameDefinition = extName
2154                 if not extensionNameDefinition:
2155                         extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2156                 # construct defines with names
2157                 if extLine:
2158                         extensionDefines.append(extLine)
2159                 else:
2160                         extensionDefines.append('#define {0} "core_property"'.format(extensionNameDefinition))
2161                 # construct makePropertyDesc template function definitions
2162                 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2163                 makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2164                         "{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dpDefs)-idx))
2165                 # construct CreateProperty struct wrapper block
2166                 propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2167                         # construct method that will check if structure sType is part of blob
2168         blobChecker = "bool isPartOfBlobProperties (VkStructureType sType)\n{\n" \
2169                                   "\tconst std::vector<VkStructureType> sTypeVect =" \
2170                                   "\t{\n"
2171         # iterate over blobs with list of structures
2172         for blobName in sorted(blobStructs.keys()):
2173                 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2174                 # iterate over all feature structures in current blob
2175                 structuresList = list(blobStructs[blobName])
2176                 structuresList = sorted(structuresList, key=lambda s: s.name)
2177                 for structType in structuresList:
2178                         # find definition of this structure in dpDefs
2179                         structName = structType.name
2180                         structDef = [s for s in dpDefs if s[3] == structName][0]
2181                         sType = structDef[0]
2182                         sSuffix = structDef[1] + structDef[2]
2183                         sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2184                         blobChecker += "\t\t{0},\n".format(sTypeName)
2185         blobChecker += "\t};\n" \
2186                                    "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2187                                    "}\n"
2188         # combine all definition lists
2189         stream = [
2190         '#include "vkDeviceProperties.hpp"\n',
2191         'namespace vk\n{']
2192         stream.extend(extensionDefines)
2193         stream.append('\n')
2194         stream.extend(initFromBlobDefinitions)
2195         stream.append('\n// generic template is not enough for some compilers')
2196         stream.extend(emptyInitDefinitions)
2197         stream.append('\n')
2198         stream.extend(makePropertyDescDefinitions)
2199         stream.append('\n')
2200         stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2201         stream.extend(propertyStructWrappers)
2202         stream.append('};\n')
2203         stream.append(blobChecker)
2204         stream.append('} // vk\n')
2205         writeInlFile(filename, INL_HEADER, stream)
2206
2207 def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
2208         stream = []
2209         for _, _, _, extStruct, _, _, _ in dfDefs:
2210                 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2211                 stream.append(pattern.format(extStruct, nameSubStr))
2212         writeInlFile(filename, INL_HEADER, indentLines(stream))
2213
2214 def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
2215         pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
2216         genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2217
2218 def writeDeviceFeaturesContextDecl(dfDefs, filename):
2219         pattern = "const vk::{0}&\tget{1}\t(void) const;"
2220         genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2221
2222 def writeDeviceFeaturesContextDefs(dfDefs, filename):
2223         pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2224         genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2225
2226 def genericDevicePropertiesWriter(dfDefs, pattern, filename):
2227         stream = []
2228         for _, _, _, extStruct, _, _, _ in dfDefs:
2229                 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2230                 if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
2231                         nameSubStr += "NV"
2232                 stream.append(pattern.format(extStruct, nameSubStr))
2233         writeInlFile(filename, INL_HEADER, indentLines(stream))
2234
2235 def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
2236         pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
2237         genericDevicePropertiesWriter(dfDefs, pattern, filename)
2238
2239 def writeDevicePropertiesContextDecl(dfDefs, filename):
2240         pattern = "const vk::{0}&\tget{1}\t(void) const;"
2241         genericDevicePropertiesWriter(dfDefs, pattern, filename)
2242
2243 def writeDevicePropertiesContextDefs(dfDefs, filename):
2244         pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2245         genericDevicePropertiesWriter(dfDefs, pattern, filename)
2246
2247 def splitWithQuotation(line):
2248         result = []
2249         splitted = re.findall(r'[^"\s]\S*|".+?"', line)
2250         for s in splitted:
2251                 result.append(s.replace('"', ''))
2252         return result
2253
2254 def writeMandatoryFeatures(filename):
2255         stream = []
2256         pattern = r'\s*([\w]+)\s+FEATURES\s+\((.*)\)\s+REQUIREMENTS\s+\((.*)\)'
2257         mandatoryFeatures = readFile(os.path.join(VULKAN_H_DIR, "mandatory_features.txt"))
2258         matches = re.findall(pattern, mandatoryFeatures)
2259         dictStructs = {}
2260         dictData = []
2261         for m in matches:
2262                 allRequirements = splitWithQuotation(m[2])
2263                 dictData.append( [ m[0], m[1].strip(), allRequirements ] )
2264                 if m[0] != 'VkPhysicalDeviceFeatures' :
2265                         if (m[0] not in dictStructs):
2266                                 dictStructs[m[0]] = [m[0][2:3].lower() + m[0][3:]]
2267                         if (allRequirements[0]):
2268                                 if (allRequirements[0] not in dictStructs[m[0]][1:]):
2269                                         dictStructs[m[0]].append(allRequirements[0])
2270
2271         stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
2272                                    '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
2273                                    '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
2274                                    '',
2275                                    '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
2276                                    '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
2277                                    '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
2278                                    '',
2279                                    '\ttcu::TestLog& log = context.getTestContext().getLog();',
2280                                    '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
2281                                    '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
2282                                    '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
2283                                    '\tvoid** nextPtr = &coreFeatures.pNext;',
2284                                    ''])
2285
2286         listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
2287         for k, v in listStruct:
2288                 if (v[1].startswith("ApiVersion")):
2289                         cond = '\tif (context.contextSupports(vk::' + v[1] + '))'
2290                 else:
2291                         cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[1] + '"))'
2292                 stream.extend(['\tvk::' + k + ' ' + v[0]+ ';',
2293                                         '\tdeMemset(&' + v[0] + ', 0, sizeof(' + v[0] + '));',
2294                                         ''])
2295                 reqs = v[1:]
2296                 if len(reqs) > 0 :
2297                         cond = 'if ( '
2298                         for i, req in enumerate(reqs) :
2299                                 if (req.startswith("ApiVersion")):
2300                                         cond = cond + 'context.contextSupports(vk::' + req + ')'
2301                                 else:
2302                                         cond = cond + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2303                                 if i+1 < len(reqs) :
2304                                         cond = cond + ' || '
2305                         cond = cond + ' )'
2306                         stream.append('\t' + cond)
2307                 stream.extend(['\t{',
2308                                            '\t\t' + v[0] + '.sType = getStructureType<' + k + '>();',
2309                                            '\t\t*nextPtr = &' + v[0] + ';',
2310                                            '\t\tnextPtr  = &' + v[0] + '.pNext;',
2311                                            '\t}',
2312                                            ''])
2313         stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
2314                                    '\tbool result = true;',
2315                                    ''])
2316
2317         for v in dictData:
2318                 structType = v[0];
2319                 structName = 'coreFeatures.features';
2320                 if v[0] != 'VkPhysicalDeviceFeatures' :
2321                         structName = dictStructs[v[0]][0]
2322                 if len(v[2]) > 0 :
2323                         condition = 'if ( '
2324                         for i, req in enumerate(v[2]) :
2325                                 if (req.startswith("ApiVersion")):
2326                                         condition = condition + 'context.contextSupports(vk::' + req + ')'
2327                                 elif '.' in req:
2328                                         condition = condition + req
2329                                 else:
2330                                         condition = condition + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2331                                 if i+1 < len(v[2]) :
2332                                         condition = condition + ' && '
2333                         condition = condition + ' )'
2334                         stream.append('\t' + condition)
2335                 stream.append('\t{')
2336                 # Don't need to support an AND case since that would just be another line in the .txt
2337                 if len(v[1].split(" ")) == 1:
2338                         stream.append('\t\tif ( ' + structName + '.' + v[1] + ' == VK_FALSE )')
2339                 else:
2340                         condition = 'if ( '
2341                         for i, feature in enumerate(v[1].split(" ")):
2342                                 if i != 0:
2343                                         condition = condition + ' && '
2344                                 condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
2345                         condition = condition + ' )'
2346                         stream.append('\t\t' + condition)
2347                 featureSet = v[1].replace(" ", " or ")
2348                 stream.extend(['\t\t{',
2349                                            '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
2350                                            '\t\t\tresult = false;',
2351                                            '\t\t}',
2352                                            '\t}',
2353                                            ''])
2354         stream.append('\treturn result;')
2355         stream.append('}\n')
2356         writeInlFile(filename, INL_HEADER, stream)
2357
2358 def writeExtensionList(filename, patternPart):
2359         stream = []
2360         stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(patternPart.title()))
2361         extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
2362         pattern = r'\s*([^\s]+)\s+{0}\s*[0-9_]*'.format(patternPart)
2363         matches = re.findall(pattern, extensionsData)
2364         for m in matches:
2365                 stream.append('\t"' + m + '",')
2366         stream.append('};\n')
2367         writeInlFile(filename, INL_HEADER, stream)
2368
2369 def preprocessTopInclude(src, dir):
2370         pattern = r'#include\s+"([^\n]+)"'
2371         while True:
2372                 inc = re.search(pattern, src)
2373                 if inc is None:
2374                         return src
2375                 incFileName = inc.string[inc.start(1):inc.end(1)]
2376                 patternIncNamed = r'#include\s+"' + incFileName + '"'
2377                 incBody = readFile(os.path.join(dir, incFileName)) if incFileName != 'vulkan/vk_platform.h' else ''
2378                 incBodySanitized = re.sub(pattern, '', incBody)
2379                 bodyEndSanitized = re.sub(patternIncNamed, '', src[inc.end(0):])
2380                 src = src[0:inc.start(0)] + incBodySanitized + bodyEndSanitized
2381         return src
2382
2383 if __name__ == "__main__":
2384         # Read all .h files, with vulkan_core.h first
2385         files                   = os.listdir(VULKAN_H_DIR)
2386         files                   = [f for f in files if f.endswith(".h")]
2387         files.sort()
2388         files.remove("vulkan_core.h")
2389         first = ["vk_video/vulkan_video_codecs_common.h", "vulkan_core.h"]
2390         files = first + files
2391
2392         src                             = ""
2393         for file in files:
2394                 src += preprocessTopInclude(readFile(os.path.join(VULKAN_H_DIR,file)), VULKAN_H_DIR)
2395
2396         src = re.sub('\s*//[^\n]*', '', src)
2397         src = re.sub('\n\n', '\n', src)
2398
2399         api                             = parseAPI(src)
2400
2401         platformFuncs   = [Function.TYPE_PLATFORM]
2402         instanceFuncs   = [Function.TYPE_INSTANCE]
2403         deviceFuncs             = [Function.TYPE_DEVICE]
2404
2405         dfd                                                                             = generateDeviceFeaturesDefs(src)
2406         writeDeviceFeatures                                             (api, dfd, os.path.join(VULKAN_DIR, "vkDeviceFeatures.inl"))
2407         writeDeviceFeaturesDefaultDeviceDefs    (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
2408         writeDeviceFeaturesContextDecl                  (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDecl.inl"))
2409         writeDeviceFeaturesContextDefs                  (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDefs.inl"))
2410
2411         dpd                                                                             = generateDevicePropertiesDefs(src)
2412         writeDeviceProperties                                   (api, dpd, os.path.join(VULKAN_DIR, "vkDeviceProperties.inl"))
2413
2414         writeDevicePropertiesDefaultDeviceDefs  (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
2415         writeDevicePropertiesContextDecl                (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDecl.inl"))
2416         writeDevicePropertiesContextDefs                (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDefs.inl"))
2417
2418         writeHandleType                                                 (api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
2419         writeBasicTypes                                                 (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
2420         writeCompositeTypes                                             (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
2421         writeInterfaceDecl                                              (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"),               platformFuncs,  False)
2422         writeInterfaceDecl                                              (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"),               instanceFuncs,  False)
2423         writeInterfaceDecl                                              (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"),                 deviceFuncs,    False)
2424         writeInterfaceDecl                                              (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"),              platformFuncs,  True)
2425         writeInterfaceDecl                                              (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"),              instanceFuncs,  True)
2426         writeInterfaceDecl                                              (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"),                deviceFuncs,    True)
2427         writeFunctionPtrTypes                                   (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
2428         writeFunctionPointers                                   (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"),               platformFuncs)
2429         writeFunctionPointers                                   (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"),               instanceFuncs)
2430         writeFunctionPointers                                   (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"),                 deviceFuncs)
2431         writeInitFunctionPointers                               (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"),   platformFuncs,  lambda f: f.name != "vkGetInstanceProcAddr")
2432         writeInitFunctionPointers                               (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"),   instanceFuncs)
2433         writeInitFunctionPointers                               (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"),             deviceFuncs)
2434         writeFuncPtrInterfaceImpl                               (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"),                             platformFuncs,  "PlatformDriver")
2435         writeFuncPtrInterfaceImpl                               (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"),                             instanceFuncs,  "InstanceDriver")
2436         writeFuncPtrInterfaceImpl                               (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"),                               deviceFuncs,    "DeviceDriver")
2437         writeStrUtilProto                                               (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
2438         writeStrUtilImpl                                                (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
2439         writeRefUtilProto                                               (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
2440         writeRefUtilImpl                                                (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
2441         writeStructTraitsImpl                                   (api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl"))
2442         writeNullDriverImpl                                             (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
2443         writeTypeUtil                                                   (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
2444         writeSupportedExtenions                                 (api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl"))
2445         writeCoreFunctionalities                                (api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl"))
2446         writeExtensionFunctions                                 (api, os.path.join(VULKAN_DIR, "vkExtensionFunctions.inl"))
2447         writeDeviceFeatures2                                    (api, os.path.join(VULKAN_DIR, "vkDeviceFeatures2.inl"))
2448         writeMandatoryFeatures                                  (     os.path.join(VULKAN_DIR, "vkMandatoryFeatures.inl"))
2449         writeExtensionList                                              (     os.path.join(VULKAN_DIR, "vkInstanceExtensions.inl"),                             'INSTANCE')
2450         writeExtensionList                                              (     os.path.join(VULKAN_DIR, "vkDeviceExtensions.inl"),                               'DEVICE')
2451         writeDriverIds                                                  (     os.path.join(VULKAN_DIR, "vkKnownDriverIds.inl"))
2452         writeObjTypeImpl                                                (api, os.path.join(VULKAN_DIR, "vkObjTypeImpl.inl"))