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