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 #-------------------------------------------------------------------------
27 from itertools import chain
28 from collections import OrderedDict
30 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
32 from build.common import DEQP_DIR
33 from khr_util.format import indentLines, writeInlFile
35 VULKAN_H_DIR = os.path.join(os.path.dirname(__file__), "src")
36 VULKAN_DIR = os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan")
39 /* WARNING: This is auto-generated file. Do not modify, since changes will
40 * be lost! Modify the generating script instead.
45 ("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE", "size_t"),
46 ("VK_MAX_EXTENSION_NAME_SIZE", "size_t"),
47 ("VK_MAX_DRIVER_NAME_SIZE", "size_t"),
48 ("VK_MAX_DRIVER_INFO_SIZE", "size_t"),
49 ("VK_UUID_SIZE", "size_t"),
50 ("VK_LUID_SIZE", "size_t"),
51 ("VK_MAX_MEMORY_TYPES", "size_t"),
52 ("VK_MAX_MEMORY_HEAPS", "size_t"),
53 ("VK_MAX_DESCRIPTION_SIZE", "size_t"),
54 ("VK_MAX_DEVICE_GROUP_SIZE", "size_t"),
55 ("VK_ATTACHMENT_UNUSED", "uint32_t"),
56 ("VK_SUBPASS_EXTERNAL", "uint32_t"),
57 ("VK_QUEUE_FAMILY_IGNORED", "uint32_t"),
58 ("VK_QUEUE_FAMILY_EXTERNAL", "uint32_t"),
59 ("VK_REMAINING_MIP_LEVELS", "uint32_t"),
60 ("VK_REMAINING_ARRAY_LAYERS", "uint32_t"),
61 ("VK_WHOLE_SIZE", "vk::VkDeviceSize"),
62 ("VK_TRUE", "vk::VkBool32"),
63 ("VK_FALSE", "vk::VkBool32"),
68 (["Display","*"], ["XlibDisplayPtr"], "void*"),
69 (["Window"], ["XlibWindow"], "uintptr_t",),
70 (["VisualID"], ["XlibVisualID"], "uint32_t"),
73 (["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"),
74 (["xcb_window_t"], ["XcbWindow"], "uintptr_t"),
75 (["xcb_visualid_t"], ["XcbVisualid"], "uint32_t"),
77 # VK_KHR_wayland_surface
78 (["struct", "wl_display","*"], ["WaylandDisplayPtr"], "void*"),
79 (["struct", "wl_surface", "*"], ["WaylandSurfacePtr"], "void*"),
82 (["MirConnection", "*"], ["MirConnectionPtr"], "void*"),
83 (["MirSurface", "*"], ["MirSurfacePtr"], "void*"),
85 # VK_KHR_android_surface
86 (["ANativeWindow", "*"], ["AndroidNativeWindowPtr"], "void*"),
88 # VK_KHR_win32_surface
89 (["HINSTANCE"], ["Win32InstanceHandle"], "void*"),
90 (["HWND"], ["Win32WindowHandle"], "void*"),
91 (["HANDLE"], ["Win32Handle"], "void*"),
92 (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"),
93 (["AHardwareBuffer", "*"], ["AndroidHardwareBufferPtr"], "void*"),
94 (["HMONITOR"], ["Win32MonitorHandle"], "void*"),
95 (["LPCWSTR"], ["Win32LPCWSTR"], "const void*"),
97 # VK_EXT_acquire_xlib_display
98 (["RROutput"], ["RROutput"], "void*"),
100 (["zx_handle_t"], ["zx_handle_t"], "int32_t"),
101 (["GgpFrameToken"], ["GgpFrameToken"], "int32_t"),
102 (["GgpStreamDescriptor"], ["GgpStreamDescriptor"], "int32_t"),
103 (["CAMetalLayer"], ["CAMetalLayer"], "void*"),
106 PLATFORM_TYPE_NAMESPACE = "pt"
108 TYPE_SUBSTITUTIONS = [
109 ("bool32_t", "deUint32"),
112 ("DWORD", "deUint32"),
113 ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
116 EXTENSION_POSTFIXES = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK", "FUCHSIA", "GGP", "AMD"]
117 EXTENSION_POSTFIXES_STANDARD = ["KHR", "EXT"]
119 def prefixName (prefix, name):
120 name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
121 name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
124 name = name.replace("YCB_CR_", "YCBCR_")
125 name = name.replace("WIN_32_", "WIN32_")
126 name = name.replace("8_BIT_", "8BIT_")
127 name = name.replace("16_BIT_", "16BIT_")
128 name = name.replace("INT_64_", "INT64_")
129 name = name.replace("D_3_D_12_", "D3D12_")
130 name = name.replace("IOSSURFACE_", "IOS_SURFACE_")
131 name = name.replace("MAC_OS", "MACOS_")
132 name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_")
133 name = name.replace("VIEWPORT_W", "VIEWPORT_W_")
134 name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES")
135 name = name.replace("PHYSICAL_DEVICE_SHADER_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES")
136 name = name.replace("_PCIBUS_", "_PCI_BUS_")
137 name = name.replace("ASTCD", "ASTC_D")
138 name = name.replace("AABBNV", "AABB_NV")
139 name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
140 name = name.replace("SMBUILTINS", "SM_BUILTINS")
141 name = name.replace("ASTCHDRFEATURES", "ASTC_HDR_FEATURES")
142 name = name.replace("UINT_8", "UINT8")
143 name = name.replace("VULKAN_11_FEATURES", "VULKAN_1_1_FEATURES")
144 name = name.replace("VULKAN_11_PROPERTIES", "VULKAN_1_1_PROPERTIES")
145 name = name.replace("VULKAN_12_FEATURES", "VULKAN_1_2_FEATURES")
146 name = name.replace("VULKAN_12_PROPERTIES", "VULKAN_1_2_PROPERTIES")
147 name = name.replace("INT_8_", "INT8_")
148 name = name.replace("AABBNV", "AABB_NV")
149 name = name.replace("_H_264_", "_H264_")
150 name = name.replace("_H_265_", "_H265_")
151 name = name.replace("RDMAFEATURES", "RDMA_FEATURES")
157 def __init__ (self, versionTuple):
158 self.major = versionTuple[0]
159 self.minor = versionTuple[1]
160 self.patch = versionTuple[2]
164 return "VK_API_VERSION_%d_%d" % (self.major, self.minor)
165 return '0x%Xu' % (hash(self))
167 def isStandardVersion (self):
174 def getBestRepresentation (self):
175 if self.isStandardVersion():
176 return self.getInHex()
177 return self.getDefineName()
179 def getDefineName (self):
180 return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch)
183 return (self.major << 22) | (self.minor << 12) | self.patch
185 def __eq__ (self, other):
186 return self.major == other.major and self.minor == other.minor and self.patch == other.patch
189 return self.getBestRepresentation()
196 def __init__ (self, type, name):
202 def getHandleType (self):
203 return prefixName("HANDLE_TYPE_", self.name)
205 def checkAliasValidity (self):
209 return '%s (%s, %s)' % (self.name, self.alias, self.isAlias)
212 def __init__ (self, type, name, value):
220 return '%s = %s (%s)' % (self.name, self.value, self.type)
223 def __init__ (self, name, values):
229 def checkAliasValidity (self):
230 if self.alias != None:
231 if len(self.values) != len(self.alias.values):
232 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
233 for index, value in enumerate(self.values):
234 aliasVal = self.alias.values[index]
235 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
236 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
239 return '%s (%s) %s' % (self.name, self.alias, self.values)
242 def __init__ (self, name, values):
248 def checkAliasValidity (self):
249 if self.alias != None:
250 if len(self.values) != len(self.alias.values):
251 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
252 for index, value in enumerate(self.values):
253 aliasVal = self.alias.values[index]
254 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
255 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
258 return '%s (%s)' % (self.name, self.alias)
261 def __init__ (self, type, name, arraySizeOrFieldWidth):
262 type = type.replace('*',' *').replace('&',' &')
263 for src, dst in TYPE_SUBSTITUTIONS:
264 type = type.replace(src, dst)
265 self.type = type.split(' ')
266 for platformType, substitute, compat in PLATFORM_TYPES:
267 range = self.contains(self.type, platformType)
269 self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:]
272 if len(arraySizeOrFieldWidth) > 0 and arraySizeOrFieldWidth[0] == ':':
274 self.fieldWidth = arraySizeOrFieldWidth
276 self.arraySize = arraySizeOrFieldWidth
279 def contains(self, big, small):
280 for i in range(len(big)-len(small)+1):
281 for j in range(len(small)):
282 if big[i+j] != small[j]:
285 return i, i+len(small)
289 return ' '.join(self.type).replace(' *','*').replace(' &','&')
291 def getAsString (self, separator):
292 return '%s%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize, self.fieldWidth)
294 def getAsStringForArgumentList (self, separator):
295 return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize)
298 return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize)
300 def __eq__ (self, other):
301 if len(self.type) != len(other.type):
303 for index, type in enumerate(self.type):
304 if "*" == type or "&" == type or "const" == type or "volatile" == type:
305 if type != other.type[index]:
307 elif type != other.type[index] and \
308 type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \
309 other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD):
311 return self.arraySize == other.arraySize
313 def __ne__ (self, other):
314 return not self == other
320 def __init__ (self, typeClass, name, members, apiVersion = None):
321 self.typeClass = typeClass
323 self.members = members
326 self.apiVersion = apiVersion
328 def getClassName (self):
329 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
330 return names[self.typeClass]
332 def checkAliasValidity (self):
333 if self.alias != None:
334 if len(self.members) != len(self.alias.members):
335 raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name))
336 for index, member in enumerate(self.members ):
338 #if member != self.alias.members[index]:
339 #raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name))
340 #raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".")
342 return '%s (%s)' % (self.name, self.alias)
345 TYPE_PLATFORM = 0 # Not bound to anything
346 TYPE_INSTANCE = 1 # Bound to VkInstance
347 TYPE_DEVICE = 2 # Bound to VkDevice
349 def __init__ (self, name, returnType, arguments, apiVersion = None):
351 self.returnType = returnType
352 self.arguments = arguments
355 self.apiVersion = apiVersion
359 if self.name == "vkGetInstanceProcAddr":
360 return Function.TYPE_PLATFORM
361 assert len(self.arguments) > 0
362 firstArgType = self.arguments[0].getType()
363 if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
364 return Function.TYPE_INSTANCE
365 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
366 return Function.TYPE_DEVICE
368 return Function.TYPE_PLATFORM
370 def checkAliasValidity (self):
371 if self.alias != None:
372 if len(self.arguments) != len(self.alias.arguments):
373 raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name))
374 if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)):
375 raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name))
376 for index, argument in enumerate(self.arguments):
377 if argument != self.alias.arguments[index]:
378 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))
381 return '%s (%s)' % (self.name, self.alias)
384 def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, typedefs, versionInCore):
386 self.definitions = definitions
387 self.additionalDefs = additionalDefinitions
388 self.handles = handles
390 self.bitfields = bitfields
391 self.compositeTypes = compositeTypes
392 self.functions = functions
393 self.typedefs = typedefs
394 self.versionInCore = versionInCore
397 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)
400 def __init__ (self, versions, definitions, handles, enums, bitfields, bitfields64, compositeTypes, functions, extensions):
401 self.versions = versions
402 self.definitions = definitions
403 self.handles = handles
405 self.bitfields = bitfields
406 self.bitfields64 = bitfields64
407 self.compositeTypes = compositeTypes
408 self.functions = functions # \note contains extension functions as well
409 self.extensions = extensions
411 def readFile (filename):
412 with open(filename, 'rt') as f:
415 IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*'
416 WIDTH_PTRN = r'[:0-9]*'
417 TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
419 def getInterfaceName (function):
420 assert function.name[:2] == "vk"
421 return function.name[2].lower() + function.name[3:]
423 def getFunctionTypeName (function):
424 assert function.name[:2] == "vk"
425 return function.name[2:] + "Func"
427 def endsWith (str, postfix):
428 return str[-len(postfix):] == postfix
430 def splitNameExtPostfix (name):
431 knownExtPostfixes = EXTENSION_POSTFIXES
432 for postfix in knownExtPostfixes:
433 if endsWith(name, postfix):
434 return (name[:-len(postfix)], postfix)
437 def getBitEnumNameForBitfield (bitfieldName):
438 bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
439 assert bitfieldName[-1] == "s"
440 return bitfieldName[:-1] + "Bits" + postfix
442 def getBitfieldNameForBitEnum (bitEnumName):
443 bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
444 assert bitEnumName[-4:] == "Bits"
445 return bitEnumName[:-4] + "s" + postfix
447 def parsePreprocDefinedValue (src, name):
448 value = parsePreprocDefinedValueOptional(src, name)
450 raise Exception("No such definition: %s" % name)
453 def parsePreprocDefinedValueOptional (src, name):
454 definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
455 if definition is None:
457 value = definition.group(1).strip()
458 if value == "UINT32_MAX":
462 def parseEnum (name, src):
463 keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,\n}]+)\s*[,\n}]'
464 return Enum(name, re.findall(keyValuePtrn, src))
466 # \note Parses raw enums, some are mapped to bitfields later
467 def parseEnums (src):
468 matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
470 for enumname, contents, typename in matches:
471 enums.append(parseEnum(typename, contents))
474 def parseCompositeType (type, name, src):
475 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\]|\s*:\s*[0-9]+)*)\s*;'
476 matches = re.findall(typeNamePtrn, src)
477 members = [Variable(t.strip(), n.strip(), a.replace(' ', '')) for t, n, a, _ in matches]
478 return CompositeType(type, name, members)
480 def parseCompositeTypes (src):
481 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
482 matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
484 for type, structname, contents, typename in matches:
485 types.append(parseCompositeType(typeMap[type], typename, contents))
488 def parseCompositeTypesByVersion (src, versionsData):
490 # find occurence of extension is a place where
491 # we cant assign apiVersion to found structures
492 extPtrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
493 versionEnd = re.search(extPtrn, src)
494 versions = [Version((v[2], v[3], 0)) for v in versionsData]
495 versions.append(None)
497 # construct list of locations where version definitions start, and add the end of the file to it
498 sectionLocations = [versionDef[1] for versionDef in versionsData]
499 sectionLocations.append(versionEnd.start())
500 sectionLocations.append(len(src))
502 # construct function declaration pattern
503 ptrn = r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;'
504 regPtrn = re.compile(ptrn)
506 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
508 # iterate over all versions and find all structure definitions
509 for index, v in enumerate(versions):
510 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
511 for type, structname, contents, typename in matches:
512 compositeType = parseCompositeType(typeMap[type], typename, contents)
513 compositeType.apiVersion = v
514 types.append(compositeType)
517 def parseVersions (src):
518 # returns list of tuples each with four items:
519 # 1. string with version token (without ' 1' at the end)
520 # 2. starting point off version specific definitions in vulkan.h.in
521 # 3. major version number
522 # 4. minor version number
523 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)]
525 def parseHandles (src):
526 matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
528 typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
529 for type, name in matches:
530 handle = Handle(typeMap[type], name)
531 handles.append(handle)
534 def parseArgList (src):
535 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*'
537 for rawArg in src.split(','):
538 m = re.search(typeNamePtrn, rawArg)
539 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
542 def removeTypeExtPostfix (name):
543 for extPostfix in EXTENSION_POSTFIXES_STANDARD:
544 if endsWith(name, extPostfix):
545 return name[0:-len(extPostfix)]
548 def populateExtensionAliases(allObjects, extensionObjects):
549 for object in extensionObjects:
550 withoutPostfix = removeTypeExtPostfix(object.name)
551 if withoutPostfix != None and withoutPostfix in allObjects:
552 # max 1 alias is assumed by functions in this file
553 assert allObjects[withoutPostfix].alias == None
554 allObjects[withoutPostfix].alias = object
555 object.isAlias = True
556 for object in extensionObjects:
557 object.checkAliasValidity()
559 def populateAliasesWithTypedefs (objects, src):
561 for object in objects:
562 objectsByName[object.name] = object
563 ptrn = r'\s*typedef\s+' + object.name + r'\s+([^;]+)'
564 stash = re.findall(ptrn, src)
566 objExt = copy.deepcopy(object)
567 objExt.name = stash[0]
568 object.alias = objExt
569 objExt.isAlias = True
570 objects.append(objExt)
572 def removeAliasedValues (enum):
574 for name, value in enum.values:
575 valueByName[name] = value
577 def removeDefExtPostfix (name):
578 for extPostfix in EXTENSION_POSTFIXES:
579 if endsWith(name, "_" + extPostfix):
580 return name[0:-(len(extPostfix)+1)]
584 for name, value in enum.values:
585 withoutPostfix = removeDefExtPostfix(name)
586 if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value:
588 newValues.append((name, value))
589 enum.values = newValues
591 def parseFunctions (src):
592 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
593 matches = re.findall(ptrn, src)
595 for returnType, name, argList in matches:
596 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
599 def parseFunctionsByVersion (src, versions):
600 # construct list of locations where version definitions start, and add the end of the file to it
601 sectionLocations = [versionDef[1] for versionDef in versions]
602 sectionLocations.append(len(src))
604 # construct function declaration pattern
605 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
606 regPtrn = re.compile(ptrn)
609 # iterate over all versions and find all function definitions
610 for index, v in enumerate(versions):
611 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
612 for returnType, name, argList in matches:
613 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), v[0]))
616 def splitByExtension (src):
617 ptrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
618 # Construct long pattern that will be used to split whole source by extensions
619 match = "#define\s+("
620 for part in re.finditer(ptrn, src):
621 match += part.group(1)+"|"
622 match = match[:-1] + ")\s+1"
623 parts = re.split(match, src)
625 # First part is core, following tuples contain extension name and all its definitions
626 byExtension = [(None, parts[0])]
627 for ndx in range(1, len(parts), 2):
628 byExtension.append((parts[ndx], parts[ndx+1]))
631 def parseDefinitions (extensionName, src):
633 def skipDefinition (extensionName, definition):
634 if extensionName == None:
636 extNameUpper = extensionName.upper()
637 extNameUpper = extNameUpper.replace("VK_KHR_SYNCHRONIZATION2", "VK_KHR_SYNCHRONIZATION_2")
638 extNameUpper = extNameUpper.replace("VK_INTEL_SHADER_INTEGER_FUNCTIONS2", "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2")
639 extNameUpper = extNameUpper.replace("VK_EXT_ROBUSTNESS2", "VK_EXT_ROBUSTNESS_2")
640 extNameUpper = extNameUpper.replace("VK_EXT_FRAGMENT_DENSITY_MAP2", "VK_EXT_FRAGMENT_DENSITY_MAP_2")
641 extNameUpper = extNameUpper.replace("VK_AMD_SHADER_CORE_PROPERTIES2", "VK_AMD_SHADER_CORE_PROPERTIES_2")
642 extNameUpper = extNameUpper.replace("VK_EXT_EXTENDED_DYNAMIC_STATE2", "VK_EXT_EXTENDED_DYNAMIC_STATE_2")
644 if definition[0].startswith(extNameUpper) and definition[1].isdigit():
646 if definition[0].startswith(extNameUpper):
648 if definition[1].isdigit():
652 ptrn = r'#define\s+([^\s]+)\s+([^\r\n]+)'
653 matches = re.findall(ptrn, src)
655 return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)]
657 def parseTypedefs (src):
659 ptrn = r'typedef\s+([^\s]+)\s+([^\r\n]+);'
660 matches = re.findall(ptrn, src)
662 return [Definition(None, match[0], match[1]) for match in matches]
664 def parseExtensions (src, versions, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions):
666 def getCoreVersion (extensionName, extensionsData):
667 # returns None when extension was not added to core for any Vulkan version
668 # returns array containing DEVICE or INSTANCE string followed by the vulkan version in which this extension is core
669 # note that this function is also called for vulkan 1.0 source for which extName is None
670 if not extensionName:
672 ptrn = extensionName + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)'
673 coreVersion = re.search(ptrn, extensionsData, re.I)
674 if coreVersion != None:
675 return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]]
678 extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
679 splitSrc = splitByExtension(src)
681 functionsByName = {function.name: function for function in allFunctions}
682 compositeTypesByName = {compType.name: compType for compType in allCompositeTypes}
683 enumsByName = {enum.name: enum for enum in allEnums}
684 bitfieldsByName = {bitfield.name: bitfield for bitfield in allBitfields}
685 handlesByName = {handle.name: handle for handle in allHandles}
686 definitionsByName = {definition.name: definition for definition in allDefinitions}
688 for extensionName, extensionSrc in splitSrc:
689 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValueOptional(extensionSrc, v.getInHex())) for v in versions]
690 definitions.extend([Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS])
691 definitions = [definition for definition in definitions if definition.value != None]
692 additionalDefinitions = parseDefinitions(extensionName, extensionSrc)
693 handles = parseHandles(extensionSrc)
694 functions = parseFunctions(extensionSrc)
695 compositeTypes = parseCompositeTypes(extensionSrc)
696 rawEnums = parseEnums(extensionSrc)
697 bitfieldNames = parseBitfieldNames(extensionSrc)
698 typedefs = parseTypedefs(extensionSrc)
699 enumBitfieldNames = [getBitEnumNameForBitfield(name) for name in bitfieldNames]
700 enums = [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
702 extCoreVersion = getCoreVersion(extensionName, extensionsData)
703 extFunctions = [functionsByName[function.name] for function in functions]
704 extCompositeTypes = [compositeTypesByName[compositeType.name] for compositeType in compositeTypes]
705 extEnums = [enumsByName[enum.name] for enum in enums]
706 extBitfields = [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames]
707 extHandles = [handlesByName[handle.name] for handle in handles]
708 extDefinitions = [definitionsByName[definition.name] for definition in definitions]
710 if extCoreVersion != None:
711 populateExtensionAliases(functionsByName, extFunctions)
712 populateExtensionAliases(handlesByName, extHandles)
713 populateExtensionAliases(enumsByName, extEnums)
714 populateExtensionAliases(bitfieldsByName, extBitfields)
715 populateExtensionAliases(compositeTypesByName, extCompositeTypes)
716 extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, typedefs, extCoreVersion))
719 def parseBitfieldNames (src):
720 ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
721 matches = re.findall(ptrn, src)
725 def parse64bitBitfieldNames (src):
726 ptrn = r'typedef\s+VkFlags64\s(' + IDENT_PTRN + r')\s*;'
727 matches = re.findall(ptrn, src)
731 def parse64bitBitfieldValues (src, bitfieldNamesList):
734 for bitfieldName in bitfieldNamesList:
735 ptrn = r'static const ' + bitfieldName + r'\s*(' + IDENT_PTRN + r')\s*=\s*([a-zA-Z0-9_]+)\s*;'
736 matches = re.findall(ptrn, src)
737 bitfields64.append(Bitfield(bitfieldName, matches))
742 versionsData = parseVersions(src)
743 versions = [Version((v[2], v[3], 0)) for v in versionsData]
744 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValue(src, v.getInHex())) for v in versions] +\
745 [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
747 handles = parseHandles(src)
748 rawEnums = parseEnums(src)
749 bitfieldNames = parseBitfieldNames(src)
750 bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
751 bitfield64Names = parse64bitBitfieldNames(src)
752 bitfields64 = parse64bitBitfieldValues(src, bitfield64Names)
755 compositeTypes = parseCompositeTypesByVersion(src, versionsData)
756 allFunctions = parseFunctionsByVersion(src, versionsData)
758 for enum in rawEnums:
759 if enum.name in bitfieldEnums:
760 bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
764 for bitfieldName in bitfieldNames:
765 if not bitfieldName in [bitfield.name for bitfield in bitfields]:
767 bitfields.append(Bitfield(bitfieldName, []))
769 extensions = parseExtensions(src, versions, allFunctions, compositeTypes, enums, bitfields, handles, definitions)
771 # Populate alias fields
772 populateAliasesWithTypedefs(compositeTypes, src)
773 populateAliasesWithTypedefs(enums, src)
774 populateAliasesWithTypedefs(bitfields, src)
775 populateAliasesWithTypedefs(handles, src)
778 removeAliasedValues(enum)
780 # Make generator to create Deleter<VkAccelerationStructureNV>
781 for f in allFunctions:
782 if (f.name == 'vkDestroyAccelerationStructureNV'):
783 f.arguments[1].type[0] = 'VkAccelerationStructureNV'
785 # Dealias handles VkAccelerationStructureNV and VkAccelerationStructureKHR
786 for handle in handles:
787 if handle.name == 'VkAccelerationStructureKHR':
789 if handle.name == 'VkAccelerationStructureNV':
790 handle.isAlias = False
793 definitions = definitions,
796 bitfields = bitfields,
797 bitfields64 = bitfields64,
798 compositeTypes = compositeTypes,
799 functions = allFunctions,
800 extensions = extensions)
802 def splitUniqueAndDuplicatedEntries (handles):
803 listOfUniqueHandles = []
804 duplicates = OrderedDict()
805 for handle in handles:
806 if handle.alias != None:
807 duplicates[handle.alias] = handle
808 if not handle.isAlias:
809 listOfUniqueHandles.append(handle)
810 return listOfUniqueHandles, duplicates
812 def writeHandleType (api, filename):
813 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles)
816 yield "\t%s\t= 0," % uniqeHandles[0].getHandleType()
817 for handle in uniqeHandles[1:]:
818 yield "\t%s," % handle.getHandleType()
819 for duplicate in duplicatedHandles:
820 yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType())
821 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType())
823 def genHandlesBlock ():
824 yield "enum HandleType"
827 for line in indentLines(genHandles()):
833 writeInlFile(filename, INL_HEADER, genHandlesBlock())
835 def getEnumValuePrefix (enum):
836 prefix = enum.name[0]
837 for i in range(1, len(enum.name)):
838 if enum.name[i].isupper() and not enum.name[i-1].isupper():
840 prefix += enum.name[i].upper()
843 def parseInt (value):
844 if value[:2] == "0x":
845 return int(value, 16)
847 return int(value, 10)
849 def areEnumValuesLinear (enum):
851 for name, value in enum.values:
852 if value[:2] != "VK":
853 intValue = parseInt(value)
854 if intValue != curIndex:
855 # consider enums containing *_MAX_ENUM = 0x7FFFFFFF as linear
856 if intValue == 0x7FFFFFFF:
862 def genEnumSrc (enum):
863 yield "enum %s" % enum.name
866 lines = ["\t%s\t= %s," % v for v in enum.values]
867 if areEnumValuesLinear(enum):
868 lastItem = "\t%s_LAST," % getEnumValuePrefix(enum)
869 if parseInt(enum.values[-1][1]) == 0x7FFFFFFF:
870 # if last enum item is *_MAX_ENUM then we need to make sure
871 # it stays last entry also if we append *_LAST to generated
872 # source (without this value of *_LAST won't be correct)
873 lines.insert(-1, lastItem)
875 lines.append(lastItem)
877 for line in indentLines(lines):
882 def genBitfieldSrc (bitfield):
883 if len(bitfield.values) > 0:
884 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
886 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
889 yield "typedef uint32_t %s;" % bitfield.name
891 def genBitfield64Src (bitfield64):
892 yield "typedef uint64_t %s;" % bitfield64.name
893 if len(bitfield64.values) > 0:
894 ptrn = "static const " + bitfield64.name + " %s\t= %s;"
895 for line in indentLines([ptrn % v for v in bitfield64.values]):
899 def genCompositeTypeSrc (type):
900 yield "%s %s" % (type.getClassName(), type.name)
902 for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]):
906 def genHandlesSrc (handles):
907 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles)
909 def genLines (handles):
910 for handle in uniqeHandles:
911 if handle.type == Handle.TYPE_DISP:
912 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
913 elif handle.type == Handle.TYPE_NONDISP:
914 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
916 for duplicate in duplicatedHandles:
917 if duplicate.type == Handle.TYPE_DISP:
918 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
919 elif duplicate.type == Handle.TYPE_NONDISP:
920 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
922 for line in indentLines(genLines(handles)):
925 def stripTrailingComment(str):
926 index = str.find("//")
931 def genDefinitionsSrc (definitions):
932 for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, stripTrailingComment(definition.value)) for definition in definitions]:
935 def genDefinitionsAliasSrc (definitions):
936 for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]:
937 if definition.value != definitions[definition].value and definition.value != definitions[definition].name:
938 raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value))
941 def genMaxFrameworkVersion (definitions):
942 maxApiVersionMajor = 1
943 maxApiVersionMinor = 0
944 for definition in definitions:
945 match = re.match("VK_API_VERSION_(\d+)_(\d+)", definition.name)
947 apiVersionMajor = int(match.group(1))
948 apiVersionMinor = int(match.group(2))
949 if apiVersionMajor > maxApiVersionMajor:
950 maxApiVersionMajor = apiVersionMajor
951 maxApiVersionMinor = apiVersionMinor
952 elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
953 maxApiVersionMinor = apiVersionMinor
954 yield "#define VK_API_MAX_FRAMEWORK_VERSION\tVK_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
956 def writeBasicTypes (api, filename):
959 definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
961 for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
965 for line in genHandlesSrc(api.handles):
969 for enum in api.enums:
971 for line in genEnumSrc(enum):
974 for enum2 in api.enums:
975 if enum2.alias == enum:
976 yield "typedef %s %s;" % (enum2.name, enum.name)
979 for bitfield in api.bitfields:
980 if not bitfield.isAlias:
981 for line in genBitfieldSrc(bitfield):
984 for bitfield2 in api.bitfields:
985 if bitfield2.alias == bitfield:
986 yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
989 for bitfield64 in api.bitfields64:
990 for line in genBitfield64Src(bitfield64):
993 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
996 for ext in api.extensions:
997 if ext.additionalDefs != None:
998 for definition in ext.additionalDefs:
999 yield "#define " + definition.name + " " + definition.value
1001 writeInlFile(filename, INL_HEADER, gen())
1003 def writeCompositeTypes (api, filename):
1005 for type in api.compositeTypes:
1006 type.checkAliasValidity()
1008 if not type.isAlias:
1009 for line in genCompositeTypeSrc(type):
1012 for type2 in api.compositeTypes:
1013 if type2.alias == type:
1014 yield "typedef %s %s;" % (type2.name, type.name)
1017 writeInlFile(filename, INL_HEADER, gen())
1019 def argListToStr (args):
1020 return ", ".join(v.getAsStringForArgumentList(' ') for v in args)
1022 def writeInterfaceDecl (api, filename, functionTypes, concrete):
1024 postfix = "" if concrete else " = 0"
1025 for function in api.functions:
1026 if not function.getType() in functionTypes:
1028 if not function.isAlias:
1029 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
1031 writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1033 def writeFunctionPtrTypes (api, filename):
1035 for function in api.functions:
1036 yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
1038 writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1040 def writeFunctionPointers (api, filename, functionTypes):
1041 def FunctionsYielder ():
1042 for function in api.functions:
1043 if function.getType() in functionTypes:
1044 if function.isAlias:
1045 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1046 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1048 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1050 writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1052 def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1053 def makeInitFunctionPointers ():
1054 for function in api.functions:
1055 if function.getType() in functionTypes and (cond == None or cond(function)):
1056 interfaceName = getInterfaceName(function)
1057 if function.isAlias:
1058 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1059 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1061 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1062 if function.alias != None:
1063 yield "if (!m_vk.%s)" % (getInterfaceName(function))
1064 yield " m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name)
1065 lines = [line.replace(' ', '\t') for line in indentLines(makeInitFunctionPointers())]
1066 writeInlFile(filename, INL_HEADER, lines)
1068 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1069 def makeFuncPtrInterfaceImpl ():
1070 for function in api.functions:
1071 if function.getType() in functionTypes and not function.isAlias:
1073 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
1075 if function.name == "vkEnumerateInstanceVersion":
1076 yield " if (m_vk.enumerateInstanceVersion)"
1077 yield " return m_vk.enumerateInstanceVersion(pApiVersion);"
1079 yield " *pApiVersion = VK_API_VERSION_1_0;"
1080 yield " return VK_SUCCESS;"
1081 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None:
1082 yield " vk::VkPhysicalDeviceProperties props;"
1083 yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1084 yield " if (props.apiVersion >= VK_API_VERSION_1_1)"
1085 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1087 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments))
1089 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1092 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1094 def writeStrUtilProto (api, filename):
1095 def makeStrUtilProto ():
1096 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]):
1099 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]):
1102 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]):
1105 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']):
1108 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]):
1111 writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1113 def writeStrUtilImpl (api, filename):
1114 def makeStrUtilImpl ():
1115 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]):
1119 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1122 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):
1127 for enum in api.enums:
1131 yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1133 yield "\tswitch (value)"
1135 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;"]):
1140 for bitfield in api.bitfields:
1141 if bitfield.isAlias:
1142 if bitfield.name != 'VkBuildAccelerationStructureFlagsNV':
1145 yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
1148 if len(bitfield.values) > 0:
1149 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1151 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
1154 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1156 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
1159 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
1161 for type in api.compositeTypes:
1162 if not type.isAlias:
1164 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1166 yield "\ts << \"%s = {\\n\";" % type.name
1167 for member in type.members:
1168 memberName = member.name
1171 if member.getType() in bitfieldTypeNames:
1172 valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name)
1173 elif member.getType() == "const char*" or member.getType() == "char*":
1174 valFmt = "getCharPtrStr(value.%s)" % member.name
1175 elif member.getType() == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1176 valFmt = "getWStr(value.%s)" % member.name
1177 elif member.arraySize != '':
1178 singleDimensional = not '][' in member.arraySize
1179 if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1180 valFmt = "(const char*)value.%s" % member.name
1181 elif singleDimensional and (member.getType() == 'char' or member.getType() == 'uint8_t'):
1182 newLine = "'\\n' << "
1183 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)
1185 if member.name == "memoryTypes" or member.name == "memoryHeaps":
1186 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1188 endIter = "DE_ARRAY_END(value.%s)" % member.name
1189 newLine = "'\\n' << "
1190 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1191 memberName = member.name
1193 valFmt = "value.%s" % member.name
1194 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1198 writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1201 def writeObjTypeImpl (api, filename):
1202 def makeObjTypeImpl ():
1204 yield "namespace vk"
1207 yield "template<typename T> VkObjectType getObjectType (void);"
1209 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]):
1214 writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1216 class ConstructorFunction:
1217 def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1220 self.objectType = objectType
1221 self.ifaceArgs = ifaceArgs
1222 self.arguments = arguments
1224 def getConstructorFunctions (api):
1227 Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")],
1228 Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")],
1229 Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")]
1231 for function in api.functions:
1232 if function.isAlias:
1234 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1235 if function.name == "vkCreateDisplayModeKHR":
1236 continue # No way to delete display modes (bug?)
1238 # \todo [pyry] Rather hacky
1239 ifaceArgs = ifacesDict[function.getType()]
1240 if function.name == "vkCreateDevice":
1241 ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs
1243 assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"])
1245 objectType = function.arguments[-1].type[0] #not getType() but type[0] on purpose
1246 arguments = function.arguments[:-1]
1247 funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments))
1250 def addVersionDefines(versionSpectrum):
1251 output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1254 def removeVersionDefines(versionSpectrum):
1255 output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()]
1258 def writeRefUtilProto (api, filename):
1259 functions = getConstructorFunctions(api)
1261 def makeRefUtilProto ():
1263 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]):
1266 writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1268 def writeRefUtilImpl (api, filename):
1269 functions = getConstructorFunctions(api)
1271 def makeRefUtilImpl ():
1272 yield "namespace refdetails"
1276 for function in api.functions:
1277 if function.getType() == Function.TYPE_DEVICE \
1278 and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1279 and not function.name == "vkDestroyDevice" \
1280 and not function.isAlias:
1281 objectType = function.arguments[-2].getType()
1283 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1285 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
1289 yield "} // refdetails"
1293 Function.TYPE_PLATFORM: "object",
1294 Function.TYPE_INSTANCE: "instance",
1295 Function.TYPE_DEVICE: "device"
1298 for function in functions:
1299 deleterArgsString = ''
1300 if function.name == "createDevice":
1301 # createDevice requires two additional parameters to setup VkDevice deleter
1302 deleterArgsString = "vkp, instance, object, " + function.arguments[-1].name
1304 deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1306 yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1308 yield "\t%s object = 0;" % function.objectType
1309 yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1310 yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1314 writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1316 def writeStructTraitsImpl (api, filename):
1318 for type in api.compositeTypes:
1319 if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias and type.name != "VkBaseOutStructure" and type.name != "VkBaseInStructure":
1320 yield "template<> VkStructureType getStructureType<%s> (void)" % type.name
1322 yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name)
1326 writeInlFile(filename, INL_HEADER, gen())
1328 def writeNullDriverImpl (api, filename):
1329 def genNullDriverImpl ():
1330 specialFuncNames = [
1331 "vkCreateGraphicsPipelines",
1332 "vkCreateComputePipelines",
1333 "vkCreateRayTracingPipelinesNV",
1334 "vkCreateRayTracingPipelinesKHR",
1335 "vkGetInstanceProcAddr",
1336 "vkGetDeviceProcAddr",
1337 "vkEnumeratePhysicalDevices",
1338 "vkEnumerateInstanceExtensionProperties",
1339 "vkEnumerateDeviceExtensionProperties",
1340 "vkGetPhysicalDeviceFeatures",
1341 "vkGetPhysicalDeviceFeatures2KHR",
1342 "vkGetPhysicalDeviceProperties",
1343 "vkGetPhysicalDeviceProperties2KHR",
1344 "vkGetPhysicalDeviceQueueFamilyProperties",
1345 "vkGetPhysicalDeviceMemoryProperties",
1346 "vkGetPhysicalDeviceFormatProperties",
1347 "vkGetPhysicalDeviceImageFormatProperties",
1349 "vkGetBufferMemoryRequirements",
1350 "vkGetBufferMemoryRequirements2KHR",
1351 "vkGetImageMemoryRequirements",
1352 "vkGetImageMemoryRequirements2KHR",
1356 "vkAllocateDescriptorSets",
1357 "vkFreeDescriptorSets",
1358 "vkResetDescriptorPool",
1359 "vkAllocateCommandBuffers",
1360 "vkFreeCommandBuffers",
1361 "vkCreateDisplayModeKHR",
1362 "vkCreateSharedSwapchainsKHR",
1363 "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1364 "vkGetPhysicalDeviceImageFormatProperties2KHR",
1365 "vkGetMemoryAndroidHardwareBufferANDROID",
1368 coreFunctions = [f for f in api.functions if not f.isAlias]
1369 specialFuncs = [f for f in coreFunctions if f.name in specialFuncNames]
1370 createFuncs = [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1371 destroyFuncs = [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1372 dummyFuncs = [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs]
1374 def getHandle (name):
1375 for handle in api.handles:
1376 if handle.name == name[0]:
1378 raise Exception("No such handle: %s" % name)
1380 for function in createFuncs:
1381 objectType = function.arguments[-1].type[:-1]
1382 argsStr = ", ".join([a.name for a in function.arguments[:-1]])
1384 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1386 yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1388 if getHandle(objectType).type == Handle.TYPE_NONDISP:
1389 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1391 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1395 for function in destroyFuncs:
1396 objectArg = function.arguments[-2]
1398 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1400 for arg in function.arguments[:-2]:
1401 yield "\tDE_UNREF(%s);" % arg.name
1403 if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
1404 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1406 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1411 for function in dummyFuncs:
1412 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1414 for arg in function.arguments:
1415 yield "\tDE_UNREF(%s);" % arg.name
1416 if function.returnType != "void":
1417 yield "\treturn VK_SUCCESS;"
1421 def genFuncEntryTable (type, name):
1422 funcs = [f for f in api.functions if f.getType() == type]
1424 for f in api.functions:
1426 refFuncs[f.alias] = f
1428 yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1430 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]):
1436 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1439 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1442 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1445 writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1447 def writeTypeUtil (api, filename):
1448 # Structs filled by API queries are not often used in test code
1449 QUERY_RESULT_TYPES = set([
1450 "VkPhysicalDeviceFeatures",
1451 "VkPhysicalDeviceLimits",
1452 "VkFormatProperties",
1453 "VkImageFormatProperties",
1454 "VkPhysicalDeviceSparseProperties",
1455 "VkQueueFamilyProperties",
1458 "StdVideoH264SpsVuiFlags",
1459 "StdVideoH264SpsFlags",
1460 "StdVideoH264PpsFlags",
1461 "StdVideoDecodeH264PictureInfoFlags",
1462 "StdVideoDecodeH264ReferenceInfoFlags",
1463 "StdVideoDecodeH264MvcElementFlags",
1464 "StdVideoEncodeH264SliceHeaderFlags",
1465 "StdVideoEncodeH264PictureInfoFlags",
1466 "StdVideoEncodeH264RefMgmtFlags",
1467 "StdVideoH265HrdFlags",
1468 "StdVideoH265VpsFlags",
1469 "StdVideoH265SpsVuiFlags",
1470 "StdVideoH265SpsFlags",
1471 "StdVideoH265PpsFlags",
1472 "StdVideoDecodeH265PictureInfoFlags",
1473 "StdVideoDecodeH265ReferenceInfoFlags",
1474 "StdVideoEncodeH265PictureInfoFlags"
1476 COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias])
1478 def isSimpleStruct (type):
1479 def hasArrayMember (type):
1480 for member in type.members:
1481 if member.arraySize != '':
1485 def hasCompositeMember (type):
1486 for member in type.members:
1487 if member.getType() in COMPOSITE_TYPES:
1491 return type.typeClass == CompositeType.CLASS_STRUCT and \
1492 type.members[0].getType() != "VkStructureType" and \
1493 not type.name in QUERY_RESULT_TYPES and \
1494 not hasArrayMember(type) and \
1495 not hasCompositeMember(type)
1498 for type in api.compositeTypes:
1499 if not isSimpleStruct(type) or type.isAlias:
1502 name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
1505 yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
1507 yield "\t%s res;" % type.name
1508 for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1510 yield "\treturn res;"
1513 writeInlFile(filename, INL_HEADER, gen())
1515 def writeDriverIds(filename):
1517 driverIdsString = []
1518 driverIdsString.append("static const struct\n"
1520 "\tstd::string driver;\n"
1522 "} driverIds [] =\n"
1525 vulkanCore = readFile(os.path.join(VULKAN_H_DIR, "vulkan_core.h"))
1527 items = re.search(r'(?:typedef\s+enum\s+VkDriverId\s*{)((.*\n)*)(?:}\s*VkDriverId\s*;)', vulkanCore).group(1).split(',')
1528 driverItems = dict()
1531 splitted = item.split('=')
1532 key = splitted[0].strip()
1533 value_str = splitted[1].strip()
1534 try: # is this previously defined value?
1535 value = driverItems[value_str]
1540 value_str = "\t// " + value_str
1541 driverItems[key] = value
1542 if not item == items[-1]:
1543 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}," + value_str)
1545 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}" + value_str)
1546 driverItems[key] = value
1548 driverIdsString.append("};")
1550 writeInlFile(filename, INL_HEADER, driverIdsString)
1553 def writeSupportedExtenions(api, filename):
1555 def writeExtensionsForVersions(map):
1558 result.append(" if (coreVersion >= " + str(version) + ")")
1560 for extension in map[version]:
1561 result.append(' dst.push_back("' + extension.name + '");')
1570 for ext in api.extensions:
1571 if ext.versionInCore != None:
1572 if ext.versionInCore[0] == 'INSTANCE':
1573 list = instanceMap.get(Version(ext.versionInCore[1:]))
1574 instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1576 list = deviceMap.get(Version(ext.versionInCore[1:]))
1577 deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1578 versionSet.add(Version(ext.versionInCore[1:]))
1580 lines = addVersionDefines(versionSet) + [
1582 "void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""),
1583 "{"] + writeExtensionsForVersions(deviceMap) + [
1586 "void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""),
1587 "{"] + writeExtensionsForVersions(instanceMap) + [
1589 ""] + removeVersionDefines(versionSet)
1590 writeInlFile(filename, INL_HEADER, lines)
1592 def writeExtensionFunctions (api, filename):
1594 def isInstanceExtension (ext):
1595 if ext.name and ext.functions:
1596 if ext.functions[0].getType() == Function.TYPE_INSTANCE:
1601 def isDeviceExtension (ext):
1602 if ext.name and ext.functions:
1603 if ext.functions[0].getType() == Function.TYPE_DEVICE:
1608 def writeExtensionNameArrays ():
1609 instanceExtensionNames = []
1610 deviceExtensionNames = []
1611 for ext in api.extensions:
1612 if ext.name and isInstanceExtension(ext):
1613 instanceExtensionNames += [ext.name]
1614 elif ext.name and isDeviceExtension(ext):
1615 deviceExtensionNames += [ext.name]
1616 yield '::std::string instanceExtensionNames[] =\n{'
1617 for instanceExtName in instanceExtensionNames:
1618 if (instanceExtName == instanceExtensionNames[len(instanceExtensionNames) - 1]):
1619 yield '\t"%s"' % instanceExtName
1621 yield '\t"%s",' % instanceExtName
1623 yield '::std::string deviceExtensionNames[] =\n{'
1624 for deviceExtName in deviceExtensionNames:
1625 if (deviceExtName == deviceExtensionNames[len(deviceExtensionNames) - 1]):
1626 yield '\t"%s"' % deviceExtName
1628 yield '\t"%s",' % deviceExtName
1631 def writeExtensionFunctions (functionType):
1633 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
1634 if functionType == Function.TYPE_INSTANCE:
1635 yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1636 dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
1637 elif functionType == Function.TYPE_DEVICE:
1638 yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1639 dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
1640 for ext in api.extensions:
1643 for func in ext.functions:
1644 if func.getType() == functionType:
1645 # only add functions with same vendor as extension
1646 # this is a workaroudn for entrypoints requiring more
1647 # than one excetions and lack of the dependency in vulkan_core.h
1648 vendor = ext.name.split('_')[1]
1649 if func.name.endswith(vendor):
1650 funcNames.append(func.name)
1652 yield '\tif (extName == "%s")' % ext.name
1654 for funcName in funcNames:
1655 if funcName in dg_list:
1656 yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
1658 yield '\t\tfunctions.push_back("%s");' % funcName
1659 if ext.name == "VK_KHR_device_group":
1660 for dg_func in dg_list:
1661 yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
1664 isFirstWrite = False
1665 if not isFirstWrite:
1666 yield '\tDE_FATAL("Extension name not found");'
1670 for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
1673 for line in writeExtensionFunctions(Function.TYPE_DEVICE):
1676 for line in writeExtensionNameArrays():
1679 writeInlFile(filename, INL_HEADER, lines)
1681 def writeCoreFunctionalities(api, filename):
1682 functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1683 lines = addVersionDefines(api.versions) + [
1685 'enum FunctionOrigin', '{'] + [line for line in indentLines([
1686 '\t' + functionOriginValues[0] + '\t= 0,',
1687 '\t' + functionOriginValues[1] + ',',
1688 '\t' + functionOriginValues[2]])] + [
1691 "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1692 "typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1693 "typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;",
1695 "void initApisMap (ApisMap& apis)",
1697 " apis.clear();"] + [
1698 " apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + str(v) + ", FunctionInfosList()));" for v in api.versions] + [
1702 for index, v in enumerate(api.versions):
1704 apiVersions.append("VK_VERSION_{0}_{1}".format(v.major, v.minor))
1705 # iterate over all functions that are core in latest vulkan version
1706 # note that first item in api.extension array are actually all definitions that are in vulkan.h.in before section with extensions
1707 for fun in api.extensions[0].functions:
1708 if fun.apiVersion in apiVersions:
1709 funcs.append(' apis[' + str(v) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));')
1710 lines = lines + [line for line in indentLines(funcs)] + [""]
1712 lines = lines + ["}", ""] + removeVersionDefines(api.versions)
1713 writeInlFile(filename, INL_HEADER, lines)
1715 def writeDeviceFeatures2(api, filename):
1716 # list of structures that should be tested with getPhysicalDeviceFeatures2
1717 # this is not posible to determine from vulkan_core.h, if new feature structures
1718 # are added they should be manualy added to this list
1719 testedStructures = [
1720 'VkPhysicalDeviceConditionalRenderingFeaturesEXT',
1721 'VkPhysicalDeviceScalarBlockLayoutFeatures',
1722 'VkPhysicalDevicePerformanceQueryFeaturesKHR',
1723 'VkPhysicalDevice16BitStorageFeatures',
1724 'VkPhysicalDeviceMultiviewFeatures',
1725 'VkPhysicalDeviceProtectedMemoryFeatures',
1726 'VkPhysicalDeviceSamplerYcbcrConversionFeatures',
1727 'VkPhysicalDeviceVariablePointersFeatures',
1728 'VkPhysicalDevice8BitStorageFeatures',
1729 'VkPhysicalDeviceShaderAtomicInt64Features',
1730 'VkPhysicalDeviceShaderFloat16Int8Features',
1731 'VkPhysicalDeviceBufferDeviceAddressFeaturesEXT',
1732 'VkPhysicalDeviceBufferDeviceAddressFeatures',
1733 'VkPhysicalDeviceDescriptorIndexingFeatures',
1734 'VkPhysicalDeviceTimelineSemaphoreFeatures',
1735 'VkPhysicalDeviceFragmentDensityMapFeaturesEXT',
1736 'VkPhysicalDeviceFragmentDensityMap2FeaturesEXT'
1738 # helper class used to encapsulate all data needed during generation
1739 class StructureDetail:
1740 def __init__ (self, name):
1741 nameResult = re.search('(.*)Features(.*)', name[len('VkPhysicalDevice'):])
1743 # generate structure type name from structure name
1744 # note that sometimes digits are separated with '_':
1745 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT
1746 # but mostly they are not:
1747 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES
1748 if (nameResult.group(1) == 'FragmentDensityMap2'):
1749 nameSplitUp = ['FRAGMENT', 'DENSITY', 'MAP', '2', 'FEATURES']
1751 nameSplit = re.findall(r'[1-9A-Z]+(?:[a-z1-9]+|[A-Z]*(?=[A-Z]|$))', nameResult.group(1))
1752 nameSplitUp = map(str.upper, nameSplit)
1753 nameSplitUp = list(nameSplitUp) + ['FEATURES']
1754 # check if there is extension suffix
1755 if (len(nameResult.group(2)) != 0):
1756 nameSplitUp.append(nameResult.group(2))
1758 self.sType = 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_' + '_'.join(nameSplitUp)
1759 self.instanceName = 'd' + name[11:]
1760 self.flagName = 'is' + name[16:]
1761 self.extension = None
1765 # helper extension class used in algorith below
1766 class StructureFoundContinueToNextOne(Exception):
1768 testedStructureDetail = [StructureDetail(struct) for struct in testedStructures]
1769 # iterate over all searched structures and find extensions that enable them
1770 for structureDetail in testedStructureDetail:
1772 # iterate over all extensions
1773 for extension in api.extensions[1:]:
1774 # check composite types and typedefs in case extension is part of core
1775 for structureList in [extension.compositeTypes, extension.typedefs]:
1776 # iterate over all structures added by extension
1777 for extensionStructure in structureList:
1778 # compare checked structure name to name of structure from extension
1779 if structureDetail.name == extensionStructure.name:
1780 structureDetail.extension = extension.name
1781 if extension.versionInCore is not None:
1782 structureDetail.major = extension.versionInCore[1]
1783 structureDetail.minor = extension.versionInCore[2]
1784 raise StructureFoundContinueToNextOne
1785 except StructureFoundContinueToNextOne:
1787 for structureDetail in testedStructureDetail:
1788 for compositeType in api.compositeTypes:
1789 if structureDetail.name != compositeType.name:
1791 structureMembers = compositeType.members[2:]
1792 structureDetail.members = [m.name for m in structureMembers]
1793 if structureDetail.major is not None:
1795 # if structure was not added with extension then check if
1796 # it was added directly with one of vulkan versions
1797 apiVersion = compositeType.apiVersion
1798 if apiVersion is None:
1800 structureDetail.major = apiVersion.major
1801 structureDetail.minor = apiVersion.minor
1803 # generate file content
1804 structureDefinitions = []
1805 featureEnabledFlags = []
1806 clearStructures = []
1809 verifyStructures = []
1810 for index, structureDetail in enumerate(testedStructureDetail):
1811 # create two instances of each structure
1812 nameSpacing = '\t' * int((55 - len(structureDetail.name)) / 4)
1813 structureDefinitions.append(structureDetail.name + nameSpacing + structureDetail.instanceName + '[count];')
1814 # create flags that check if proper extension or vulkan version is available
1816 extension = structureDetail.extension
1817 major = structureDetail.major
1818 if extension is not None:
1819 condition = ' checkExtension(properties, "' + extension + '")'
1820 if major is not None:
1822 condition += '\t' * int((39 - len(extension)) / 4) + '|| '
1824 condition += '\t' * 17 + ' '
1825 condition += 'context.contextSupports(vk::ApiVersion(' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
1827 nameSpacing = '\t' * int((40 - len(structureDetail.flagName)) / 4)
1828 featureEnabledFlags.append('const bool ' + structureDetail.flagName + nameSpacing + '=' + condition)
1829 # clear memory of each structure
1830 nameSpacing = '\t' * int((43 - len(structureDetail.instanceName)) / 4)
1831 clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx],' + nameSpacing + '0xFF * ndx, sizeof(' + structureDetail.name + '));')
1832 # construct structure chain
1833 nextInstanceName = 'DE_NULL';
1834 if index < len(testedStructureDetail)-1:
1835 nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
1836 structureChain.append('\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.sType + ';')
1837 structureChain.append('\t' + structureDetail.instanceName + '[ndx].pNext = ' + nextInstanceName + ';\n')
1838 # construct log section
1839 logStructures.append('if (' + structureDetail.flagName + ')')
1840 logStructures.append('\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;')
1841 #construct verification section
1842 verifyStructures.append('if (' + structureDetail.flagName + ' &&')
1843 for index, m in enumerate(structureDetail.members):
1844 prefix = '\t(' if index == 0 else '\t '
1845 postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
1846 verifyStructures.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
1847 verifyStructures.append('{\n\t\tTCU_FAIL("Mismatch between ' + structureDetail.name + '");\n}')
1848 # construct file content
1850 stream.extend(structureDefinitions)
1852 stream.extend(featureEnabledFlags)
1853 stream.append('\nfor (int ndx = 0; ndx < count; ++ndx)\n{')
1854 stream.extend(clearStructures)
1856 stream.extend(structureChain)
1857 stream.append('\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
1858 '\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
1859 '\textFeatures.pNext = &' + testedStructureDetail[0].instanceName + '[ndx];\n'
1860 '\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);\n}\n')
1861 stream.extend(logStructures)
1863 stream.extend(verifyStructures)
1864 writeInlFile(filename, INL_HEADER, stream)
1866 def generateDeviceFeaturesDefs(src):
1867 # look for definitions
1868 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_FEATURES(\w*)\s*='
1869 matches = re.findall(ptrnSType, src, re.M)
1870 matches = sorted(matches, key=lambda m: m[0])
1871 # construct final list
1873 for sType, sSuffix in matches:
1874 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1875 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Features' + sSuffix.replace('_', '') + ')'
1876 matchStructName = re.search(ptrnStructName, src, re.IGNORECASE)
1878 # handle special cases
1879 if sType == "EXCLUSIVE_SCISSOR":
1880 sType = "SCISSOR_EXCLUSIVE"
1881 elif sType == "ASTC_DECODE":
1882 sType = "ASTC_DECODE_MODE"
1883 if sType in {'VULKAN_1_1', 'VULKAN_1_2'}:
1885 # end handling special cases
1886 ptrnExtensionName = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_EXTENSION_NAME).+$'
1887 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1888 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_SPEC_VERSION).+$'
1889 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1890 defs.append( (sType, '', sSuffix, matchStructName.group(1), \
1891 matchExtensionName.group(0) if matchExtensionName else None,
1892 matchExtensionName.group(1) if matchExtensionName else None,
1893 matchSpecVersion.group(1) if matchSpecVersion else '0') )
1896 def generateDevicePropertiesDefs(src):
1897 # look for definitions
1898 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
1899 matches = re.findall(ptrnSType, src, re.M)
1900 matches = sorted(matches, key=lambda m: m[0])
1901 # construct final list
1903 for sType, sSuffix in matches:
1904 # handle special cases
1905 if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
1907 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
1908 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
1910 sExtSuffix = sSuffix
1911 suffixStart = sSuffix.rfind('_')
1913 sVerSuffix = sSuffix[:suffixStart]
1914 sExtSuffix = sSuffix[suffixStart:]
1915 # handle special case
1919 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1920 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
1921 matchStructName = re.search(ptrnStructName, src, re.M)
1924 if extType == "MAINTENANCE_3":
1925 extType = "MAINTENANCE3"
1926 elif extType == "DISCARD_RECTANGLE":
1927 extType = "DISCARD_RECTANGLES"
1928 elif extType == "DRIVER":
1929 extType = "DRIVER_PROPERTIES"
1930 elif extType == "POINT_CLIPPING":
1931 extType = "MAINTENANCE2"
1932 elif extType == "SHADER_CORE":
1933 extType = "SHADER_CORE_PROPERTIES"
1934 elif extType == "DRM":
1935 extType = "PHYSICAL_DEVICE_DRM"
1936 # end handling special cases
1937 ptrnExtensionName = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
1938 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1939 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
1940 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1941 defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
1942 matchExtensionName.group(0) if matchExtensionName else None,
1943 matchExtensionName.group(1) if matchExtensionName else None,
1944 matchSpecVersion.group (1) if matchSpecVersion else '0') )
1947 def writeDeviceFeatures(api, dfDefs, filename):
1948 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
1949 # and construct dictionary with all of their attributes
1952 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
1953 for structureType in api.compositeTypes:
1954 match = blobPattern.match(structureType.name)
1956 allMembers = [member.name for member in structureType.members]
1957 vkVersion = match.group(1)
1958 blobMembers[vkVersion] = allMembers[2:]
1959 blobStructs[vkVersion] = set()
1960 initFromBlobDefinitions = []
1961 emptyInitDefinitions = []
1962 # iterate over all feature structures
1963 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
1964 nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
1965 for structureType in api.compositeTypes:
1966 # skip structures that are not feature structures
1967 if not allFeaturesPattern.match(structureType.name):
1969 # skip structures that were previously identified as blobs
1970 if blobPattern.match(structureType.name):
1972 if structureType.isAlias:
1974 # skip sType and pNext and just grab third and next attributes
1975 structureMembers = structureType.members[2:]
1976 notPartOfBlob = True
1977 if nonExtFeaturesPattern.match(structureType.name):
1978 # check if this member is part of any of the blobs
1979 for blobName, blobMemberList in blobMembers.items():
1980 # if just one member is not part of this blob go to the next blob
1981 # (we asume that all members are part of blob - no need to check all)
1982 if structureMembers[0].name not in blobMemberList:
1984 # add another feature structure name to this blob
1985 blobStructs[blobName].add(structureType)
1986 # add specialization for this feature structure
1988 for member in structureMembers:
1989 memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
1991 "template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
1994 "}}".format(structureType.name, memberCopying)
1995 initFromBlobDefinitions.append(wholeFunction)
1996 notPartOfBlob = False
1997 # assuming that all members are part of blob, goto next
1999 # add empty template definition as on Fedora there are issue with
2000 # linking using just generic template - all specializations are needed
2002 emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2003 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2004 extensionDefines = []
2005 makeFeatureDescDefinitions = []
2006 featureStructWrappers = []
2007 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dfDefs):
2008 extensionNameDefinition = extName
2009 if not extensionNameDefinition:
2010 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2011 # construct defines with names
2013 extensionDefines.append(extLine)
2015 extensionDefines.append('#define {0} "not_existent_feature"'.format(extensionNameDefinition))
2016 # handle special cases
2017 if sType == "SCISSOR_EXCLUSIVE":
2018 sType = "EXCLUSIVE_SCISSOR"
2019 elif sType == "ASTC_DECODE_MODE":
2020 sType = "ASTC_DECODE"
2021 # end handling special cases
2022 # construct makeFeatureDesc template function definitions
2023 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2024 makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2025 "{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dfDefs)-idx))
2026 # construct CreateFeatureStruct wrapper block
2027 featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2028 # construct method that will check if structure sType is part of blob
2029 blobChecker = "bool isPartOfBlobFeatures (VkStructureType sType)\n{\n" \
2030 "\tconst std::vector<VkStructureType> sTypeVect =" \
2032 # iterate over blobs with list of structures
2033 for blobName in sorted(blobStructs.keys()):
2034 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2035 # iterate over all feature structures in current blob
2036 structuresList = list(blobStructs[blobName])
2037 structuresList = sorted(structuresList, key=lambda s: s.name)
2038 for structType in structuresList:
2039 # find definition of this structure in dfDefs
2040 structName = structType.name
2041 # handle special cases
2042 if structName == 'VkPhysicalDeviceShaderDrawParameterFeatures':
2043 structName = 'VkPhysicalDeviceShaderDrawParametersFeatures'
2044 # end handling special cases
2045 structDef = [s for s in dfDefs if s[3] == structName][0]
2046 sType = structDef[0]
2047 sSuffix = structDef[1] + structDef[2]
2048 # handle special cases
2049 if sType == "SCISSOR_EXCLUSIVE":
2050 sType = "EXCLUSIVE_SCISSOR"
2051 # end handling special cases
2052 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2053 blobChecker += "\t\t{0},\n".format(sTypeName)
2054 blobChecker += "\t};\n" \
2055 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2057 # combine all definition lists
2059 '#include "vkDeviceFeatures.hpp"\n',
2061 stream.extend(extensionDefines)
2063 stream.extend(initFromBlobDefinitions)
2064 stream.append('\n// generic template is not enough for some compilers')
2065 stream.extend(emptyInitDefinitions)
2067 stream.extend(makeFeatureDescDefinitions)
2069 stream.append('static const FeatureStructCreationData featureStructCreationArray[] =\n{')
2070 stream.extend(featureStructWrappers)
2071 stream.append('};\n')
2072 stream.append(blobChecker)
2073 stream.append('} // vk\n')
2074 writeInlFile(filename, INL_HEADER, stream)
2076 def writeDeviceProperties(api, dpDefs, filename):
2077 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2078 # and construct dictionary with all of their attributes
2081 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2082 for structureType in api.compositeTypes:
2083 match = blobPattern.match(structureType.name)
2085 allMembers = [member.name for member in structureType.members]
2086 vkVersion = match.group(1)
2087 blobMembers[vkVersion] = allMembers[2:]
2088 blobStructs[vkVersion] = set()
2089 initFromBlobDefinitions = []
2090 emptyInitDefinitions = []
2091 # iterate over all property structures
2092 allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2093 nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2094 for structureType in api.compositeTypes:
2095 # skip structures that are not property structures
2096 if not allPropertiesPattern.match(structureType.name):
2098 # skip structures that were previously identified as blobs
2099 if blobPattern.match(structureType.name):
2101 if structureType.isAlias:
2103 # skip sType and pNext and just grab third and next attributes
2104 structureMembers = structureType.members[2:]
2105 notPartOfBlob = True
2106 if nonExtPropertiesPattern.match(structureType.name):
2107 # check if this member is part of any of the blobs
2108 for blobName, blobMemberList in blobMembers.items():
2109 # if just one member is not part of this blob go to the next blob
2110 # (we asume that all members are part of blob - no need to check all)
2111 if structureMembers[0].name not in blobMemberList:
2113 # add another property structure name to this blob
2114 blobStructs[blobName].add(structureType)
2115 # add specialization for this property structure
2117 for member in structureMembers:
2118 if not member.arraySize:
2119 # handle special case
2120 if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2121 blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2122 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2123 # end handling special case
2125 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2127 memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type[0], member.arraySize[1:-1])
2129 "template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2132 "}}".format(structureType.name, memberCopying)
2133 initFromBlobDefinitions.append(wholeFunction)
2134 notPartOfBlob = False
2135 # assuming that all members are part of blob, goto next
2137 # add empty template definition as on Fedora there are issue with
2138 # linking using just generic template - all specializations are needed
2140 emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2141 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2142 extensionDefines = []
2143 makePropertyDescDefinitions = []
2144 propertyStructWrappers = []
2145 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dpDefs):
2146 extensionNameDefinition = extName
2147 if not extensionNameDefinition:
2148 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2149 # construct defines with names
2151 extensionDefines.append(extLine)
2153 extensionDefines.append('#define {0} "core_property"'.format(extensionNameDefinition))
2154 # construct makePropertyDesc template function definitions
2155 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2156 makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2157 "{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dpDefs)-idx))
2158 # construct CreateProperty struct wrapper block
2159 propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2160 # construct method that will check if structure sType is part of blob
2161 blobChecker = "bool isPartOfBlobProperties (VkStructureType sType)\n{\n" \
2162 "\tconst std::vector<VkStructureType> sTypeVect =" \
2164 # iterate over blobs with list of structures
2165 for blobName in sorted(blobStructs.keys()):
2166 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2167 # iterate over all feature structures in current blob
2168 structuresList = list(blobStructs[blobName])
2169 structuresList = sorted(structuresList, key=lambda s: s.name)
2170 for structType in structuresList:
2171 # find definition of this structure in dpDefs
2172 structName = structType.name
2173 structDef = [s for s in dpDefs if s[3] == structName][0]
2174 sType = structDef[0]
2175 sSuffix = structDef[1] + structDef[2]
2176 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2177 blobChecker += "\t\t{0},\n".format(sTypeName)
2178 blobChecker += "\t};\n" \
2179 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2181 # combine all definition lists
2183 '#include "vkDeviceProperties.hpp"\n',
2185 stream.extend(extensionDefines)
2187 stream.extend(initFromBlobDefinitions)
2188 stream.append('\n// generic template is not enough for some compilers')
2189 stream.extend(emptyInitDefinitions)
2191 stream.extend(makePropertyDescDefinitions)
2193 stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2194 stream.extend(propertyStructWrappers)
2195 stream.append('};\n')
2196 stream.append(blobChecker)
2197 stream.append('} // vk\n')
2198 writeInlFile(filename, INL_HEADER, stream)
2200 def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
2202 for _, _, _, extStruct, _, _, _ in dfDefs:
2203 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2204 stream.append(pattern.format(extStruct, nameSubStr))
2205 writeInlFile(filename, INL_HEADER, indentLines(stream))
2207 def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
2208 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
2209 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2211 def writeDeviceFeaturesContextDecl(dfDefs, filename):
2212 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2213 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2215 def writeDeviceFeaturesContextDefs(dfDefs, filename):
2216 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2217 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2219 def genericDevicePropertiesWriter(dfDefs, pattern, filename):
2221 for _, _, _, extStruct, _, _, _ in dfDefs:
2222 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2223 if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
2225 stream.append(pattern.format(extStruct, nameSubStr))
2226 writeInlFile(filename, INL_HEADER, indentLines(stream))
2228 def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
2229 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
2230 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2232 def writeDevicePropertiesContextDecl(dfDefs, filename):
2233 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2234 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2236 def writeDevicePropertiesContextDefs(dfDefs, filename):
2237 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2238 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2240 def splitWithQuotation(line):
2242 splitted = re.findall(r'[^"\s]\S*|".+?"', line)
2244 result.append(s.replace('"', ''))
2247 def writeMandatoryFeatures(filename):
2249 pattern = r'\s*([\w]+)\s+FEATURES\s+\((.*)\)\s+REQUIREMENTS\s+\((.*)\)'
2250 mandatoryFeatures = readFile(os.path.join(VULKAN_H_DIR, "mandatory_features.txt"))
2251 matches = re.findall(pattern, mandatoryFeatures)
2255 allRequirements = splitWithQuotation(m[2])
2256 dictData.append( [ m[0], m[1].strip(), allRequirements ] )
2257 if m[0] != 'VkPhysicalDeviceFeatures' :
2258 if (m[0] not in dictStructs):
2259 dictStructs[m[0]] = [m[0][2:3].lower() + m[0][3:]]
2260 if (allRequirements[0]):
2261 if (allRequirements[0] not in dictStructs[m[0]][1:]):
2262 dictStructs[m[0]].append(allRequirements[0])
2264 stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
2265 '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
2266 '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
2268 '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
2269 '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
2270 '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
2272 '\ttcu::TestLog& log = context.getTestContext().getLog();',
2273 '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
2274 '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
2275 '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
2276 '\tvoid** nextPtr = &coreFeatures.pNext;',
2279 listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
2280 for k, v in listStruct:
2281 if (v[1].startswith("ApiVersion")):
2282 cond = '\tif (context.contextSupports(vk::' + v[1] + '))'
2284 cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[1] + '"))'
2285 stream.extend(['\tvk::' + k + ' ' + v[0]+ ';',
2286 '\tdeMemset(&' + v[0] + ', 0, sizeof(' + v[0] + '));',
2291 for i, req in enumerate(reqs) :
2292 if (req.startswith("ApiVersion")):
2293 cond = cond + 'context.contextSupports(vk::' + req + ')'
2295 cond = cond + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2296 if i+1 < len(reqs) :
2297 cond = cond + ' || '
2299 stream.append('\t' + cond)
2300 stream.extend(['\t{',
2301 '\t\t' + v[0] + '.sType = getStructureType<' + k + '>();',
2302 '\t\t*nextPtr = &' + v[0] + ';',
2303 '\t\tnextPtr = &' + v[0] + '.pNext;',
2306 stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
2307 '\tbool result = true;',
2312 structName = 'coreFeatures.features';
2313 if v[0] != 'VkPhysicalDeviceFeatures' :
2314 structName = dictStructs[v[0]][0]
2317 for i, req in enumerate(v[2]) :
2318 if (req.startswith("ApiVersion")):
2319 condition = condition + 'context.contextSupports(vk::' + req + ')'
2321 condition = condition + req
2323 condition = condition + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2324 if i+1 < len(v[2]) :
2325 condition = condition + ' && '
2326 condition = condition + ' )'
2327 stream.append('\t' + condition)
2328 stream.append('\t{')
2329 # Don't need to support an AND case since that would just be another line in the .txt
2330 if len(v[1].split(" ")) == 1:
2331 stream.append('\t\tif ( ' + structName + '.' + v[1] + ' == VK_FALSE )')
2334 for i, feature in enumerate(v[1].split(" ")):
2336 condition = condition + ' && '
2337 condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
2338 condition = condition + ' )'
2339 stream.append('\t\t' + condition)
2340 featureSet = v[1].replace(" ", " or ")
2341 stream.extend(['\t\t{',
2342 '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
2343 '\t\t\tresult = false;',
2347 stream.append('\treturn result;')
2348 stream.append('}\n')
2349 writeInlFile(filename, INL_HEADER, stream)
2351 def writeExtensionList(filename, patternPart):
2353 stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(patternPart.title()))
2354 extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
2355 pattern = r'\s*([^\s]+)\s+{0}\s*[0-9_]*'.format(patternPart)
2356 matches = re.findall(pattern, extensionsData)
2358 stream.append('\t"' + m + '",')
2359 stream.append('};\n')
2360 writeInlFile(filename, INL_HEADER, stream)
2362 def preprocessTopInclude(src, dir):
2363 pattern = r'#include\s+"([^\n]+)"'
2365 inc = re.search(pattern, src)
2368 incFileName = inc.string[inc.start(1):inc.end(1)]
2369 patternIncNamed = r'#include\s+"' + incFileName + '"'
2370 incBody = readFile(os.path.join(dir, incFileName)) if incFileName != 'vulkan/vk_platform.h' else ''
2371 incBodySanitized = re.sub(pattern, '', incBody)
2372 bodyEndSanitized = re.sub(patternIncNamed, '', src[inc.end(0):])
2373 src = src[0:inc.start(0)] + incBodySanitized + bodyEndSanitized
2376 if __name__ == "__main__":
2377 # Read all .h files, with vulkan_core.h first
2378 files = os.listdir(VULKAN_H_DIR)
2379 files = [f for f in files if f.endswith(".h")]
2381 files.remove("vulkan_core.h")
2382 first = ["vk_video/vulkan_video_codecs_common.h", "vulkan_core.h"]
2383 files = first + files
2387 src += preprocessTopInclude(readFile(os.path.join(VULKAN_H_DIR,file)), VULKAN_H_DIR)
2389 src = re.sub('\s*//[^\n]*', '', src)
2390 src = re.sub('\n\n', '\n', src)
2394 platformFuncs = [Function.TYPE_PLATFORM]
2395 instanceFuncs = [Function.TYPE_INSTANCE]
2396 deviceFuncs = [Function.TYPE_DEVICE]
2398 dfd = generateDeviceFeaturesDefs(src)
2399 writeDeviceFeatures (api, dfd, os.path.join(VULKAN_DIR, "vkDeviceFeatures.inl"))
2400 writeDeviceFeaturesDefaultDeviceDefs (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
2401 writeDeviceFeaturesContextDecl (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDecl.inl"))
2402 writeDeviceFeaturesContextDefs (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDefs.inl"))
2404 dpd = generateDevicePropertiesDefs(src)
2405 writeDeviceProperties (api, dpd, os.path.join(VULKAN_DIR, "vkDeviceProperties.inl"))
2407 writeDevicePropertiesDefaultDeviceDefs (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
2408 writeDevicePropertiesContextDecl (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDecl.inl"))
2409 writeDevicePropertiesContextDefs (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDefs.inl"))
2411 writeHandleType (api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
2412 writeBasicTypes (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
2413 writeCompositeTypes (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
2414 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"), platformFuncs, False)
2415 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"), instanceFuncs, False)
2416 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"), deviceFuncs, False)
2417 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"), platformFuncs, True)
2418 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"), instanceFuncs, True)
2419 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"), deviceFuncs, True)
2420 writeFunctionPtrTypes (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
2421 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"), platformFuncs)
2422 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"), instanceFuncs)
2423 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"), deviceFuncs)
2424 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr")
2425 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"), instanceFuncs)
2426 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"), deviceFuncs)
2427 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver")
2428 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver")
2429 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver")
2430 writeStrUtilProto (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
2431 writeStrUtilImpl (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
2432 writeRefUtilProto (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
2433 writeRefUtilImpl (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
2434 writeStructTraitsImpl (api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl"))
2435 writeNullDriverImpl (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
2436 writeTypeUtil (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
2437 writeSupportedExtenions (api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl"))
2438 writeCoreFunctionalities (api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl"))
2439 writeExtensionFunctions (api, os.path.join(VULKAN_DIR, "vkExtensionFunctions.inl"))
2440 writeDeviceFeatures2 (api, os.path.join(VULKAN_DIR, "vkDeviceFeatures2.inl"))
2441 writeMandatoryFeatures ( os.path.join(VULKAN_DIR, "vkMandatoryFeatures.inl"))
2442 writeExtensionList ( os.path.join(VULKAN_DIR, "vkInstanceExtensions.inl"), 'INSTANCE')
2443 writeExtensionList ( os.path.join(VULKAN_DIR, "vkDeviceExtensions.inl"), 'DEVICE')
2444 writeDriverIds ( os.path.join(VULKAN_DIR, "vkKnownDriverIds.inl"))
2445 writeObjTypeImpl (api, os.path.join(VULKAN_DIR, "vkObjTypeImpl.inl"))