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