1 # -*- coding: utf-8 -*-
3 #-------------------------------------------------------------------------
7 # Copyright (c) 2015 Google Inc.
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
13 # http://www.apache.org/licenses/LICENSE-2.0
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.
21 #-------------------------------------------------------------------------
29 from itertools import chain
30 from collections import OrderedDict
32 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
34 from build.common import DEQP_DIR, execute
35 from khr_util.format import indentLines, writeInlFile
37 VULKAN_HEADERS_INCLUDE_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "include")
38 VULKAN_SRC_DIR = os.path.join(os.path.dirname(__file__), "src")
41 /* WARNING: This is auto-generated file. Do not modify, since changes will
42 * be lost! Modify the generating script instead.
43 * This file was generated by /scripts/gen_framework.py
48 ("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE", "size_t"),
49 ("VK_MAX_EXTENSION_NAME_SIZE", "size_t"),
50 ("VK_MAX_DRIVER_NAME_SIZE", "size_t"),
51 ("VK_MAX_DRIVER_INFO_SIZE", "size_t"),
52 ("VK_UUID_SIZE", "size_t"),
53 ("VK_LUID_SIZE", "size_t"),
54 ("VK_MAX_MEMORY_TYPES", "size_t"),
55 ("VK_MAX_MEMORY_HEAPS", "size_t"),
56 ("VK_MAX_DESCRIPTION_SIZE", "size_t"),
57 ("VK_MAX_DEVICE_GROUP_SIZE", "size_t"),
58 ("VK_ATTACHMENT_UNUSED", "uint32_t"),
59 ("VK_SUBPASS_EXTERNAL", "uint32_t"),
60 ("VK_QUEUE_FAMILY_IGNORED", "uint32_t"),
61 ("VK_QUEUE_FAMILY_EXTERNAL", "uint32_t"),
62 ("VK_REMAINING_MIP_LEVELS", "uint32_t"),
63 ("VK_REMAINING_ARRAY_LAYERS", "uint32_t"),
64 ("VK_WHOLE_SIZE", "vk::VkDeviceSize"),
65 ("VK_TRUE", "vk::VkBool32"),
66 ("VK_FALSE", "vk::VkBool32"),
71 (["Display","*"], ["XlibDisplayPtr"], "void*"),
72 (["Window"], ["XlibWindow"], "uintptr_t",),
73 (["VisualID"], ["XlibVisualID"], "uint32_t"),
76 (["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"),
77 (["xcb_window_t"], ["XcbWindow"], "uintptr_t"),
78 (["xcb_visualid_t"], ["XcbVisualid"], "uint32_t"),
80 # VK_KHR_wayland_surface
81 (["struct", "wl_display","*"], ["WaylandDisplayPtr"], "void*"),
82 (["struct", "wl_surface", "*"], ["WaylandSurfacePtr"], "void*"),
85 (["MirConnection", "*"], ["MirConnectionPtr"], "void*"),
86 (["MirSurface", "*"], ["MirSurfacePtr"], "void*"),
88 # VK_KHR_android_surface
89 (["ANativeWindow", "*"], ["AndroidNativeWindowPtr"], "void*"),
91 # VK_KHR_win32_surface
92 (["HINSTANCE"], ["Win32InstanceHandle"], "void*"),
93 (["HWND"], ["Win32WindowHandle"], "void*"),
94 (["HANDLE"], ["Win32Handle"], "void*"),
95 (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"),
96 (["AHardwareBuffer", "*"], ["AndroidHardwareBufferPtr"], "void*"),
97 (["HMONITOR"], ["Win32MonitorHandle"], "void*"),
98 (["LPCWSTR"], ["Win32LPCWSTR"], "const void*"),
100 # VK_EXT_acquire_xlib_display
101 (["RROutput"], ["RROutput"], "void*"),
103 (["zx_handle_t"], ["zx_handle_t"], "uint32_t"),
104 (["GgpFrameToken"], ["GgpFrameToken"], "int32_t"),
105 (["GgpStreamDescriptor"], ["GgpStreamDescriptor"], "int32_t"),
106 (["CAMetalLayer"], ["CAMetalLayer"], "void*"),
109 PLATFORM_TYPE_NAMESPACE = "pt"
111 TYPE_SUBSTITUTIONS = [
113 ("DWORD", "uint32_t"),
114 ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
117 EXTENSION_POSTFIXES = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK", "FUCHSIA", "GGP", "AMD", "QNX"]
118 EXTENSION_POSTFIXES_STANDARD = ["KHR", "EXT"]
120 def prefixName (prefix, name):
121 name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
122 name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
125 name = name.replace("YCB_CR_", "YCBCR_")
126 name = name.replace("WIN_32_", "WIN32_")
127 name = name.replace("8_BIT_", "8BIT_")
128 name = name.replace("16_BIT_", "16BIT_")
129 name = name.replace("INT_64_", "INT64_")
130 name = name.replace("D_3_D_12_", "D3D12_")
131 name = name.replace("IOSSURFACE_", "IOS_SURFACE_")
132 name = name.replace("MAC_OS", "MACOS_")
133 name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_")
134 name = name.replace("VIEWPORT_W", "VIEWPORT_W_")
135 name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES")
136 name = name.replace("PHYSICAL_DEVICE_SHADER_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES")
137 name = name.replace("PHYSICAL_DEVICE_RGBA_10_X_6_FORMATS_FEATURES_EXT", "PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT")
138 name = name.replace("_PCIBUS_", "_PCI_BUS_")
139 name = name.replace("ASTCD", "ASTC_D")
140 name = name.replace("AABBNV", "AABB_NV")
141 name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
142 name = name.replace("SMBUILTINS", "SM_BUILTINS")
143 name = name.replace("ASTCHDRFEATURES", "ASTC_HDR_FEATURES")
144 name = name.replace("UINT_8", "UINT8")
145 name = name.replace("VULKAN_11_FEATURES", "VULKAN_1_1_FEATURES")
146 name = name.replace("VULKAN_11_PROPERTIES", "VULKAN_1_1_PROPERTIES")
147 name = name.replace("VULKAN_12_FEATURES", "VULKAN_1_2_FEATURES")
148 name = name.replace("VULKAN_12_PROPERTIES", "VULKAN_1_2_PROPERTIES")
149 name = name.replace("INT_8_", "INT8_")
150 name = name.replace("AABBNV", "AABB_NV")
151 name = name.replace("_H_264_", "_H264_")
152 name = name.replace("_H_265_", "_H265_")
153 name = name.replace("RDMAFEATURES", "RDMA_FEATURES")
154 name = name.replace("RGBA_10_X_6", "RGBA10X6")
160 def __init__ (self, versionTuple):
161 self.major = versionTuple[0]
162 self.minor = versionTuple[1]
163 self.patch = versionTuple[2]
167 return "VK_API_VERSION_%d_%d" % (self.major, self.minor)
168 return '0x%Xu' % (hash(self))
170 def isStandardVersion (self):
177 def getBestRepresentation (self):
178 if self.isStandardVersion():
179 return self.getInHex()
180 return self.getDefineName()
182 def getDefineName (self):
183 return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch)
186 return (self.major << 22) | (self.minor << 12) | self.patch
188 def __eq__ (self, other):
189 return self.major == other.major and self.minor == other.minor and self.patch == other.patch
192 return self.getBestRepresentation()
199 def __init__ (self, type, name):
205 def getHandleType (self):
206 return prefixName("HANDLE_TYPE_", self.name)
208 def checkAliasValidity (self):
212 return '%s (%s, %s)' % (self.name, self.alias, self.isAlias)
215 def __init__ (self, type, name, value):
223 return '%s = %s (%s)' % (self.name, self.value, self.type)
226 def __init__ (self, name, values):
232 def checkAliasValidity (self):
233 if self.alias != None:
234 if len(self.values) != len(self.alias.values):
235 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
236 for index, value in enumerate(self.values):
237 aliasVal = self.alias.values[index]
238 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
239 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
242 return '%s (%s) %s' % (self.name, self.alias, self.values)
245 def __init__ (self, name, values):
251 def checkAliasValidity (self):
252 if self.alias != None:
253 if len(self.values) != len(self.alias.values):
254 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
255 for index, value in enumerate(self.values):
256 aliasVal = self.alias.values[index]
257 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
258 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
261 return '%s (%s)' % (self.name, self.alias)
264 def __init__ (self, type, name, arraySizeOrFieldWidth):
265 type = type.replace('*',' *').replace('&',' &')
266 for src, dst in TYPE_SUBSTITUTIONS:
267 type = type.replace(src, dst)
268 self.type = type.split(' ')
269 for platformType, substitute, compat in PLATFORM_TYPES:
270 range = self.contains(self.type, platformType)
272 self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:]
275 if len(arraySizeOrFieldWidth) > 0 and arraySizeOrFieldWidth[0] == ':':
277 self.fieldWidth = arraySizeOrFieldWidth
279 self.arraySize = arraySizeOrFieldWidth
282 def contains(self, big, small):
283 for i in range(len(big)-len(small)+1):
284 for j in range(len(small)):
285 if big[i+j] != small[j]:
288 return i, i+len(small)
292 return ' '.join(self.type).replace(' *','*').replace(' &','&')
294 def getAsString (self, separator):
295 return '%s%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize, self.fieldWidth)
297 def getAsStringForArgumentList (self, separator):
298 return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize)
301 return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize)
303 def __eq__ (self, other):
304 if len(self.type) != len(other.type):
306 for index, type in enumerate(self.type):
307 if "*" == type or "&" == type or "const" == type or "volatile" == type:
308 if type != other.type[index]:
310 elif type != other.type[index] and \
311 type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \
312 other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD):
314 return self.arraySize == other.arraySize
316 def __ne__ (self, other):
317 return not self == other
323 def __init__ (self, typeClass, name, members, apiVersion = None):
324 self.typeClass = typeClass
326 self.members = members
329 self.apiVersion = apiVersion
331 def getClassName (self):
332 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
333 return names[self.typeClass]
335 def checkAliasValidity (self):
336 if self.alias != None:
337 if len(self.members) != len(self.alias.members):
338 raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name))
339 for index, member in enumerate(self.members ):
341 #if member != self.alias.members[index]:
342 #raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name))
343 #raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".")
345 return '%s (%s)' % (self.name, self.alias)
348 TYPE_PLATFORM = 0 # Not bound to anything
349 TYPE_INSTANCE = 1 # Bound to VkInstance
350 TYPE_DEVICE = 2 # Bound to VkDevice
352 def __init__ (self, name, returnType, arguments, apiVersion = None):
354 self.returnType = returnType
355 self.arguments = arguments
358 self.apiVersion = apiVersion
362 if self.name == "vkGetInstanceProcAddr":
363 return Function.TYPE_PLATFORM
364 assert len(self.arguments) > 0
365 firstArgType = self.arguments[0].getType()
366 if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
367 return Function.TYPE_INSTANCE
368 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
369 return Function.TYPE_DEVICE
371 return Function.TYPE_PLATFORM
373 def checkAliasValidity (self):
374 if self.alias != None:
375 if len(self.arguments) != len(self.alias.arguments):
376 raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name))
377 if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)):
378 raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name))
379 for index, argument in enumerate(self.arguments):
380 if argument != self.alias.arguments[index]:
381 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))
384 return '%s (%s)' % (self.name, self.alias)
387 def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, typedefs, versionInCore):
389 self.definitions = definitions
390 self.additionalDefs = additionalDefinitions
391 self.handles = handles
393 self.bitfields = bitfields
394 self.compositeTypes = compositeTypes
395 self.functions = functions
396 self.typedefs = typedefs
397 self.versionInCore = versionInCore
400 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)
403 def __init__ (self, versions, definitions, handles, enums, bitfields, bitfields64, compositeTypes, functions, extensions, additionalExtensionData):
404 self.versions = versions
405 self.definitions = definitions
406 self.handles = handles
408 self.bitfields = bitfields
409 self.bitfields64 = bitfields64
410 self.compositeTypes = compositeTypes
411 self.functions = functions # \note contains extension functions as well
412 self.extensions = extensions
413 self.additionalExtensionData = additionalExtensionData # \note contains mandatory features and information about promotion
415 def readFile (filename):
416 with open(filename, 'rt') as f:
419 IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*'
420 WIDTH_PTRN = r'[:0-9]*'
421 TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
423 def getInterfaceName (function):
424 assert function.name[:2] == "vk"
425 return function.name[2].lower() + function.name[3:]
427 def getFunctionTypeName (function):
428 assert function.name[:2] == "vk"
429 return function.name[2:] + "Func"
431 def endsWith (str, postfix):
432 return str[-len(postfix):] == postfix
434 def splitNameExtPostfix (name):
435 knownExtPostfixes = EXTENSION_POSTFIXES
436 for postfix in knownExtPostfixes:
437 if endsWith(name, postfix):
438 return (name[:-len(postfix)], postfix)
441 def getBitEnumNameForBitfield (bitfieldName):
442 bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
443 assert bitfieldName[-1] == "s"
444 return bitfieldName[:-1] + "Bits" + postfix
446 def getBitfieldNameForBitEnum (bitEnumName):
447 bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
448 assert bitEnumName[-4:] == "Bits"
449 return bitEnumName[:-4] + "s" + postfix
451 def parsePreprocDefinedValue (src, name):
452 value = parsePreprocDefinedValueOptional(src, name)
454 raise Exception("No such definition: %s" % name)
457 def parsePreprocDefinedValueOptional (src, name):
458 definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
459 if definition is None:
461 value = definition.group(1).strip()
462 if value == "UINT32_MAX":
466 def parseEnum (name, src):
467 keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,\n}]+)\s*[,\n}]'
468 return Enum(name, re.findall(keyValuePtrn, src))
470 # \note Parses raw enums, some are mapped to bitfields later
471 def parseEnums (src):
472 matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
474 for enumname, contents, typename in matches:
475 enums.append(parseEnum(typename, contents))
478 def parseCompositeType (type, name, src):
479 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\]|\s*:\s*[0-9]+)*)\s*;'
480 matches = re.findall(typeNamePtrn, src)
481 members = [Variable(t.strip(), n.strip(), a.replace(' ', '')) for t, n, a, _ in matches]
482 return CompositeType(type, name, members)
484 def parseCompositeTypes (src):
485 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
486 matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
488 for type, structname, contents, typename in matches:
489 types.append(parseCompositeType(typeMap[type], typename, contents))
492 def parseCompositeTypesByVersion (src, versionsData):
494 # find occurence of extension is a place where
495 # we cant assign apiVersion to found structures
496 extPtrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
497 versionEnd = re.search(extPtrn, src)
498 versions = [Version((v[2], v[3], 0)) for v in versionsData]
499 versions.append(None)
501 # construct list of locations where version definitions start, and add the end of the file to it
502 sectionLocations = [versionDef[1] for versionDef in versionsData]
503 sectionLocations.append(versionEnd.start())
504 sectionLocations.append(len(src))
506 # construct function declaration pattern
507 ptrn = r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;'
508 regPtrn = re.compile(ptrn)
510 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
512 # iterate over all versions and find all structure definitions
513 for index, v in enumerate(versions):
514 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
515 for type, structname, contents, typename in matches:
516 compositeType = parseCompositeType(typeMap[type], typename, contents)
517 compositeType.apiVersion = v
518 types.append(compositeType)
521 def parseVersions (src):
522 # returns list of tuples each with four items:
523 # 1. string with version token (without ' 1' at the end)
524 # 2. starting point off version specific definitions in vulkan.h.in
525 # 3. major version number
526 # 4. minor version number
527 return [(m.group()[:-2], m.start(), int(m.group(1)), int(m.group(2))) for m in re.finditer('VK_VERSION_([1-9])_([0-9]) 1', src)]
529 def parseHandles (src):
530 matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
532 typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
533 for type, name in matches:
534 handle = Handle(typeMap[type], name)
535 handles.append(handle)
538 def parseArgList (src):
539 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*'
541 for rawArg in src.split(','):
542 m = re.search(typeNamePtrn, rawArg)
543 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
546 def removeTypeExtPostfix (name):
547 for extPostfix in EXTENSION_POSTFIXES_STANDARD:
548 if endsWith(name, extPostfix):
549 return name[0:-len(extPostfix)]
552 def populateExtensionAliases(allObjects, extensionObjects):
553 for object in extensionObjects:
554 withoutPostfix = removeTypeExtPostfix(object.name)
555 if withoutPostfix != None and withoutPostfix in allObjects:
556 # max 1 alias is assumed by functions in this file
557 assert allObjects[withoutPostfix].alias == None
558 allObjects[withoutPostfix].alias = object
559 object.isAlias = True
560 for object in extensionObjects:
561 object.checkAliasValidity()
563 def populateAliasesWithTypedefs (objects, src):
565 for object in objects:
566 objectsByName[object.name] = object
567 ptrn = r'\s*typedef\s+' + object.name + r'\s+([^;]+)'
568 stash = re.findall(ptrn, src)
570 objExt = copy.deepcopy(object)
571 objExt.name = stash[0]
572 object.alias = objExt
573 objExt.isAlias = True
574 objects.append(objExt)
576 def removeAliasedValues (enum):
578 for name, value in enum.values:
579 valueByName[name] = value
581 def removeDefExtPostfix (name):
582 for extPostfix in EXTENSION_POSTFIXES:
583 if endsWith(name, "_" + extPostfix):
584 return name[0:-(len(extPostfix)+1)]
588 for name, value in enum.values:
589 withoutPostfix = removeDefExtPostfix(name)
590 if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value:
592 newValues.append((name, value))
593 enum.values = newValues
595 def parseFunctions (src):
596 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
597 matches = re.findall(ptrn, src)
599 for returnType, name, argList in matches:
600 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
603 def parseFunctionsByVersion (src, versions):
604 # construct list of locations where version definitions start, and add the end of the file to it
605 sectionLocations = [versionDef[1] for versionDef in versions]
606 sectionLocations.append(len(src))
608 # construct function declaration pattern
609 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
610 regPtrn = re.compile(ptrn)
613 # iterate over all versions and find all function definitions
614 for index, v in enumerate(versions):
615 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
616 for returnType, name, argList in matches:
617 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), v[0]))
620 def splitByExtension (src):
621 ptrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
622 # Construct long pattern that will be used to split whole source by extensions
623 match = "#define\s+("
624 for part in re.finditer(ptrn, src):
625 match += part.group(1)+"|"
626 match = match[:-1] + ")\s+1"
627 parts = re.split(match, src)
629 # First part is core, following tuples contain extension name and all its definitions
630 byExtension = [(None, parts[0])]
631 for ndx in range(1, len(parts), 2):
632 byExtension.append((parts[ndx], parts[ndx+1]))
635 def parseDefinitions (extensionName, src):
637 def skipDefinition (extensionName, definition):
638 if extensionName == None:
640 extNameUpper = extensionName.upper()
641 extNameUpper = extNameUpper.replace("VK_KHR_SYNCHRONIZATION2", "VK_KHR_SYNCHRONIZATION_2")
642 extNameUpper = extNameUpper.replace("VK_INTEL_SHADER_INTEGER_FUNCTIONS2", "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2")
643 extNameUpper = extNameUpper.replace("VK_EXT_ROBUSTNESS2", "VK_EXT_ROBUSTNESS_2")
644 extNameUpper = extNameUpper.replace("VK_EXT_FRAGMENT_DENSITY_MAP2", "VK_EXT_FRAGMENT_DENSITY_MAP_2")
645 extNameUpper = extNameUpper.replace("VK_EXT_SHADER_ATOMIC_FLOAT2", "VK_EXT_SHADER_ATOMIC_FLOAT_2")
646 extNameUpper = extNameUpper.replace("VK_AMD_SHADER_CORE_PROPERTIES2", "VK_AMD_SHADER_CORE_PROPERTIES_2")
647 extNameUpper = extNameUpper.replace("VK_EXT_EXTENDED_DYNAMIC_STATE2", "VK_EXT_EXTENDED_DYNAMIC_STATE_2")
649 if definition[0].startswith(extNameUpper) and definition[1].isdigit():
651 if definition[0].startswith(extNameUpper):
653 if definition[0].endswith("_H_"):
657 ptrn = r'#define\s+([^\s]+)\s+([^\r\n]+)'
658 matches = re.findall(ptrn, src)
660 return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)]
662 def parseTypedefs (src):
664 ptrn = r'typedef\s+([^\s]+)\s+([^\r\n]+);'
665 matches = re.findall(ptrn, src)
667 return [Definition(None, match[0], match[1]) for match in matches]
669 def parseExtensions (src, versions, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions, additionalExtensionData):
671 # note promotedExtensionDict is also executed for vulkan 1.0 source for which extension name is None
672 promotedExtensionDict = {None: None}
673 for extensionName, data in additionalExtensionData:
674 # make sure that this extension was registered
675 if 'register_extension' not in data.keys():
677 match = re.match("(\d).(\d).(\d)", data['register_extension']['core'])
680 # save array containing 'device' or 'instance' string followed by the vulkan version in which this extension is core
681 promotedExtensionDict[extensionName] = [data['register_extension']['type'], int(match.group(1)), int(match.group(2)), int(match.group(3))]
683 splitSrc = splitByExtension(src)
685 functionsByName = {function.name: function for function in allFunctions}
686 compositeTypesByName = {compType.name: compType for compType in allCompositeTypes}
687 enumsByName = {enum.name: enum for enum in allEnums}
688 bitfieldsByName = {bitfield.name: bitfield for bitfield in allBitfields}
689 handlesByName = {handle.name: handle for handle in allHandles}
690 definitionsByName = {definition.name: definition for definition in allDefinitions}
692 for extensionName, extensionSrc in splitSrc:
693 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValueOptional(extensionSrc, v.getInHex())) for v in versions]
694 definitions.extend([Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS])
695 definitions = [definition for definition in definitions if definition.value != None]
696 additionalDefinitions = parseDefinitions(extensionName, extensionSrc)
697 handles = parseHandles(extensionSrc)
698 functions = parseFunctions(extensionSrc)
699 compositeTypes = parseCompositeTypes(extensionSrc)
700 rawEnums = parseEnums(extensionSrc)
701 bitfieldNames = parseBitfieldNames(extensionSrc)
702 typedefs = parseTypedefs(extensionSrc)
703 enumBitfieldNames = [getBitEnumNameForBitfield(name) for name in bitfieldNames]
704 enums = [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
706 extCoreVersion = promotedExtensionDict.get(extensionName, None)
707 extFunctions = [functionsByName[function.name] for function in functions]
708 extCompositeTypes = [compositeTypesByName[compositeType.name] for compositeType in compositeTypes]
709 extEnums = [enumsByName[enum.name] for enum in enums]
710 extBitfields = [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames]
711 extHandles = [handlesByName[handle.name] for handle in handles]
712 extDefinitions = [definitionsByName[definition.name] for definition in definitions]
714 if extCoreVersion != None:
715 populateExtensionAliases(functionsByName, extFunctions)
716 populateExtensionAliases(handlesByName, extHandles)
717 populateExtensionAliases(enumsByName, extEnums)
718 populateExtensionAliases(bitfieldsByName, extBitfields)
719 populateExtensionAliases(compositeTypesByName, extCompositeTypes)
720 extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, typedefs, extCoreVersion))
723 def parseBitfieldNames (src):
724 ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
725 matches = re.findall(ptrn, src)
729 def parse64bitBitfieldNames (src):
730 ptrn = r'typedef\s+VkFlags64\s(' + IDENT_PTRN + r')\s*;'
731 matches = re.findall(ptrn, src)
735 def parse64bitBitfieldValues (src, bitfieldNamesList):
738 for bitfieldName in bitfieldNamesList:
739 ptrn = r'static const ' + bitfieldName + r'\s*(' + IDENT_PTRN + r')\s*=\s*([a-zA-Z0-9_]+)\s*;'
740 matches = re.findall(ptrn, src)
741 bitfields64.append(Bitfield(bitfieldName, matches))
746 versionsData = parseVersions(src)
747 versions = [Version((v[2], v[3], 0)) for v in versionsData]
748 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValue(src, v.getInHex())) for v in versions] +\
749 [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
751 handles = parseHandles(src)
752 rawEnums = parseEnums(src)
753 bitfieldNames = parseBitfieldNames(src)
754 bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
755 bitfield64Names = parse64bitBitfieldNames(src)
756 bitfields64 = parse64bitBitfieldValues(src, bitfield64Names)
759 compositeTypes = parseCompositeTypesByVersion(src, versionsData)
760 allFunctions = parseFunctionsByVersion(src, versionsData)
761 additionalExtensionData = {}
763 # read all files from extensions directory
764 for fileName in glob.glob(os.path.join(VULKAN_SRC_DIR, "extensions", "*.json")):
765 extensionName = os.path.basename(fileName)[:-5]
766 fileContent = readFile(fileName)
768 additionalExtensionData[extensionName] = json.loads(fileContent)
769 except ValueError as err:
770 print("Error in %s: %s" % (os.path.basename(fileName), str(err)))
772 additionalExtensionData = sorted(additionalExtensionData.items(), key=lambda e: e[0])
774 for enum in rawEnums:
775 if enum.name in bitfieldEnums:
776 bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
780 for bitfieldName in bitfieldNames:
781 if not bitfieldName in [bitfield.name for bitfield in bitfields]:
783 bitfields.append(Bitfield(bitfieldName, []))
785 extensions = parseExtensions(src, versions, allFunctions, compositeTypes, enums, bitfields, handles, definitions, additionalExtensionData)
787 # Populate alias fields
788 populateAliasesWithTypedefs(compositeTypes, src)
789 populateAliasesWithTypedefs(enums, src)
790 populateAliasesWithTypedefs(bitfields, src)
791 populateAliasesWithTypedefs(handles, src)
794 removeAliasedValues(enum)
796 # Make generator to create Deleter<VkAccelerationStructureNV>
797 for f in allFunctions:
798 if (f.name == 'vkDestroyAccelerationStructureNV'):
799 f.arguments[1].type[0] = 'VkAccelerationStructureNV'
801 # Dealias handles VkAccelerationStructureNV and VkAccelerationStructureKHR
802 for handle in handles:
803 if handle.name == 'VkAccelerationStructureKHR':
805 if handle.name == 'VkAccelerationStructureNV':
806 handle.isAlias = False
810 definitions = definitions,
813 bitfields = bitfields,
814 bitfields64 = bitfields64,
815 compositeTypes = compositeTypes,
816 functions = allFunctions,
817 extensions = extensions,
818 additionalExtensionData = additionalExtensionData)
820 def splitUniqueAndDuplicatedEntries (handles):
821 listOfUniqueHandles = []
822 duplicates = OrderedDict()
823 for handle in handles:
824 if handle.alias != None:
825 duplicates[handle.alias] = handle
826 if not handle.isAlias:
827 listOfUniqueHandles.append(handle)
828 return listOfUniqueHandles, duplicates
830 def writeHandleType (api, filename):
831 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles)
834 yield "\t%s\t= 0," % uniqeHandles[0].getHandleType()
835 for handle in uniqeHandles[1:]:
836 yield "\t%s," % handle.getHandleType()
837 for duplicate in duplicatedHandles:
838 yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType())
839 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType())
841 def genHandlesBlock ():
842 yield "enum HandleType"
845 for line in indentLines(genHandles()):
851 writeInlFile(filename, INL_HEADER, genHandlesBlock())
853 def getEnumValuePrefix (enum):
854 prefix = enum.name[0]
855 for i in range(1, len(enum.name)):
856 if enum.name[i].isupper() and not enum.name[i-1].isupper():
858 prefix += enum.name[i].upper()
861 def parseInt (value):
862 if value[:2] == "0x":
863 return int(value, 16)
865 return int(value, 10)
867 def areEnumValuesLinear (enum):
869 for name, value in enum.values:
870 if value[:2] != "VK":
871 intValue = parseInt(value)
872 if intValue != curIndex:
873 # consider enums containing *_MAX_ENUM = 0x7FFFFFFF as linear
874 if intValue == 0x7FFFFFFF:
880 def genEnumSrc (enum):
881 yield "enum %s" % enum.name
885 if areEnumValuesLinear(enum):
886 hasMaxItem = parseInt(enum.values[-1][1]) == 0x7FFFFFFF
888 values = enum.values[:-1] if hasMaxItem else enum.values
889 lastItem = "\t%s_LAST," % getEnumValuePrefix(enum)
891 # linear values first, followed by *_LAST
892 lines += ["\t%s\t= %s," % v for v in values if v[1][:2] != "VK"]
893 lines.append(lastItem)
895 # equivalence enums and *_MAX_ENUM
896 lines += ["\t%s\t= %s," % v for v in values if v[1][:2] == "VK"]
898 lines.append("\t%s\t= %s," % enum.values[-1])
900 lines += ["\t%s\t= %s," % v for v in enum.values]
902 for line in indentLines(lines):
907 def genBitfieldSrc (bitfield):
908 if len(bitfield.values) > 0:
909 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
911 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
914 yield "typedef uint32_t %s;" % bitfield.name
916 def genBitfield64Src (bitfield64):
917 yield "typedef uint64_t %s;" % bitfield64.name
918 if len(bitfield64.values) > 0:
919 ptrn = "static const " + bitfield64.name + " %s\t= %s;"
920 for line in indentLines([ptrn % v for v in bitfield64.values]):
924 def genCompositeTypeSrc (type):
925 yield "%s %s" % (type.getClassName(), type.name)
927 for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]):
931 def genHandlesSrc (handles):
932 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles)
934 def genLines (handles):
935 for handle in uniqeHandles:
936 if handle.type == Handle.TYPE_DISP:
937 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
938 elif handle.type == Handle.TYPE_NONDISP:
939 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
941 for duplicate in duplicatedHandles:
942 if duplicate.type == Handle.TYPE_DISP:
943 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
944 elif duplicate.type == Handle.TYPE_NONDISP:
945 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
947 for line in indentLines(genLines(handles)):
950 def stripTrailingComment(str):
951 index = str.find("//")
956 def genDefinitionsSrc (definitions):
957 for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, stripTrailingComment(definition.value)) for definition in definitions]:
960 def genDefinitionsAliasSrc (definitions):
961 for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]:
962 if definition.value != definitions[definition].value and definition.value != definitions[definition].name:
963 raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value))
966 def genMaxFrameworkVersion (definitions):
967 maxApiVersionMajor = 1
968 maxApiVersionMinor = 0
969 for definition in definitions:
970 match = re.match("VK_API_VERSION_(\d+)_(\d+)", definition.name)
972 apiVersionMajor = int(match.group(1))
973 apiVersionMinor = int(match.group(2))
974 if apiVersionMajor > maxApiVersionMajor:
975 maxApiVersionMajor = apiVersionMajor
976 maxApiVersionMinor = apiVersionMinor
977 elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
978 maxApiVersionMinor = apiVersionMinor
979 yield "#define VK_API_MAX_FRAMEWORK_VERSION\tVK_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
981 def writeBasicTypes (api, filename):
984 definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
986 for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
990 for line in genHandlesSrc(api.handles):
994 for enum in api.enums:
996 for line in genEnumSrc(enum):
999 for enum2 in api.enums:
1000 if enum2.alias == enum:
1001 yield "typedef %s %s;" % (enum2.name, enum.name)
1004 for bitfield in api.bitfields:
1005 if not bitfield.isAlias:
1006 for line in genBitfieldSrc(bitfield):
1009 for bitfield2 in api.bitfields:
1010 if bitfield2.alias == bitfield:
1011 yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
1014 for bitfield64 in api.bitfields64:
1015 for line in genBitfield64Src(bitfield64):
1018 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s)" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
1021 for ext in api.extensions:
1022 if ext.additionalDefs != None:
1023 for definition in ext.additionalDefs:
1024 yield "#define " + definition.name + " " + definition.value
1026 writeInlFile(filename, INL_HEADER, gen())
1028 def writeCompositeTypes (api, filename):
1030 for type in api.compositeTypes:
1031 type.checkAliasValidity()
1033 if not type.isAlias:
1034 for line in genCompositeTypeSrc(type):
1037 for type2 in api.compositeTypes:
1038 if type2.alias == type:
1039 yield "typedef %s %s;" % (type2.name, type.name)
1042 writeInlFile(filename, INL_HEADER, gen())
1044 def argListToStr (args):
1045 return ", ".join(v.getAsStringForArgumentList(' ') for v in args)
1047 def writeInterfaceDecl (api, filename, functionTypes, concrete):
1049 postfix = "" if concrete else " = 0"
1050 for function in api.functions:
1051 if not function.getType() in functionTypes:
1053 if not function.isAlias:
1054 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
1056 writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1058 def writeFunctionPtrTypes (api, filename):
1060 for function in api.functions:
1061 yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
1063 writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1065 def writeFunctionPointers (api, filename, functionTypes):
1066 def FunctionsYielder ():
1067 for function in api.functions:
1068 if function.getType() in functionTypes:
1069 if function.isAlias:
1070 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1071 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1073 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1075 writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1077 def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1078 def makeInitFunctionPointers ():
1079 for function in api.functions:
1080 if function.getType() in functionTypes and (cond == None or cond(function)):
1081 interfaceName = getInterfaceName(function)
1082 if function.isAlias:
1083 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1084 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1086 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1087 if function.alias != None:
1088 yield "if (!m_vk.%s)" % (getInterfaceName(function))
1089 yield " m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name)
1090 lines = [line.replace(' ', '\t') for line in indentLines(makeInitFunctionPointers())]
1091 writeInlFile(filename, INL_HEADER, lines)
1093 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1094 def makeFuncPtrInterfaceImpl ():
1095 for function in api.functions:
1096 if function.getType() in functionTypes and not function.isAlias:
1098 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
1100 if function.name == "vkEnumerateInstanceVersion":
1101 yield " if (m_vk.enumerateInstanceVersion)"
1102 yield " return m_vk.enumerateInstanceVersion(pApiVersion);"
1104 yield " *pApiVersion = VK_API_VERSION_1_0;"
1105 yield " return VK_SUCCESS;"
1106 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None:
1107 yield " vk::VkPhysicalDeviceProperties props;"
1108 yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1109 yield " if (props.apiVersion >= VK_API_VERSION_1_1)"
1110 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1112 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments))
1114 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1117 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1119 def writeStrUtilProto (api, filename):
1120 def makeStrUtilProto ():
1121 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]):
1124 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]):
1127 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]):
1130 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']):
1133 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]):
1136 writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1138 def writeStrUtilImpl (api, filename):
1139 def makeStrUtilImpl ():
1140 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]):
1144 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1147 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):
1152 for enum in api.enums:
1156 yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1158 yield "\tswitch (value)"
1160 for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values if v[:2] != "VK"] + ["\t\tdefault:\treturn DE_NULL;"]):
1165 for bitfield in api.bitfields:
1166 if bitfield.isAlias:
1167 if bitfield.name != 'VkBuildAccelerationStructureFlagsNV':
1170 yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
1173 if len(bitfield.values) > 0:
1174 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1176 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
1179 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1181 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
1184 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
1186 for type in api.compositeTypes:
1187 if not type.isAlias:
1189 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1191 yield "\ts << \"%s = {\\n\";" % type.name
1192 for member in type.members:
1193 memberName = member.name
1196 if member.getType() in bitfieldTypeNames:
1197 valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name)
1198 elif member.getType() == "const char*" or member.getType() == "char*":
1199 valFmt = "getCharPtrStr(value.%s)" % member.name
1200 elif member.getType() == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1201 valFmt = "getWStr(value.%s)" % member.name
1202 elif member.arraySize != '':
1203 singleDimensional = not '][' in member.arraySize
1204 if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1205 valFmt = "(const char*)value.%s" % member.name
1206 elif singleDimensional and (member.getType() == 'char' or member.getType() == 'uint8_t'):
1207 newLine = "'\\n' << "
1208 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)
1210 if member.name == "memoryTypes" or member.name == "memoryHeaps":
1211 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1213 endIter = "DE_ARRAY_END(value.%s)" % member.name
1214 newLine = "'\\n' << "
1215 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1216 memberName = member.name
1218 valFmt = "value.%s" % member.name
1219 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1223 writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1226 def writeObjTypeImpl (api, filename):
1227 def makeObjTypeImpl ():
1229 yield "namespace vk"
1232 yield "template<typename T> VkObjectType getObjectType (void);"
1234 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]):
1239 writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1241 class ConstructorFunction:
1242 def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1245 self.objectType = objectType
1246 self.ifaceArgs = ifaceArgs
1247 self.arguments = arguments
1249 def getConstructorFunctions (api):
1252 Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")],
1253 Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")],
1254 Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")]
1256 for function in api.functions:
1257 if function.isAlias:
1259 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1260 if function.name == "vkCreateDisplayModeKHR":
1261 continue # No way to delete display modes (bug?)
1263 # \todo [pyry] Rather hacky
1264 ifaceArgs = ifacesDict[function.getType()]
1265 if function.name == "vkCreateDevice":
1266 ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs
1268 assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"])
1270 objectType = function.arguments[-1].type[0] #not getType() but type[0] on purpose
1271 arguments = function.arguments[:-1]
1272 funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments))
1275 def addVersionDefines(versionSpectrum):
1276 output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1279 def removeVersionDefines(versionSpectrum):
1280 output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()]
1283 def writeRefUtilProto (api, filename):
1284 functions = getConstructorFunctions(api)
1286 def makeRefUtilProto ():
1288 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]):
1291 writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1293 def writeRefUtilImpl (api, filename):
1294 functions = getConstructorFunctions(api)
1296 def makeRefUtilImpl ():
1297 yield "namespace refdetails"
1301 for function in api.functions:
1302 if function.getType() == Function.TYPE_DEVICE \
1303 and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1304 and not function.name == "vkDestroyDevice" \
1305 and not function.isAlias:
1306 objectType = function.arguments[-2].getType()
1308 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1310 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
1314 yield "} // refdetails"
1318 Function.TYPE_PLATFORM: "object",
1319 Function.TYPE_INSTANCE: "instance",
1320 Function.TYPE_DEVICE: "device"
1323 for function in functions:
1324 deleterArgsString = ''
1325 if function.name == "createDevice":
1326 # createDevice requires two additional parameters to setup VkDevice deleter
1327 deleterArgsString = "vkp, instance, object, " + function.arguments[-1].name
1329 deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1331 yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1333 yield "\t%s object = 0;" % function.objectType
1334 yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1335 yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1339 writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1341 def writeStructTraitsImpl (api, filename):
1343 for type in api.compositeTypes:
1344 if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias and type.name != "VkBaseOutStructure" and type.name != "VkBaseInStructure":
1345 yield "template<> VkStructureType getStructureType<%s> (void)" % type.name
1347 yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name)
1351 writeInlFile(filename, INL_HEADER, gen())
1353 def writeNullDriverImpl (api, filename):
1354 def genNullDriverImpl ():
1355 specialFuncNames = [
1356 "vkCreateGraphicsPipelines",
1357 "vkCreateComputePipelines",
1358 "vkCreateRayTracingPipelinesNV",
1359 "vkCreateRayTracingPipelinesKHR",
1360 "vkGetInstanceProcAddr",
1361 "vkGetDeviceProcAddr",
1362 "vkEnumeratePhysicalDevices",
1363 "vkEnumerateInstanceExtensionProperties",
1364 "vkEnumerateDeviceExtensionProperties",
1365 "vkGetPhysicalDeviceFeatures",
1366 "vkGetPhysicalDeviceFeatures2KHR",
1367 "vkGetPhysicalDeviceProperties",
1368 "vkGetPhysicalDeviceProperties2KHR",
1369 "vkGetPhysicalDeviceQueueFamilyProperties",
1370 "vkGetPhysicalDeviceMemoryProperties",
1371 "vkGetPhysicalDeviceFormatProperties",
1372 "vkGetPhysicalDeviceImageFormatProperties",
1374 "vkGetBufferMemoryRequirements",
1375 "vkGetBufferMemoryRequirements2KHR",
1376 "vkGetImageMemoryRequirements",
1377 "vkGetImageMemoryRequirements2KHR",
1381 "vkAllocateDescriptorSets",
1382 "vkFreeDescriptorSets",
1383 "vkResetDescriptorPool",
1384 "vkAllocateCommandBuffers",
1385 "vkFreeCommandBuffers",
1386 "vkCreateDisplayModeKHR",
1387 "vkCreateSharedSwapchainsKHR",
1388 "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1389 "vkGetPhysicalDeviceImageFormatProperties2KHR",
1390 "vkGetMemoryAndroidHardwareBufferANDROID",
1393 coreFunctions = [f for f in api.functions if not f.isAlias]
1394 specialFuncs = [f for f in coreFunctions if f.name in specialFuncNames]
1395 createFuncs = [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1396 destroyFuncs = [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1397 dummyFuncs = [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs]
1399 def getHandle (name):
1400 for handle in api.handles:
1401 if handle.name == name[0]:
1403 raise Exception("No such handle: %s" % name)
1405 for function in createFuncs:
1406 objectType = function.arguments[-1].type[:-1]
1407 argsStr = ", ".join([a.name for a in function.arguments[:-1]])
1409 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1411 yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1413 if getHandle(objectType).type == Handle.TYPE_NONDISP:
1414 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1416 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1420 for function in destroyFuncs:
1421 objectArg = function.arguments[-2]
1423 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1425 for arg in function.arguments[:-2]:
1426 yield "\tDE_UNREF(%s);" % arg.name
1428 if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
1429 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1431 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1436 for function in dummyFuncs:
1437 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1439 for arg in function.arguments:
1440 yield "\tDE_UNREF(%s);" % arg.name
1441 if function.returnType != "void":
1442 yield "\treturn VK_SUCCESS;"
1446 def genFuncEntryTable (type, name):
1447 funcs = [f for f in api.functions if f.getType() == type]
1449 for f in api.functions:
1451 refFuncs[f.alias] = f
1453 yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1455 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]):
1461 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1464 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1467 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1470 writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1472 def writeTypeUtil (api, filename):
1473 # Structs filled by API queries are not often used in test code
1474 QUERY_RESULT_TYPES = set([
1475 "VkPhysicalDeviceFeatures",
1476 "VkPhysicalDeviceLimits",
1477 "VkFormatProperties",
1478 "VkImageFormatProperties",
1479 "VkPhysicalDeviceSparseProperties",
1480 "VkQueueFamilyProperties",
1483 "StdVideoH264SpsVuiFlags",
1484 "StdVideoH264SpsFlags",
1485 "StdVideoH264PpsFlags",
1486 "StdVideoDecodeH264PictureInfoFlags",
1487 "StdVideoDecodeH264ReferenceInfoFlags",
1488 "StdVideoDecodeH264MvcElementFlags",
1489 "StdVideoEncodeH264SliceHeaderFlags",
1490 "StdVideoEncodeH264PictureInfoFlags",
1491 "StdVideoEncodeH264RefMgmtFlags",
1492 "StdVideoH265HrdFlags",
1493 "StdVideoH265VpsFlags",
1494 "StdVideoH265SpsVuiFlags",
1495 "StdVideoH265SpsFlags",
1496 "StdVideoH265PpsFlags",
1497 "StdVideoDecodeH265PictureInfoFlags",
1498 "StdVideoDecodeH265ReferenceInfoFlags",
1499 "StdVideoEncodeH265PictureInfoFlags",
1500 "StdVideoEncodeH265SliceHeaderFlags",
1501 "StdVideoEncodeH265ReferenceModificationFlags",
1502 "StdVideoEncodeH265ReferenceInfoFlags",
1504 COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias])
1506 def isSimpleStruct (type):
1507 def hasArrayMember (type):
1508 for member in type.members:
1509 if member.arraySize != '':
1513 def hasCompositeMember (type):
1514 for member in type.members:
1515 if member.getType() in COMPOSITE_TYPES:
1519 return type.typeClass == CompositeType.CLASS_STRUCT and \
1520 type.members[0].getType() != "VkStructureType" and \
1521 not type.name in QUERY_RESULT_TYPES and \
1522 not hasArrayMember(type) and \
1523 not hasCompositeMember(type)
1526 for type in api.compositeTypes:
1527 if not isSimpleStruct(type) or type.isAlias:
1530 name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
1533 yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
1535 yield "\t%s res;" % type.name
1536 for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1538 yield "\treturn res;"
1541 writeInlFile(filename, INL_HEADER, gen())
1543 def writeDriverIds(filename):
1545 driverIdsString = []
1546 driverIdsString.append("static const struct\n"
1548 "\tstd::string driver;\n"
1550 "} driverIds [] =\n"
1553 vulkanCore = readFile(os.path.join(VULKAN_HEADERS_INCLUDE_DIR, "vulkan", "vulkan_core.h"))
1555 items = re.search(r'(?:typedef\s+enum\s+VkDriverId\s*{)((.*\n)*)(?:}\s*VkDriverId\s*;)', vulkanCore).group(1).split(',')
1556 driverItems = dict()
1559 splitted = item.split('=')
1560 key = splitted[0].strip()
1561 value_str = splitted[1].strip()
1562 try: # is this previously defined value?
1563 value = driverItems[value_str]
1568 value_str = "\t// " + value_str
1569 driverItems[key] = value
1570 if not item == items[-1]:
1571 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}," + value_str)
1573 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}" + value_str)
1574 driverItems[key] = value
1576 driverIdsString.append("};")
1578 writeInlFile(filename, INL_HEADER, driverIdsString)
1581 def writeSupportedExtenions(api, filename):
1583 def writeExtensionsForVersions(map):
1586 result.append(" if (coreVersion >= " + str(version) + ")")
1588 for extension in map[version]:
1589 result.append(' dst.push_back("' + extension.name + '");')
1598 for ext in api.extensions:
1599 if ext.versionInCore != None:
1600 if ext.versionInCore[0] == 'instance':
1601 list = instanceMap.get(Version(ext.versionInCore[1:]))
1602 instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1604 list = deviceMap.get(Version(ext.versionInCore[1:]))
1605 deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1606 versionSet.add(Version(ext.versionInCore[1:]))
1608 lines = addVersionDefines(versionSet) + [
1610 "void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""),
1611 "{"] + writeExtensionsForVersions(deviceMap) + [
1614 "void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""),
1615 "{"] + writeExtensionsForVersions(instanceMap) + [
1617 ""] + removeVersionDefines(versionSet)
1618 writeInlFile(filename, INL_HEADER, lines)
1620 def writeExtensionFunctions (api, filename):
1622 def isInstanceExtension (ext):
1623 if ext.name and ext.functions:
1624 if ext.functions[0].getType() == Function.TYPE_INSTANCE:
1629 def isDeviceExtension (ext):
1630 if ext.name and ext.functions:
1631 if ext.functions[0].getType() == Function.TYPE_DEVICE:
1636 def writeExtensionNameArrays ():
1637 instanceExtensionNames = []
1638 deviceExtensionNames = []
1639 for ext in api.extensions:
1640 if ext.name and isInstanceExtension(ext):
1641 instanceExtensionNames += [ext.name]
1642 elif ext.name and isDeviceExtension(ext):
1643 deviceExtensionNames += [ext.name]
1644 yield '::std::string instanceExtensionNames[] =\n{'
1645 for instanceExtName in instanceExtensionNames:
1646 if (instanceExtName == instanceExtensionNames[len(instanceExtensionNames) - 1]):
1647 yield '\t"%s"' % instanceExtName
1649 yield '\t"%s",' % instanceExtName
1651 yield '::std::string deviceExtensionNames[] =\n{'
1652 for deviceExtName in deviceExtensionNames:
1653 if (deviceExtName == deviceExtensionNames[len(deviceExtensionNames) - 1]):
1654 yield '\t"%s"' % deviceExtName
1656 yield '\t"%s",' % deviceExtName
1659 def writeExtensionFunctions (functionType):
1661 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
1662 if functionType == Function.TYPE_INSTANCE:
1663 yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1664 dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
1665 elif functionType == Function.TYPE_DEVICE:
1666 yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1667 dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
1668 for ext in api.extensions:
1671 for func in ext.functions:
1672 if func.getType() == functionType:
1673 # only add functions with same vendor as extension
1674 # this is a workaroudn for entrypoints requiring more
1675 # than one excetions and lack of the dependency in vulkan_core.h
1676 vendor = ext.name.split('_')[1]
1677 if func.name.endswith(vendor):
1678 funcNames.append(func.name)
1680 yield '\tif (extName == "%s")' % ext.name
1682 for funcName in funcNames:
1683 if funcName in dg_list:
1684 yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
1686 yield '\t\tfunctions.push_back("%s");' % funcName
1687 if ext.name == "VK_KHR_device_group":
1688 for dg_func in dg_list:
1689 yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
1692 isFirstWrite = False
1693 if not isFirstWrite:
1694 yield '\tDE_FATAL("Extension name not found");'
1698 for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
1701 for line in writeExtensionFunctions(Function.TYPE_DEVICE):
1704 for line in writeExtensionNameArrays():
1707 writeInlFile(filename, INL_HEADER, lines)
1709 def writeCoreFunctionalities(api, filename):
1710 functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1711 lines = addVersionDefines(api.versions) + [
1713 'enum FunctionOrigin', '{'] + [line for line in indentLines([
1714 '\t' + functionOriginValues[0] + '\t= 0,',
1715 '\t' + functionOriginValues[1] + ',',
1716 '\t' + functionOriginValues[2]])] + [
1719 "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1720 "typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1721 "typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;",
1723 "void initApisMap (ApisMap& apis)",
1725 " apis.clear();"] + [
1726 " apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + str(v) + ", FunctionInfosList()));" for v in api.versions] + [
1730 for index, v in enumerate(api.versions):
1732 apiVersions.append("VK_VERSION_{0}_{1}".format(v.major, v.minor))
1733 # iterate over all functions that are core in latest vulkan version
1734 # note that first item in api.extension array are actually all definitions that are in vulkan.h.in before section with extensions
1735 for fun in api.extensions[0].functions:
1736 if fun.apiVersion in apiVersions:
1737 funcs.append(' apis[' + str(v) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));')
1738 lines = lines + [line for line in indentLines(funcs)] + [""]
1740 lines = lines + ["}", ""] + removeVersionDefines(api.versions)
1741 writeInlFile(filename, INL_HEADER, lines)
1743 def writeDeviceFeatures2(api, filename):
1744 # list of structures that should be tested with getPhysicalDeviceFeatures2
1745 # this is not posible to determine from vulkan_core.h, if new feature structures
1746 # are added they should be manualy added to this list
1747 testedStructures = [
1748 'VkPhysicalDeviceConditionalRenderingFeaturesEXT',
1749 'VkPhysicalDeviceScalarBlockLayoutFeatures',
1750 'VkPhysicalDevicePerformanceQueryFeaturesKHR',
1751 'VkPhysicalDevice16BitStorageFeatures',
1752 'VkPhysicalDeviceMultiviewFeatures',
1753 'VkPhysicalDeviceProtectedMemoryFeatures',
1754 'VkPhysicalDeviceSamplerYcbcrConversionFeatures',
1755 'VkPhysicalDeviceVariablePointersFeatures',
1756 'VkPhysicalDevice8BitStorageFeatures',
1757 'VkPhysicalDeviceShaderAtomicInt64Features',
1758 'VkPhysicalDeviceShaderFloat16Int8Features',
1759 'VkPhysicalDeviceBufferDeviceAddressFeaturesEXT',
1760 'VkPhysicalDeviceBufferDeviceAddressFeatures',
1761 'VkPhysicalDeviceDescriptorIndexingFeatures',
1762 'VkPhysicalDeviceTimelineSemaphoreFeatures',
1763 'VkPhysicalDeviceFragmentDensityMapFeaturesEXT',
1764 'VkPhysicalDeviceFragmentDensityMap2FeaturesEXT',
1765 'VkPhysicalDeviceShaderIntegerDotProductFeaturesKHR',
1767 # helper class used to encapsulate all data needed during generation
1768 class StructureDetail:
1769 def __init__ (self, name):
1770 nameResult = re.search('(.*)Features(.*)', name[len('VkPhysicalDevice'):])
1772 # generate structure type name from structure name
1773 # note that sometimes digits are separated with '_':
1774 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT
1775 # but mostly they are not:
1776 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES
1777 if (nameResult.group(1) == 'FragmentDensityMap2'):
1778 nameSplitUp = ['FRAGMENT', 'DENSITY', 'MAP', '2', 'FEATURES']
1780 nameSplit = re.findall(r'[1-9A-Z]+(?:[a-z1-9]+|[A-Z]*(?=[A-Z]|$))', nameResult.group(1))
1781 nameSplitUp = map(str.upper, nameSplit)
1782 nameSplitUp = list(nameSplitUp) + ['FEATURES']
1783 # check if there is extension suffix
1784 if (len(nameResult.group(2)) != 0):
1785 nameSplitUp.append(nameResult.group(2))
1787 self.sType = 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_' + '_'.join(nameSplitUp)
1788 self.instanceName = 'd' + name[11:]
1789 self.flagName = 'is' + name[16:]
1790 self.extension = None
1794 # helper extension class used in algorith below
1795 class StructureFoundContinueToNextOne(Exception):
1797 testedStructureDetail = [StructureDetail(struct) for struct in testedStructures]
1798 # iterate over all searched structures and find extensions that enable them
1799 for structureDetail in testedStructureDetail:
1801 # iterate over all extensions
1802 for extension in api.extensions[1:]:
1803 # check composite types and typedefs in case extension is part of core
1804 for structureList in [extension.compositeTypes, extension.typedefs]:
1805 # iterate over all structures added by extension
1806 for extensionStructure in structureList:
1807 # compare checked structure name to name of structure from extension
1808 if structureDetail.name == extensionStructure.name:
1809 structureDetail.extension = extension.name
1810 if extension.versionInCore is not None:
1811 structureDetail.major = extension.versionInCore[1]
1812 structureDetail.minor = extension.versionInCore[2]
1813 raise StructureFoundContinueToNextOne
1814 except StructureFoundContinueToNextOne:
1816 for structureDetail in testedStructureDetail:
1817 for compositeType in api.compositeTypes:
1818 if structureDetail.name != compositeType.name:
1820 structureMembers = compositeType.members[2:]
1821 structureDetail.members = [m.name for m in structureMembers]
1822 if structureDetail.major is not None:
1824 # if structure was not added with extension then check if
1825 # it was added directly with one of vulkan versions
1826 apiVersion = compositeType.apiVersion
1827 if apiVersion is None:
1829 structureDetail.major = apiVersion.major
1830 structureDetail.minor = apiVersion.minor
1832 # generate file content
1833 structureDefinitions = []
1834 featureEnabledFlags = []
1835 clearStructures = []
1838 verifyStructures = []
1839 for index, structureDetail in enumerate(testedStructureDetail):
1840 # create two instances of each structure
1841 nameSpacing = '\t' * int((55 - len(structureDetail.name)) / 4)
1842 structureDefinitions.append(structureDetail.name + nameSpacing + structureDetail.instanceName + '[count];')
1843 # create flags that check if proper extension or vulkan version is available
1845 extension = structureDetail.extension
1846 major = structureDetail.major
1847 if extension is not None:
1848 condition = ' checkExtension(properties, "' + extension + '")'
1849 if major is not None:
1851 condition += '\t' * int((39 - len(extension)) / 4) + '|| '
1853 condition += '\t' * 17 + ' '
1854 condition += 'context.contextSupports(vk::ApiVersion(' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
1856 nameSpacing = '\t' * int((40 - len(structureDetail.flagName)) / 4)
1857 featureEnabledFlags.append('const bool ' + structureDetail.flagName + nameSpacing + '=' + condition)
1858 # clear memory of each structure
1859 nameSpacing = '\t' * int((43 - len(structureDetail.instanceName)) / 4)
1860 clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx],' + nameSpacing + '0xFF * ndx, sizeof(' + structureDetail.name + '));')
1861 # construct structure chain
1862 nextInstanceName = 'DE_NULL';
1863 if index < len(testedStructureDetail)-1:
1864 nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
1865 structureChain.append('\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.flagName + ' ? ' + structureDetail.sType + ' : VK_STRUCTURE_TYPE_MAX_ENUM;')
1866 structureChain.append('\t' + structureDetail.instanceName + '[ndx].pNext = ' + nextInstanceName + ';\n')
1867 # construct log section
1868 logStructures.append('if (' + structureDetail.flagName + ')')
1869 logStructures.append('\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;')
1870 #construct verification section
1871 verifyStructures.append('if (' + structureDetail.flagName + ' &&')
1872 for index, m in enumerate(structureDetail.members):
1873 prefix = '\t(' if index == 0 else '\t '
1874 postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
1875 verifyStructures.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
1876 verifyStructures.append('{\n\t\tTCU_FAIL("Mismatch between ' + structureDetail.name + '");\n}')
1877 # construct file content
1879 stream.extend(structureDefinitions)
1881 stream.extend(featureEnabledFlags)
1882 stream.append('\nfor (int ndx = 0; ndx < count; ++ndx)\n{')
1883 stream.extend(clearStructures)
1885 stream.extend(structureChain)
1886 stream.append('\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
1887 '\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
1888 '\textFeatures.pNext = &' + testedStructureDetail[0].instanceName + '[ndx];\n'
1889 '\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);\n}\n')
1890 stream.extend(logStructures)
1892 stream.extend(verifyStructures)
1893 writeInlFile(filename, INL_HEADER, stream)
1895 def generateDeviceFeaturesDefs(src):
1896 # look for definitions
1897 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_FEATURES(\w*)\s*='
1898 matches = re.findall(ptrnSType, src, re.M)
1899 matches = sorted(matches, key=lambda m: m[0])
1900 # construct final list
1902 for sType, sSuffix in matches:
1903 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1904 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Features' + sSuffix.replace('_', '') + ')'
1905 matchStructName = re.search(ptrnStructName, src, re.IGNORECASE)
1907 # handle special cases
1908 if sType == "EXCLUSIVE_SCISSOR":
1909 sType = "SCISSOR_EXCLUSIVE"
1910 elif sType == "ASTC_DECODE":
1911 sType = "ASTC_DECODE_MODE"
1912 if sType in {'VULKAN_1_1', 'VULKAN_1_2'}:
1914 # skip cases that have const pNext pointer
1915 if sType == 'RASTERIZATION_ORDER_ATTACHMENT_ACCESS':
1917 # end handling special cases
1918 ptrnExtensionName = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_EXTENSION_NAME).+$'
1919 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1920 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_SPEC_VERSION).+$'
1921 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1922 defs.append( (sType, '', sSuffix, matchStructName.group(1), \
1923 matchExtensionName.group(0) if matchExtensionName else None,
1924 matchExtensionName.group(1) if matchExtensionName else None,
1925 matchSpecVersion.group(1) if matchSpecVersion else '0') )
1928 def generateDevicePropertiesDefs(src):
1929 # look for definitions
1930 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
1931 matches = re.findall(ptrnSType, src, re.M)
1932 matches = sorted(matches, key=lambda m: m[0])
1933 # construct final list
1935 for sType, sSuffix in matches:
1936 # handle special cases
1937 if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
1939 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
1940 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
1942 sExtSuffix = sSuffix
1943 suffixStart = sSuffix.rfind('_')
1945 sVerSuffix = sSuffix[:suffixStart]
1946 sExtSuffix = sSuffix[suffixStart:]
1947 # handle special case
1951 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1952 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
1953 matchStructName = re.search(ptrnStructName, src, re.M)
1956 if extType == "DISCARD_RECTANGLE":
1957 extType = "DISCARD_RECTANGLES"
1958 elif extType == "DRIVER":
1959 extType = "DRIVER_PROPERTIES"
1960 elif extType == "POINT_CLIPPING":
1961 extType = "MAINTENANCE_2"
1962 elif extType == "SHADER_CORE":
1963 extType = "SHADER_CORE_PROPERTIES"
1964 elif extType == "DRM":
1965 extType = "PHYSICAL_DEVICE_DRM"
1966 # end handling special cases
1967 ptrnExtensionName = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
1968 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1969 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
1970 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1971 defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
1972 matchExtensionName.group(0) if matchExtensionName else None,
1973 matchExtensionName.group(1) if matchExtensionName else None,
1974 matchSpecVersion.group (1) if matchSpecVersion else '0') )
1977 def writeDeviceFeatures(api, dfDefs, filename):
1978 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
1979 # and construct dictionary with all of their attributes
1982 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
1983 for structureType in api.compositeTypes:
1984 match = blobPattern.match(structureType.name)
1986 allMembers = [member.name for member in structureType.members]
1987 vkVersion = match.group(1)
1988 blobMembers[vkVersion] = allMembers[2:]
1989 blobStructs[vkVersion] = set()
1990 initFromBlobDefinitions = []
1991 emptyInitDefinitions = []
1992 # iterate over all feature structures
1993 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
1994 nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
1995 for structureType in api.compositeTypes:
1996 # skip structures that are not feature structures
1997 if not allFeaturesPattern.match(structureType.name):
1999 # skip structures that were previously identified as blobs
2000 if blobPattern.match(structureType.name):
2002 if structureType.isAlias:
2004 # skip sType and pNext and just grab third and next attributes
2005 structureMembers = structureType.members[2:]
2006 notPartOfBlob = True
2007 if nonExtFeaturesPattern.match(structureType.name):
2008 # check if this member is part of any of the blobs
2009 for blobName, blobMemberList in blobMembers.items():
2010 # if just one member is not part of this blob go to the next blob
2011 # (we asume that all members are part of blob - no need to check all)
2012 if structureMembers[0].name not in blobMemberList:
2014 # add another feature structure name to this blob
2015 blobStructs[blobName].add(structureType)
2016 # add specialization for this feature structure
2018 for member in structureMembers:
2019 memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2021 "template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
2024 "}}".format(structureType.name, memberCopying)
2025 initFromBlobDefinitions.append(wholeFunction)
2026 notPartOfBlob = False
2027 # assuming that all members are part of blob, goto next
2029 # add empty template definition as on Fedora there are issue with
2030 # linking using just generic template - all specializations are needed
2032 emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2033 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2034 extensionDefines = []
2035 makeFeatureDescDefinitions = []
2036 featureStructWrappers = []
2037 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dfDefs):
2038 extensionNameDefinition = extName
2039 if not extensionNameDefinition:
2040 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2041 # construct defines with names
2043 extensionDefines.append(extLine)
2045 extensionDefines.append('#define {0} "not_existent_feature"'.format(extensionNameDefinition))
2046 # handle special cases
2047 if sType == "SCISSOR_EXCLUSIVE":
2048 sType = "EXCLUSIVE_SCISSOR"
2049 elif sType == "ASTC_DECODE_MODE":
2050 sType = "ASTC_DECODE"
2051 # end handling special cases
2052 # construct makeFeatureDesc template function definitions
2053 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2054 makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2055 "{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dfDefs)-idx))
2056 # construct CreateFeatureStruct wrapper block
2057 featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2058 # construct method that will check if structure sType is part of blob
2059 blobChecker = "bool isPartOfBlobFeatures (VkStructureType sType)\n{\n" \
2060 "\tconst std::vector<VkStructureType> sTypeVect =" \
2062 # iterate over blobs with list of structures
2063 for blobName in sorted(blobStructs.keys()):
2064 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2065 # iterate over all feature structures in current blob
2066 structuresList = list(blobStructs[blobName])
2067 structuresList = sorted(structuresList, key=lambda s: s.name)
2068 for structType in structuresList:
2069 # find definition of this structure in dfDefs
2070 structName = structType.name
2071 # handle special cases
2072 if structName == 'VkPhysicalDeviceShaderDrawParameterFeatures':
2073 structName = 'VkPhysicalDeviceShaderDrawParametersFeatures'
2074 # end handling special cases
2075 structDef = [s for s in dfDefs if s[3] == structName][0]
2076 sType = structDef[0]
2077 sSuffix = structDef[1] + structDef[2]
2078 # handle special cases
2079 if sType == "SCISSOR_EXCLUSIVE":
2080 sType = "EXCLUSIVE_SCISSOR"
2081 # end handling special cases
2082 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2083 blobChecker += "\t\t{0},\n".format(sTypeName)
2084 blobChecker += "\t};\n" \
2085 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2087 # combine all definition lists
2089 '#include "vkDeviceFeatures.hpp"\n',
2091 stream.extend(extensionDefines)
2093 stream.extend(initFromBlobDefinitions)
2094 stream.append('\n// generic template is not enough for some compilers')
2095 stream.extend(emptyInitDefinitions)
2097 stream.extend(makeFeatureDescDefinitions)
2099 stream.append('static const FeatureStructCreationData featureStructCreationArray[] =\n{')
2100 stream.extend(featureStructWrappers)
2101 stream.append('};\n')
2102 stream.append(blobChecker)
2103 stream.append('} // vk\n')
2104 writeInlFile(filename, INL_HEADER, stream)
2106 def writeDeviceFeatureTest(api, filename):
2108 coreFeaturesPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
2110 # iterate over all feature structures
2111 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
2112 for structureType in api.compositeTypes:
2113 # skip structures that are not feature structures
2114 if not allFeaturesPattern.match(structureType.name):
2116 # skip alias structures
2117 if structureType.isAlias:
2119 # skip sType and pNext and just grab third and next attributes
2120 structureMembers = structureType.members[2:]
2123 for member in structureMembers:
2124 items.append(" FEATURE_ITEM ({0}, {1}),".format(structureType.name, member.name))
2127 "if (const void* featuresStruct = findStructureInChain(const_cast<const void*>(deviceFeatures2.pNext), getStructureType<{0}>()))\n" \
2129 " static const Feature features[] =\n" \
2133 " auto* supportedFeatures = reinterpret_cast<const {0}*>(featuresStruct);\n" \
2134 " checkFeatures(vkp, instance, instanceDriver, physicalDevice, {2}, features, supportedFeatures, queueFamilyIndex, queueCount, queuePriority, numErrors, resultCollector, {3}, emptyDeviceFeatures);\n" \
2136 featureItems.append(testBlock.format(structureType.name, "\n".join(items), len(items), ("DE_NULL" if coreFeaturesPattern.match(structureType.name) else "&extensionNames")))
2139 stream.extend(featureItems)
2140 writeInlFile(filename, INL_HEADER, stream)
2142 def writeDeviceProperties(api, dpDefs, filename):
2143 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2144 # and construct dictionary with all of their attributes
2147 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2148 for structureType in api.compositeTypes:
2149 match = blobPattern.match(structureType.name)
2151 allMembers = [member.name for member in structureType.members]
2152 vkVersion = match.group(1)
2153 blobMembers[vkVersion] = allMembers[2:]
2154 blobStructs[vkVersion] = set()
2155 initFromBlobDefinitions = []
2156 emptyInitDefinitions = []
2157 # iterate over all property structures
2158 allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2159 nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2160 for structureType in api.compositeTypes:
2161 # skip structures that are not property structures
2162 if not allPropertiesPattern.match(structureType.name):
2164 # skip structures that were previously identified as blobs
2165 if blobPattern.match(structureType.name):
2167 if structureType.isAlias:
2169 # skip sType and pNext and just grab third and next attributes
2170 structureMembers = structureType.members[2:]
2171 notPartOfBlob = True
2172 if nonExtPropertiesPattern.match(structureType.name):
2173 # check if this member is part of any of the blobs
2174 for blobName, blobMemberList in blobMembers.items():
2175 # if just one member is not part of this blob go to the next blob
2176 # (we asume that all members are part of blob - no need to check all)
2177 if structureMembers[0].name not in blobMemberList:
2179 # add another property structure name to this blob
2180 blobStructs[blobName].add(structureType)
2181 # add specialization for this property structure
2183 for member in structureMembers:
2184 if not member.arraySize:
2185 # handle special case
2186 if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2187 blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2188 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2189 # end handling special case
2191 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2193 memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type[0], member.arraySize[1:-1])
2195 "template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2198 "}}".format(structureType.name, memberCopying)
2199 initFromBlobDefinitions.append(wholeFunction)
2200 notPartOfBlob = False
2201 # assuming that all members are part of blob, goto next
2203 # add empty template definition as on Fedora there are issue with
2204 # linking using just generic template - all specializations are needed
2206 emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2207 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2208 extensionDefines = []
2209 makePropertyDescDefinitions = []
2210 propertyStructWrappers = []
2211 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dpDefs):
2212 extensionNameDefinition = extName
2213 if not extensionNameDefinition:
2214 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2215 # construct defines with names
2217 extensionDefines.append(extLine)
2219 extensionDefines.append('#define {0} "core_property"'.format(extensionNameDefinition))
2220 # construct makePropertyDesc template function definitions
2221 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2222 makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2223 "{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dpDefs)-idx))
2224 # construct CreateProperty struct wrapper block
2225 propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2226 # construct method that will check if structure sType is part of blob
2227 blobChecker = "bool isPartOfBlobProperties (VkStructureType sType)\n{\n" \
2228 "\tconst std::vector<VkStructureType> sTypeVect =" \
2230 # iterate over blobs with list of structures
2231 for blobName in sorted(blobStructs.keys()):
2232 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2233 # iterate over all feature structures in current blob
2234 structuresList = list(blobStructs[blobName])
2235 structuresList = sorted(structuresList, key=lambda s: s.name)
2236 for structType in structuresList:
2237 # find definition of this structure in dpDefs
2238 structName = structType.name
2239 structDef = [s for s in dpDefs if s[3] == structName][0]
2240 sType = structDef[0]
2241 sSuffix = structDef[1] + structDef[2]
2242 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2243 blobChecker += "\t\t{0},\n".format(sTypeName)
2244 blobChecker += "\t};\n" \
2245 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2247 # combine all definition lists
2249 '#include "vkDeviceProperties.hpp"\n',
2251 stream.extend(extensionDefines)
2253 stream.extend(initFromBlobDefinitions)
2254 stream.append('\n// generic template is not enough for some compilers')
2255 stream.extend(emptyInitDefinitions)
2257 stream.extend(makePropertyDescDefinitions)
2259 stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2260 stream.extend(propertyStructWrappers)
2261 stream.append('};\n')
2262 stream.append(blobChecker)
2263 stream.append('} // vk\n')
2264 writeInlFile(filename, INL_HEADER, stream)
2266 def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
2268 for _, _, _, extStruct, _, _, _ in dfDefs:
2269 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2270 stream.append(pattern.format(extStruct, nameSubStr))
2271 writeInlFile(filename, INL_HEADER, indentLines(stream))
2273 def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
2274 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
2275 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2277 def writeDeviceFeaturesContextDecl(dfDefs, filename):
2278 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2279 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2281 def writeDeviceFeaturesContextDefs(dfDefs, filename):
2282 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2283 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2285 def genericDevicePropertiesWriter(dfDefs, pattern, filename):
2287 for _, _, _, extStruct, _, _, _ in dfDefs:
2288 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2289 if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
2291 stream.append(pattern.format(extStruct, nameSubStr))
2292 writeInlFile(filename, INL_HEADER, indentLines(stream))
2294 def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
2295 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
2296 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2298 def writeDevicePropertiesContextDecl(dfDefs, filename):
2299 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2300 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2302 def writeDevicePropertiesContextDefs(dfDefs, filename):
2303 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2304 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2306 def writeMandatoryFeatures(api, filename):
2311 for _, data in api.additionalExtensionData:
2312 if 'mandatory_features' not in data.keys():
2314 # sort to have same results for py2 and py3
2315 listStructFeatures = sorted(data['mandatory_features'].items(), key=lambda tup: tup[0])
2316 for structure, featuresList in listStructFeatures:
2317 for featureData in featuresList:
2318 assert('features' in featureData.keys())
2319 assert('requirements' in featureData.keys())
2320 requirements = featureData['requirements']
2321 dictData.append( [ structure, featureData['features'], requirements ])
2322 if structure == 'VkPhysicalDeviceFeatures':
2324 # if structure is not in dict construct name of variable and add is as a first item
2325 if (structure not in dictStructs):
2326 dictStructs[structure] = [structure[2:3].lower() + structure[3:]]
2327 # add first requirement if it is unique
2328 if requirements and (requirements[0] not in dictStructs[structure]):
2329 dictStructs[structure].append(requirements[0])
2331 stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
2332 '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
2333 '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
2335 '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
2336 '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
2337 '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
2339 '\ttcu::TestLog& log = context.getTestContext().getLog();',
2340 '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
2341 '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
2342 '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
2343 '\tvoid** nextPtr = &coreFeatures.pNext;',
2346 listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
2347 for k, v in listStruct:
2348 if (v[1].startswith("ApiVersion")):
2349 cond = '\tif (context.contextSupports(vk::' + v[1] + '))'
2351 cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[1] + '"))'
2352 stream.extend(['\tvk::' + k + ' ' + v[0]+ ';',
2353 '\tdeMemset(&' + v[0] + ', 0, sizeof(' + v[0] + '));',
2358 for i, req in enumerate(reqs) :
2359 if (req.startswith("ApiVersion")):
2360 cond = cond + 'context.contextSupports(vk::' + req + ')'
2362 cond = cond + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2363 if i+1 < len(reqs) :
2364 cond = cond + ' || '
2366 stream.append('\t' + cond)
2367 stream.extend(['\t{',
2368 '\t\t' + v[0] + '.sType = getStructureType<' + k + '>();',
2369 '\t\t*nextPtr = &' + v[0] + ';',
2370 '\t\tnextPtr = &' + v[0] + '.pNext;',
2373 stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
2374 '\tbool result = true;',
2379 structName = 'coreFeatures.features';
2380 if v[0] != 'VkPhysicalDeviceFeatures' :
2381 structName = dictStructs[v[0]][0]
2384 for i, req in enumerate(v[2]) :
2385 if (req.startswith("ApiVersion")):
2386 condition = condition + 'context.contextSupports(vk::' + req + ')'
2388 condition = condition + req
2390 condition = condition + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2391 if i+1 < len(v[2]) :
2392 condition = condition + ' && '
2393 condition = condition + ' )'
2394 stream.append('\t' + condition)
2395 stream.append('\t{')
2396 # Don't need to support an AND case since that would just be another line in the .txt
2398 stream.append('\t\tif ( ' + structName + '.' + v[1][0] + ' == VK_FALSE )')
2401 for i, feature in enumerate(v[1]):
2403 condition = condition + ' && '
2404 condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
2405 condition = condition + ' )'
2406 stream.append('\t\t' + condition)
2407 featureSet = " or ".join(v[1])
2408 stream.extend(['\t\t{',
2409 '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
2410 '\t\t\tresult = false;',
2414 stream.append('\treturn result;')
2415 stream.append('}\n')
2416 writeInlFile(filename, INL_HEADER, stream)
2418 def writeExtensionList(api, filename, extensionType):
2420 for extensionName, data in api.additionalExtensionData:
2421 # make sure extension name starts with VK_KHR
2422 if not extensionName.startswith('VK_KHR'):
2424 # make sure that this extension was registered
2425 if 'register_extension' not in data.keys():
2427 # make sure extension has proper type
2428 if extensionType == data['register_extension']['type']:
2429 extensionList.append(extensionName)
2430 extensionList.sort()
2431 # write list of all found extensions
2433 stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(extensionType.title()))
2434 for n in extensionList:
2435 stream.append('\t"' + n + '",')
2436 stream.append('};\n')
2437 writeInlFile(filename, INL_HEADER, stream)
2439 def preprocessTopInclude(src, dir):
2440 pattern = r'#include\s+"([^\n]+)"'
2442 inc = re.search(pattern, src)
2445 incFileName = inc.string[inc.start(1):inc.end(1)]
2446 patternIncNamed = r'#include\s+"' + incFileName + '"'
2447 incBody = readFile(os.path.join(dir, incFileName)) if incFileName != 'vk_platform.h' else ''
2448 incBodySanitized = re.sub(pattern, '', incBody)
2449 bodyEndSanitized = re.sub(patternIncNamed, '', src[inc.end(0):])
2450 src = src[0:inc.start(0)] + incBodySanitized + bodyEndSanitized
2453 if __name__ == "__main__":
2455 outputPath = os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan")
2456 # if argument was specified it is interpreted as a path to which .inl files will be written
2457 if len(sys.argv) > 1:
2458 outputPath = str(sys.argv[1])
2460 # Generate vulkan headers from vk.xml
2461 currentDir = os.getcwd()
2462 pythonExecutable = sys.executable or "python"
2463 os.chdir(os.path.join(VULKAN_HEADERS_INCLUDE_DIR, "..", "xml"))
2478 "vulkan_xlib_xrandr.h",
2480 for target in targets:
2481 execute([pythonExecutable, "../scripts/genvk.py", "-o", "../include/vulkan", target])
2482 os.chdir(currentDir)
2484 # Read all .h files and make sure vulkan_core.h is first out of vulkan files
2485 targets.remove("vulkan_core.h")
2487 vkFilesWithCatalog = [os.path.join("vulkan", f) for f in targets]
2488 first = [os.path.join("vk_video", "vulkan_video_codecs_common.h"), os.path.join("vulkan", "vulkan_core.h")]
2489 allFilesWithCatalog = first + vkFilesWithCatalog
2492 for file in allFilesWithCatalog:
2493 src += preprocessTopInclude(readFile(os.path.join(VULKAN_HEADERS_INCLUDE_DIR,file)), VULKAN_HEADERS_INCLUDE_DIR)
2495 src = re.sub('\s*//[^\n]*', '', src)
2496 src = re.sub('\n\n', '\n', src)
2500 platformFuncs = [Function.TYPE_PLATFORM]
2501 instanceFuncs = [Function.TYPE_INSTANCE]
2502 deviceFuncs = [Function.TYPE_DEVICE]
2504 dfd = generateDeviceFeaturesDefs(src)
2505 writeDeviceFeatures (api, dfd, os.path.join(outputPath, "vkDeviceFeatures.inl"))
2506 writeDeviceFeaturesDefaultDeviceDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
2507 writeDeviceFeaturesContextDecl (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDecl.inl"))
2508 writeDeviceFeaturesContextDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDefs.inl"))
2509 writeDeviceFeatureTest (api, os.path.join(outputPath, "vkDeviceFeatureTest.inl"))
2511 dpd = generateDevicePropertiesDefs(src)
2512 writeDeviceProperties (api, dpd, os.path.join(outputPath, "vkDeviceProperties.inl"))
2514 writeDevicePropertiesDefaultDeviceDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
2515 writeDevicePropertiesContextDecl (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDecl.inl"))
2516 writeDevicePropertiesContextDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDefs.inl"))
2518 writeHandleType (api, os.path.join(outputPath, "vkHandleType.inl"))
2519 writeBasicTypes (api, os.path.join(outputPath, "vkBasicTypes.inl"))
2520 writeCompositeTypes (api, os.path.join(outputPath, "vkStructTypes.inl"))
2521 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualPlatformInterface.inl"), platformFuncs, False)
2522 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualInstanceInterface.inl"), instanceFuncs, False)
2523 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualDeviceInterface.inl"), deviceFuncs, False)
2524 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcretePlatformInterface.inl"), platformFuncs, True)
2525 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteInstanceInterface.inl"), instanceFuncs, True)
2526 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteDeviceInterface.inl"), deviceFuncs, True)
2527 writeFunctionPtrTypes (api, os.path.join(outputPath, "vkFunctionPointerTypes.inl"))
2528 writeFunctionPointers (api, os.path.join(outputPath, "vkPlatformFunctionPointers.inl"), platformFuncs)
2529 writeFunctionPointers (api, os.path.join(outputPath, "vkInstanceFunctionPointers.inl"), instanceFuncs)
2530 writeFunctionPointers (api, os.path.join(outputPath, "vkDeviceFunctionPointers.inl"), deviceFuncs)
2531 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr")
2532 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitInstanceFunctionPointers.inl"), instanceFuncs)
2533 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitDeviceFunctionPointers.inl"), deviceFuncs)
2534 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver")
2535 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver")
2536 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver")
2537 writeStrUtilProto (api, os.path.join(outputPath, "vkStrUtil.inl"))
2538 writeStrUtilImpl (api, os.path.join(outputPath, "vkStrUtilImpl.inl"))
2539 writeRefUtilProto (api, os.path.join(outputPath, "vkRefUtil.inl"))
2540 writeRefUtilImpl (api, os.path.join(outputPath, "vkRefUtilImpl.inl"))
2541 writeStructTraitsImpl (api, os.path.join(outputPath, "vkGetStructureTypeImpl.inl"))
2542 writeNullDriverImpl (api, os.path.join(outputPath, "vkNullDriverImpl.inl"))
2543 writeTypeUtil (api, os.path.join(outputPath, "vkTypeUtil.inl"))
2544 writeSupportedExtenions (api, os.path.join(outputPath, "vkSupportedExtensions.inl"))
2545 writeCoreFunctionalities (api, os.path.join(outputPath, "vkCoreFunctionalities.inl"))
2546 writeExtensionFunctions (api, os.path.join(outputPath, "vkExtensionFunctions.inl"))
2547 writeDeviceFeatures2 (api, os.path.join(outputPath, "vkDeviceFeatures2.inl"))
2548 writeMandatoryFeatures (api, os.path.join(outputPath, "vkMandatoryFeatures.inl"))
2549 writeExtensionList (api, os.path.join(outputPath, "vkInstanceExtensions.inl"), 'instance')
2550 writeExtensionList (api, os.path.join(outputPath, "vkDeviceExtensions.inl"), 'device')
2551 writeDriverIds ( os.path.join(outputPath, "vkKnownDriverIds.inl"))
2552 writeObjTypeImpl (api, os.path.join(outputPath, "vkObjTypeImpl.inl"))
2553 # NOTE: when new files are generated then they should also be added to the
2554 # vk-gl-cts\external\vulkancts\framework\vulkan\CMakeLists.txt outputs list