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