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