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