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 = [
110 ("DWORD", "uint32_t"),
111 ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
114 EXTENSION_POSTFIXES = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK", "FUCHSIA", "GGP", "AMD"]
115 EXTENSION_POSTFIXES_STANDARD = ["KHR", "EXT"]
117 def prefixName (prefix, name):
118 name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
119 name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
122 name = name.replace("YCB_CR_", "YCBCR_")
123 name = name.replace("WIN_32_", "WIN32_")
124 name = name.replace("8_BIT_", "8BIT_")
125 name = name.replace("16_BIT_", "16BIT_")
126 name = name.replace("INT_64_", "INT64_")
127 name = name.replace("D_3_D_12_", "D3D12_")
128 name = name.replace("IOSSURFACE_", "IOS_SURFACE_")
129 name = name.replace("MAC_OS", "MACOS_")
130 name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_")
131 name = name.replace("VIEWPORT_W", "VIEWPORT_W_")
132 name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES")
133 name = name.replace("PHYSICAL_DEVICE_SHADER_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES")
134 name = name.replace("_PCIBUS_", "_PCI_BUS_")
135 name = name.replace("ASTCD", "ASTC_D")
136 name = name.replace("AABBNV", "AABB_NV")
137 name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
138 name = name.replace("SMBUILTINS", "SM_BUILTINS")
139 name = name.replace("ASTCHDRFEATURES", "ASTC_HDR_FEATURES")
140 name = name.replace("UINT_8", "UINT8")
141 name = name.replace("VULKAN_11_FEATURES", "VULKAN_1_1_FEATURES")
142 name = name.replace("VULKAN_11_PROPERTIES", "VULKAN_1_1_PROPERTIES")
143 name = name.replace("VULKAN_12_FEATURES", "VULKAN_1_2_FEATURES")
144 name = name.replace("VULKAN_12_PROPERTIES", "VULKAN_1_2_PROPERTIES")
145 name = name.replace("INT_8_", "INT8_")
146 name = name.replace("AABBNV", "AABB_NV")
147 name = name.replace("_H_264_", "_H264_")
148 name = name.replace("_H_265_", "_H265_")
149 name = name.replace("RDMAFEATURES", "RDMA_FEATURES")
155 def __init__ (self, versionTuple):
156 self.major = versionTuple[0]
157 self.minor = versionTuple[1]
158 self.patch = versionTuple[2]
162 return "VK_API_VERSION_%d_%d" % (self.major, self.minor)
163 return '0x%Xu' % (hash(self))
165 def isStandardVersion (self):
172 def getBestRepresentation (self):
173 if self.isStandardVersion():
174 return self.getInHex()
175 return self.getDefineName()
177 def getDefineName (self):
178 return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch)
181 return (self.major << 22) | (self.minor << 12) | self.patch
183 def __eq__ (self, other):
184 return self.major == other.major and self.minor == other.minor and self.patch == other.patch
187 return self.getBestRepresentation()
194 def __init__ (self, type, name):
200 def getHandleType (self):
201 return prefixName("HANDLE_TYPE_", self.name)
203 def checkAliasValidity (self):
207 return '%s (%s, %s)' % (self.name, self.alias, self.isAlias)
210 def __init__ (self, type, name, value):
218 return '%s = %s (%s)' % (self.name, self.value, self.type)
221 def __init__ (self, name, values):
227 def checkAliasValidity (self):
228 if self.alias != None:
229 if len(self.values) != len(self.alias.values):
230 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
231 for index, value in enumerate(self.values):
232 aliasVal = self.alias.values[index]
233 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
234 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
237 return '%s (%s) %s' % (self.name, self.alias, self.values)
240 def __init__ (self, name, values):
246 def checkAliasValidity (self):
247 if self.alias != None:
248 if len(self.values) != len(self.alias.values):
249 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
250 for index, value in enumerate(self.values):
251 aliasVal = self.alias.values[index]
252 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
253 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
256 return '%s (%s)' % (self.name, self.alias)
259 def __init__ (self, type, name, arraySizeOrFieldWidth):
260 type = type.replace('*',' *').replace('&',' &')
261 for src, dst in TYPE_SUBSTITUTIONS:
262 type = type.replace(src, dst)
263 self.type = type.split(' ')
264 for platformType, substitute, compat in PLATFORM_TYPES:
265 range = self.contains(self.type, platformType)
267 self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:]
270 if len(arraySizeOrFieldWidth) > 0 and arraySizeOrFieldWidth[0] == ':':
272 self.fieldWidth = arraySizeOrFieldWidth
274 self.arraySize = arraySizeOrFieldWidth
277 def contains(self, big, small):
278 for i in range(len(big)-len(small)+1):
279 for j in range(len(small)):
280 if big[i+j] != small[j]:
283 return i, i+len(small)
287 return ' '.join(self.type).replace(' *','*').replace(' &','&')
289 def getAsString (self, separator):
290 return '%s%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize, self.fieldWidth)
292 def getAsStringForArgumentList (self, separator):
293 return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize)
296 return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize)
298 def __eq__ (self, other):
299 if len(self.type) != len(other.type):
301 for index, type in enumerate(self.type):
302 if "*" == type or "&" == type or "const" == type or "volatile" == type:
303 if type != other.type[index]:
305 elif type != other.type[index] and \
306 type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \
307 other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD):
309 return self.arraySize == other.arraySize
311 def __ne__ (self, other):
312 return not self == other
318 def __init__ (self, typeClass, name, members, apiVersion = None):
319 self.typeClass = typeClass
321 self.members = members
324 self.apiVersion = apiVersion
326 def getClassName (self):
327 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
328 return names[self.typeClass]
330 def checkAliasValidity (self):
331 if self.alias != None:
332 if len(self.members) != len(self.alias.members):
333 raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name))
334 for index, member in enumerate(self.members ):
336 #if member != self.alias.members[index]:
337 #raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name))
338 #raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".")
340 return '%s (%s)' % (self.name, self.alias)
343 TYPE_PLATFORM = 0 # Not bound to anything
344 TYPE_INSTANCE = 1 # Bound to VkInstance
345 TYPE_DEVICE = 2 # Bound to VkDevice
347 def __init__ (self, name, returnType, arguments, apiVersion = None):
349 self.returnType = returnType
350 self.arguments = arguments
353 self.apiVersion = apiVersion
357 if self.name == "vkGetInstanceProcAddr":
358 return Function.TYPE_PLATFORM
359 assert len(self.arguments) > 0
360 firstArgType = self.arguments[0].getType()
361 if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
362 return Function.TYPE_INSTANCE
363 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
364 return Function.TYPE_DEVICE
366 return Function.TYPE_PLATFORM
368 def checkAliasValidity (self):
369 if self.alias != None:
370 if len(self.arguments) != len(self.alias.arguments):
371 raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name))
372 if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)):
373 raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name))
374 for index, argument in enumerate(self.arguments):
375 if argument != self.alias.arguments[index]:
376 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))
379 return '%s (%s)' % (self.name, self.alias)
382 def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, typedefs, versionInCore):
384 self.definitions = definitions
385 self.additionalDefs = additionalDefinitions
386 self.handles = handles
388 self.bitfields = bitfields
389 self.compositeTypes = compositeTypes
390 self.functions = functions
391 self.typedefs = typedefs
392 self.versionInCore = versionInCore
395 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)
398 def __init__ (self, versions, definitions, handles, enums, bitfields, bitfields64, compositeTypes, functions, extensions):
399 self.versions = versions
400 self.definitions = definitions
401 self.handles = handles
403 self.bitfields = bitfields
404 self.bitfields64 = bitfields64
405 self.compositeTypes = compositeTypes
406 self.functions = functions # \note contains extension functions as well
407 self.extensions = extensions
409 def readFile (filename):
410 with open(filename, 'rt') as f:
413 IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*'
414 WIDTH_PTRN = r'[:0-9]*'
415 TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
417 def getInterfaceName (function):
418 assert function.name[:2] == "vk"
419 return function.name[2].lower() + function.name[3:]
421 def getFunctionTypeName (function):
422 assert function.name[:2] == "vk"
423 return function.name[2:] + "Func"
425 def endsWith (str, postfix):
426 return str[-len(postfix):] == postfix
428 def splitNameExtPostfix (name):
429 knownExtPostfixes = EXTENSION_POSTFIXES
430 for postfix in knownExtPostfixes:
431 if endsWith(name, postfix):
432 return (name[:-len(postfix)], postfix)
435 def getBitEnumNameForBitfield (bitfieldName):
436 bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
437 assert bitfieldName[-1] == "s"
438 return bitfieldName[:-1] + "Bits" + postfix
440 def getBitfieldNameForBitEnum (bitEnumName):
441 bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
442 assert bitEnumName[-4:] == "Bits"
443 return bitEnumName[:-4] + "s" + postfix
445 def parsePreprocDefinedValue (src, name):
446 value = parsePreprocDefinedValueOptional(src, name)
448 raise Exception("No such definition: %s" % name)
451 def parsePreprocDefinedValueOptional (src, name):
452 definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
453 if definition is None:
455 value = definition.group(1).strip()
456 if value == "UINT32_MAX":
460 def parseEnum (name, src):
461 keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,\n}]+)\s*[,\n}]'
462 return Enum(name, re.findall(keyValuePtrn, src))
464 # \note Parses raw enums, some are mapped to bitfields later
465 def parseEnums (src):
466 matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
468 for enumname, contents, typename in matches:
469 enums.append(parseEnum(typename, contents))
472 def parseCompositeType (type, name, src):
473 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\]|\s*:\s*[0-9]+)*)\s*;'
474 matches = re.findall(typeNamePtrn, src)
475 members = [Variable(t.strip(), n.strip(), a.replace(' ', '')) for t, n, a, _ in matches]
476 return CompositeType(type, name, members)
478 def parseCompositeTypes (src):
479 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
480 matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
482 for type, structname, contents, typename in matches:
483 types.append(parseCompositeType(typeMap[type], typename, contents))
486 def parseCompositeTypesByVersion (src, versionsData):
488 # find occurence of extension is a place where
489 # we cant assign apiVersion to found structures
490 extPtrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
491 versionEnd = re.search(extPtrn, src)
492 versions = [Version((v[2], v[3], 0)) for v in versionsData]
493 versions.append(None)
495 # construct list of locations where version definitions start, and add the end of the file to it
496 sectionLocations = [versionDef[1] for versionDef in versionsData]
497 sectionLocations.append(versionEnd.start())
498 sectionLocations.append(len(src))
500 # construct function declaration pattern
501 ptrn = r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;'
502 regPtrn = re.compile(ptrn)
504 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
506 # iterate over all versions and find all structure definitions
507 for index, v in enumerate(versions):
508 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
509 for type, structname, contents, typename in matches:
510 compositeType = parseCompositeType(typeMap[type], typename, contents)
511 compositeType.apiVersion = v
512 types.append(compositeType)
515 def parseVersions (src):
516 # returns list of tuples each with four items:
517 # 1. string with version token (without ' 1' at the end)
518 # 2. starting point off version specific definitions in vulkan.h.in
519 # 3. major version number
520 # 4. minor version number
521 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)]
523 def parseHandles (src):
524 matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
526 typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
527 for type, name in matches:
528 handle = Handle(typeMap[type], name)
529 handles.append(handle)
532 def parseArgList (src):
533 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*'
535 for rawArg in src.split(','):
536 m = re.search(typeNamePtrn, rawArg)
537 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
540 def removeTypeExtPostfix (name):
541 for extPostfix in EXTENSION_POSTFIXES_STANDARD:
542 if endsWith(name, extPostfix):
543 return name[0:-len(extPostfix)]
546 def populateExtensionAliases(allObjects, extensionObjects):
547 for object in extensionObjects:
548 withoutPostfix = removeTypeExtPostfix(object.name)
549 if withoutPostfix != None and withoutPostfix in allObjects:
550 # max 1 alias is assumed by functions in this file
551 assert allObjects[withoutPostfix].alias == None
552 allObjects[withoutPostfix].alias = object
553 object.isAlias = True
554 for object in extensionObjects:
555 object.checkAliasValidity()
557 def populateAliasesWithTypedefs (objects, src):
559 for object in objects:
560 objectsByName[object.name] = object
561 ptrn = r'\s*typedef\s+' + object.name + r'\s+([^;]+)'
562 stash = re.findall(ptrn, src)
564 objExt = copy.deepcopy(object)
565 objExt.name = stash[0]
566 object.alias = objExt
567 objExt.isAlias = True
568 objects.append(objExt)
570 def removeAliasedValues (enum):
572 for name, value in enum.values:
573 valueByName[name] = value
575 def removeDefExtPostfix (name):
576 for extPostfix in EXTENSION_POSTFIXES:
577 if endsWith(name, "_" + extPostfix):
578 return name[0:-(len(extPostfix)+1)]
582 for name, value in enum.values:
583 withoutPostfix = removeDefExtPostfix(name)
584 if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value:
586 newValues.append((name, value))
587 enum.values = newValues
589 def parseFunctions (src):
590 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
591 matches = re.findall(ptrn, src)
593 for returnType, name, argList in matches:
594 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
597 def parseFunctionsByVersion (src, versions):
598 # construct list of locations where version definitions start, and add the end of the file to it
599 sectionLocations = [versionDef[1] for versionDef in versions]
600 sectionLocations.append(len(src))
602 # construct function declaration pattern
603 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
604 regPtrn = re.compile(ptrn)
607 # iterate over all versions and find all function definitions
608 for index, v in enumerate(versions):
609 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
610 for returnType, name, argList in matches:
611 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), v[0]))
614 def splitByExtension (src):
615 ptrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
616 # Construct long pattern that will be used to split whole source by extensions
617 match = "#define\s+("
618 for part in re.finditer(ptrn, src):
619 match += part.group(1)+"|"
620 match = match[:-1] + ")\s+1"
621 parts = re.split(match, src)
623 # First part is core, following tuples contain extension name and all its definitions
624 byExtension = [(None, parts[0])]
625 for ndx in range(1, len(parts), 2):
626 byExtension.append((parts[ndx], parts[ndx+1]))
629 def parseDefinitions (extensionName, src):
631 def skipDefinition (extensionName, definition):
632 if extensionName == None:
634 extNameUpper = extensionName.upper()
635 extNameUpper = extNameUpper.replace("VK_KHR_SYNCHRONIZATION2", "VK_KHR_SYNCHRONIZATION_2")
636 extNameUpper = extNameUpper.replace("VK_INTEL_SHADER_INTEGER_FUNCTIONS2", "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2")
637 extNameUpper = extNameUpper.replace("VK_EXT_ROBUSTNESS2", "VK_EXT_ROBUSTNESS_2")
638 extNameUpper = extNameUpper.replace("VK_EXT_FRAGMENT_DENSITY_MAP2", "VK_EXT_FRAGMENT_DENSITY_MAP_2")
639 extNameUpper = extNameUpper.replace("VK_EXT_SHADER_ATOMIC_FLOAT2", "VK_EXT_SHADER_ATOMIC_FLOAT_2")
640 extNameUpper = extNameUpper.replace("VK_AMD_SHADER_CORE_PROPERTIES2", "VK_AMD_SHADER_CORE_PROPERTIES_2")
641 extNameUpper = extNameUpper.replace("VK_EXT_EXTENDED_DYNAMIC_STATE2", "VK_EXT_EXTENDED_DYNAMIC_STATE_2")
643 if definition[0].startswith(extNameUpper) and definition[1].isdigit():
645 if definition[0].startswith(extNameUpper):
647 if definition[1].isdigit():
651 ptrn = r'#define\s+([^\s]+)\s+([^\r\n]+)'
652 matches = re.findall(ptrn, src)
654 return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)]
656 def parseTypedefs (src):
658 ptrn = r'typedef\s+([^\s]+)\s+([^\r\n]+);'
659 matches = re.findall(ptrn, src)
661 return [Definition(None, match[0], match[1]) for match in matches]
663 def parseExtensions (src, versions, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions):
665 def getCoreVersion (extensionName, extensionsData):
666 # returns None when extension was not added to core for any Vulkan version
667 # returns array containing DEVICE or INSTANCE string followed by the vulkan version in which this extension is core
668 # note that this function is also called for vulkan 1.0 source for which extName is None
669 if not extensionName:
671 ptrn = extensionName + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)'
672 coreVersion = re.search(ptrn, extensionsData, re.I)
673 if coreVersion != None:
674 return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]]
677 extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
678 splitSrc = splitByExtension(src)
680 functionsByName = {function.name: function for function in allFunctions}
681 compositeTypesByName = {compType.name: compType for compType in allCompositeTypes}
682 enumsByName = {enum.name: enum for enum in allEnums}
683 bitfieldsByName = {bitfield.name: bitfield for bitfield in allBitfields}
684 handlesByName = {handle.name: handle for handle in allHandles}
685 definitionsByName = {definition.name: definition for definition in allDefinitions}
687 for extensionName, extensionSrc in splitSrc:
688 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValueOptional(extensionSrc, v.getInHex())) for v in versions]
689 definitions.extend([Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS])
690 definitions = [definition for definition in definitions if definition.value != None]
691 additionalDefinitions = parseDefinitions(extensionName, extensionSrc)
692 handles = parseHandles(extensionSrc)
693 functions = parseFunctions(extensionSrc)
694 compositeTypes = parseCompositeTypes(extensionSrc)
695 rawEnums = parseEnums(extensionSrc)
696 bitfieldNames = parseBitfieldNames(extensionSrc)
697 typedefs = parseTypedefs(extensionSrc)
698 enumBitfieldNames = [getBitEnumNameForBitfield(name) for name in bitfieldNames]
699 enums = [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
701 extCoreVersion = getCoreVersion(extensionName, extensionsData)
702 extFunctions = [functionsByName[function.name] for function in functions]
703 extCompositeTypes = [compositeTypesByName[compositeType.name] for compositeType in compositeTypes]
704 extEnums = [enumsByName[enum.name] for enum in enums]
705 extBitfields = [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames]
706 extHandles = [handlesByName[handle.name] for handle in handles]
707 extDefinitions = [definitionsByName[definition.name] for definition in definitions]
709 if extCoreVersion != None:
710 populateExtensionAliases(functionsByName, extFunctions)
711 populateExtensionAliases(handlesByName, extHandles)
712 populateExtensionAliases(enumsByName, extEnums)
713 populateExtensionAliases(bitfieldsByName, extBitfields)
714 populateExtensionAliases(compositeTypesByName, extCompositeTypes)
715 extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, typedefs, extCoreVersion))
718 def parseBitfieldNames (src):
719 ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
720 matches = re.findall(ptrn, src)
724 def parse64bitBitfieldNames (src):
725 ptrn = r'typedef\s+VkFlags64\s(' + IDENT_PTRN + r')\s*;'
726 matches = re.findall(ptrn, src)
730 def parse64bitBitfieldValues (src, bitfieldNamesList):
733 for bitfieldName in bitfieldNamesList:
734 ptrn = r'static const ' + bitfieldName + r'\s*(' + IDENT_PTRN + r')\s*=\s*([a-zA-Z0-9_]+)\s*;'
735 matches = re.findall(ptrn, src)
736 bitfields64.append(Bitfield(bitfieldName, matches))
741 versionsData = parseVersions(src)
742 versions = [Version((v[2], v[3], 0)) for v in versionsData]
743 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValue(src, v.getInHex())) for v in versions] +\
744 [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
746 handles = parseHandles(src)
747 rawEnums = parseEnums(src)
748 bitfieldNames = parseBitfieldNames(src)
749 bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
750 bitfield64Names = parse64bitBitfieldNames(src)
751 bitfields64 = parse64bitBitfieldValues(src, bitfield64Names)
754 compositeTypes = parseCompositeTypesByVersion(src, versionsData)
755 allFunctions = parseFunctionsByVersion(src, versionsData)
757 for enum in rawEnums:
758 if enum.name in bitfieldEnums:
759 bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
763 for bitfieldName in bitfieldNames:
764 if not bitfieldName in [bitfield.name for bitfield in bitfields]:
766 bitfields.append(Bitfield(bitfieldName, []))
768 extensions = parseExtensions(src, versions, allFunctions, compositeTypes, enums, bitfields, handles, definitions)
770 # Populate alias fields
771 populateAliasesWithTypedefs(compositeTypes, src)
772 populateAliasesWithTypedefs(enums, src)
773 populateAliasesWithTypedefs(bitfields, src)
774 populateAliasesWithTypedefs(handles, src)
777 removeAliasedValues(enum)
779 # Make generator to create Deleter<VkAccelerationStructureNV>
780 for f in allFunctions:
781 if (f.name == 'vkDestroyAccelerationStructureNV'):
782 f.arguments[1].type[0] = 'VkAccelerationStructureNV'
784 # Dealias handles VkAccelerationStructureNV and VkAccelerationStructureKHR
785 for handle in handles:
786 if handle.name == 'VkAccelerationStructureKHR':
788 if handle.name == 'VkAccelerationStructureNV':
789 handle.isAlias = False
792 definitions = definitions,
795 bitfields = bitfields,
796 bitfields64 = bitfields64,
797 compositeTypes = compositeTypes,
798 functions = allFunctions,
799 extensions = extensions)
801 def splitUniqueAndDuplicatedEntries (handles):
802 listOfUniqueHandles = []
803 duplicates = OrderedDict()
804 for handle in handles:
805 if handle.alias != None:
806 duplicates[handle.alias] = handle
807 if not handle.isAlias:
808 listOfUniqueHandles.append(handle)
809 return listOfUniqueHandles, duplicates
811 def writeHandleType (api, filename):
812 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles)
815 yield "\t%s\t= 0," % uniqeHandles[0].getHandleType()
816 for handle in uniqeHandles[1:]:
817 yield "\t%s," % handle.getHandleType()
818 for duplicate in duplicatedHandles:
819 yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType())
820 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType())
822 def genHandlesBlock ():
823 yield "enum HandleType"
826 for line in indentLines(genHandles()):
832 writeInlFile(filename, INL_HEADER, genHandlesBlock())
834 def getEnumValuePrefix (enum):
835 prefix = enum.name[0]
836 for i in range(1, len(enum.name)):
837 if enum.name[i].isupper() and not enum.name[i-1].isupper():
839 prefix += enum.name[i].upper()
842 def parseInt (value):
843 if value[:2] == "0x":
844 return int(value, 16)
846 return int(value, 10)
848 def areEnumValuesLinear (enum):
850 for name, value in enum.values:
851 if value[:2] != "VK":
852 intValue = parseInt(value)
853 if intValue != curIndex:
854 # consider enums containing *_MAX_ENUM = 0x7FFFFFFF as linear
855 if intValue == 0x7FFFFFFF:
861 def genEnumSrc (enum):
862 yield "enum %s" % enum.name
866 if areEnumValuesLinear(enum):
867 hasMaxItem = parseInt(enum.values[-1][1]) == 0x7FFFFFFF
869 values = enum.values[:-1] if hasMaxItem else enum.values
870 lastItem = "\t%s_LAST," % getEnumValuePrefix(enum)
872 # linear values first, followed by *_LAST
873 lines += ["\t%s\t= %s," % v for v in values if v[1][:2] != "VK"]
874 lines.append(lastItem)
876 # equivalence enums and *_MAX_ENUM
877 lines += ["\t%s\t= %s," % v for v in values if v[1][:2] == "VK"]
879 lines.append("\t%s\t= %s," % enum.values[-1])
881 lines += ["\t%s\t= %s," % v for v in enum.values]
883 for line in indentLines(lines):
888 def genBitfieldSrc (bitfield):
889 if len(bitfield.values) > 0:
890 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
892 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
895 yield "typedef uint32_t %s;" % bitfield.name
897 def genBitfield64Src (bitfield64):
898 yield "typedef uint64_t %s;" % bitfield64.name
899 if len(bitfield64.values) > 0:
900 ptrn = "static const " + bitfield64.name + " %s\t= %s;"
901 for line in indentLines([ptrn % v for v in bitfield64.values]):
905 def genCompositeTypeSrc (type):
906 yield "%s %s" % (type.getClassName(), type.name)
908 for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]):
912 def genHandlesSrc (handles):
913 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles)
915 def genLines (handles):
916 for handle in uniqeHandles:
917 if handle.type == Handle.TYPE_DISP:
918 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
919 elif handle.type == Handle.TYPE_NONDISP:
920 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
922 for duplicate in duplicatedHandles:
923 if duplicate.type == Handle.TYPE_DISP:
924 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
925 elif duplicate.type == Handle.TYPE_NONDISP:
926 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
928 for line in indentLines(genLines(handles)):
931 def stripTrailingComment(str):
932 index = str.find("//")
937 def genDefinitionsSrc (definitions):
938 for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, stripTrailingComment(definition.value)) for definition in definitions]:
941 def genDefinitionsAliasSrc (definitions):
942 for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]:
943 if definition.value != definitions[definition].value and definition.value != definitions[definition].name:
944 raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value))
947 def genMaxFrameworkVersion (definitions):
948 maxApiVersionMajor = 1
949 maxApiVersionMinor = 0
950 for definition in definitions:
951 match = re.match("VK_API_VERSION_(\d+)_(\d+)", definition.name)
953 apiVersionMajor = int(match.group(1))
954 apiVersionMinor = int(match.group(2))
955 if apiVersionMajor > maxApiVersionMajor:
956 maxApiVersionMajor = apiVersionMajor
957 maxApiVersionMinor = apiVersionMinor
958 elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
959 maxApiVersionMinor = apiVersionMinor
960 yield "#define VK_API_MAX_FRAMEWORK_VERSION\tVK_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
962 def writeBasicTypes (api, filename):
965 definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
967 for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
971 for line in genHandlesSrc(api.handles):
975 for enum in api.enums:
977 for line in genEnumSrc(enum):
980 for enum2 in api.enums:
981 if enum2.alias == enum:
982 yield "typedef %s %s;" % (enum2.name, enum.name)
985 for bitfield in api.bitfields:
986 if not bitfield.isAlias:
987 for line in genBitfieldSrc(bitfield):
990 for bitfield2 in api.bitfields:
991 if bitfield2.alias == bitfield:
992 yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
995 for bitfield64 in api.bitfields64:
996 for line in genBitfield64Src(bitfield64):
999 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
1002 for ext in api.extensions:
1003 if ext.additionalDefs != None:
1004 for definition in ext.additionalDefs:
1005 yield "#define " + definition.name + " " + definition.value
1007 writeInlFile(filename, INL_HEADER, gen())
1009 def writeCompositeTypes (api, filename):
1011 for type in api.compositeTypes:
1012 type.checkAliasValidity()
1014 if not type.isAlias:
1015 for line in genCompositeTypeSrc(type):
1018 for type2 in api.compositeTypes:
1019 if type2.alias == type:
1020 yield "typedef %s %s;" % (type2.name, type.name)
1023 writeInlFile(filename, INL_HEADER, gen())
1025 def argListToStr (args):
1026 return ", ".join(v.getAsStringForArgumentList(' ') for v in args)
1028 def writeInterfaceDecl (api, filename, functionTypes, concrete):
1030 postfix = "" if concrete else " = 0"
1031 for function in api.functions:
1032 if not function.getType() in functionTypes:
1034 if not function.isAlias:
1035 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
1037 writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1039 def writeFunctionPtrTypes (api, filename):
1041 for function in api.functions:
1042 yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
1044 writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1046 def writeFunctionPointers (api, filename, functionTypes):
1047 def FunctionsYielder ():
1048 for function in api.functions:
1049 if function.getType() in functionTypes:
1050 if function.isAlias:
1051 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1052 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1054 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1056 writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1058 def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1059 def makeInitFunctionPointers ():
1060 for function in api.functions:
1061 if function.getType() in functionTypes and (cond == None or cond(function)):
1062 interfaceName = getInterfaceName(function)
1063 if function.isAlias:
1064 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1065 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1067 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1068 if function.alias != None:
1069 yield "if (!m_vk.%s)" % (getInterfaceName(function))
1070 yield " m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name)
1071 lines = [line.replace(' ', '\t') for line in indentLines(makeInitFunctionPointers())]
1072 writeInlFile(filename, INL_HEADER, lines)
1074 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1075 def makeFuncPtrInterfaceImpl ():
1076 for function in api.functions:
1077 if function.getType() in functionTypes and not function.isAlias:
1079 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
1081 if function.name == "vkEnumerateInstanceVersion":
1082 yield " if (m_vk.enumerateInstanceVersion)"
1083 yield " return m_vk.enumerateInstanceVersion(pApiVersion);"
1085 yield " *pApiVersion = VK_API_VERSION_1_0;"
1086 yield " return VK_SUCCESS;"
1087 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None:
1088 yield " vk::VkPhysicalDeviceProperties props;"
1089 yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1090 yield " if (props.apiVersion >= VK_API_VERSION_1_1)"
1091 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1093 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments))
1095 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1098 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1100 def writeStrUtilProto (api, filename):
1101 def makeStrUtilProto ():
1102 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]):
1105 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]):
1108 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]):
1111 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']):
1114 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]):
1117 writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1119 def writeStrUtilImpl (api, filename):
1120 def makeStrUtilImpl ():
1121 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]):
1125 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1128 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):
1133 for enum in api.enums:
1137 yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1139 yield "\tswitch (value)"
1141 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;"]):
1146 for bitfield in api.bitfields:
1147 if bitfield.isAlias:
1148 if bitfield.name != 'VkBuildAccelerationStructureFlagsNV':
1151 yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
1154 if len(bitfield.values) > 0:
1155 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1157 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
1160 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1162 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
1165 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
1167 for type in api.compositeTypes:
1168 if not type.isAlias:
1170 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1172 yield "\ts << \"%s = {\\n\";" % type.name
1173 for member in type.members:
1174 memberName = member.name
1177 if member.getType() in bitfieldTypeNames:
1178 valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name)
1179 elif member.getType() == "const char*" or member.getType() == "char*":
1180 valFmt = "getCharPtrStr(value.%s)" % member.name
1181 elif member.getType() == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1182 valFmt = "getWStr(value.%s)" % member.name
1183 elif member.arraySize != '':
1184 singleDimensional = not '][' in member.arraySize
1185 if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1186 valFmt = "(const char*)value.%s" % member.name
1187 elif singleDimensional and (member.getType() == 'char' or member.getType() == 'uint8_t'):
1188 newLine = "'\\n' << "
1189 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)
1191 if member.name == "memoryTypes" or member.name == "memoryHeaps":
1192 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1194 endIter = "DE_ARRAY_END(value.%s)" % member.name
1195 newLine = "'\\n' << "
1196 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1197 memberName = member.name
1199 valFmt = "value.%s" % member.name
1200 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1204 writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1207 def writeObjTypeImpl (api, filename):
1208 def makeObjTypeImpl ():
1210 yield "namespace vk"
1213 yield "template<typename T> VkObjectType getObjectType (void);"
1215 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]):
1220 writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1222 class ConstructorFunction:
1223 def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1226 self.objectType = objectType
1227 self.ifaceArgs = ifaceArgs
1228 self.arguments = arguments
1230 def getConstructorFunctions (api):
1233 Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")],
1234 Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")],
1235 Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")]
1237 for function in api.functions:
1238 if function.isAlias:
1240 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1241 if function.name == "vkCreateDisplayModeKHR":
1242 continue # No way to delete display modes (bug?)
1244 # \todo [pyry] Rather hacky
1245 ifaceArgs = ifacesDict[function.getType()]
1246 if function.name == "vkCreateDevice":
1247 ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs
1249 assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"])
1251 objectType = function.arguments[-1].type[0] #not getType() but type[0] on purpose
1252 arguments = function.arguments[:-1]
1253 funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments))
1256 def addVersionDefines(versionSpectrum):
1257 output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1260 def removeVersionDefines(versionSpectrum):
1261 output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()]
1264 def writeRefUtilProto (api, filename):
1265 functions = getConstructorFunctions(api)
1267 def makeRefUtilProto ():
1269 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]):
1272 writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1274 def writeRefUtilImpl (api, filename):
1275 functions = getConstructorFunctions(api)
1277 def makeRefUtilImpl ():
1278 yield "namespace refdetails"
1282 for function in api.functions:
1283 if function.getType() == Function.TYPE_DEVICE \
1284 and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1285 and not function.name == "vkDestroyDevice" \
1286 and not function.isAlias:
1287 objectType = function.arguments[-2].getType()
1289 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1291 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
1295 yield "} // refdetails"
1299 Function.TYPE_PLATFORM: "object",
1300 Function.TYPE_INSTANCE: "instance",
1301 Function.TYPE_DEVICE: "device"
1304 for function in functions:
1305 deleterArgsString = ''
1306 if function.name == "createDevice":
1307 # createDevice requires two additional parameters to setup VkDevice deleter
1308 deleterArgsString = "vkp, instance, object, " + function.arguments[-1].name
1310 deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1312 yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1314 yield "\t%s object = 0;" % function.objectType
1315 yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1316 yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1320 writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1322 def writeStructTraitsImpl (api, filename):
1324 for type in api.compositeTypes:
1325 if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias and type.name != "VkBaseOutStructure" and type.name != "VkBaseInStructure":
1326 yield "template<> VkStructureType getStructureType<%s> (void)" % type.name
1328 yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name)
1332 writeInlFile(filename, INL_HEADER, gen())
1334 def writeNullDriverImpl (api, filename):
1335 def genNullDriverImpl ():
1336 specialFuncNames = [
1337 "vkCreateGraphicsPipelines",
1338 "vkCreateComputePipelines",
1339 "vkCreateRayTracingPipelinesNV",
1340 "vkCreateRayTracingPipelinesKHR",
1341 "vkGetInstanceProcAddr",
1342 "vkGetDeviceProcAddr",
1343 "vkEnumeratePhysicalDevices",
1344 "vkEnumerateInstanceExtensionProperties",
1345 "vkEnumerateDeviceExtensionProperties",
1346 "vkGetPhysicalDeviceFeatures",
1347 "vkGetPhysicalDeviceFeatures2KHR",
1348 "vkGetPhysicalDeviceProperties",
1349 "vkGetPhysicalDeviceProperties2KHR",
1350 "vkGetPhysicalDeviceQueueFamilyProperties",
1351 "vkGetPhysicalDeviceMemoryProperties",
1352 "vkGetPhysicalDeviceFormatProperties",
1353 "vkGetPhysicalDeviceImageFormatProperties",
1355 "vkGetBufferMemoryRequirements",
1356 "vkGetBufferMemoryRequirements2KHR",
1357 "vkGetImageMemoryRequirements",
1358 "vkGetImageMemoryRequirements2KHR",
1362 "vkAllocateDescriptorSets",
1363 "vkFreeDescriptorSets",
1364 "vkResetDescriptorPool",
1365 "vkAllocateCommandBuffers",
1366 "vkFreeCommandBuffers",
1367 "vkCreateDisplayModeKHR",
1368 "vkCreateSharedSwapchainsKHR",
1369 "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1370 "vkGetPhysicalDeviceImageFormatProperties2KHR",
1371 "vkGetMemoryAndroidHardwareBufferANDROID",
1374 coreFunctions = [f for f in api.functions if not f.isAlias]
1375 specialFuncs = [f for f in coreFunctions if f.name in specialFuncNames]
1376 createFuncs = [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1377 destroyFuncs = [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1378 dummyFuncs = [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs]
1380 def getHandle (name):
1381 for handle in api.handles:
1382 if handle.name == name[0]:
1384 raise Exception("No such handle: %s" % name)
1386 for function in createFuncs:
1387 objectType = function.arguments[-1].type[:-1]
1388 argsStr = ", ".join([a.name for a in function.arguments[:-1]])
1390 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1392 yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1394 if getHandle(objectType).type == Handle.TYPE_NONDISP:
1395 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1397 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1401 for function in destroyFuncs:
1402 objectArg = function.arguments[-2]
1404 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1406 for arg in function.arguments[:-2]:
1407 yield "\tDE_UNREF(%s);" % arg.name
1409 if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
1410 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1412 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1417 for function in dummyFuncs:
1418 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1420 for arg in function.arguments:
1421 yield "\tDE_UNREF(%s);" % arg.name
1422 if function.returnType != "void":
1423 yield "\treturn VK_SUCCESS;"
1427 def genFuncEntryTable (type, name):
1428 funcs = [f for f in api.functions if f.getType() == type]
1430 for f in api.functions:
1432 refFuncs[f.alias] = f
1434 yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1436 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]):
1442 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1445 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1448 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1451 writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1453 def writeTypeUtil (api, filename):
1454 # Structs filled by API queries are not often used in test code
1455 QUERY_RESULT_TYPES = set([
1456 "VkPhysicalDeviceFeatures",
1457 "VkPhysicalDeviceLimits",
1458 "VkFormatProperties",
1459 "VkImageFormatProperties",
1460 "VkPhysicalDeviceSparseProperties",
1461 "VkQueueFamilyProperties",
1464 "StdVideoH264SpsVuiFlags",
1465 "StdVideoH264SpsFlags",
1466 "StdVideoH264PpsFlags",
1467 "StdVideoDecodeH264PictureInfoFlags",
1468 "StdVideoDecodeH264ReferenceInfoFlags",
1469 "StdVideoDecodeH264MvcElementFlags",
1470 "StdVideoEncodeH264SliceHeaderFlags",
1471 "StdVideoEncodeH264PictureInfoFlags",
1472 "StdVideoEncodeH264RefMgmtFlags",
1473 "StdVideoH265HrdFlags",
1474 "StdVideoH265VpsFlags",
1475 "StdVideoH265SpsVuiFlags",
1476 "StdVideoH265SpsFlags",
1477 "StdVideoH265PpsFlags",
1478 "StdVideoDecodeH265PictureInfoFlags",
1479 "StdVideoDecodeH265ReferenceInfoFlags",
1480 "StdVideoEncodeH265PictureInfoFlags"
1482 COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias])
1484 def isSimpleStruct (type):
1485 def hasArrayMember (type):
1486 for member in type.members:
1487 if member.arraySize != '':
1491 def hasCompositeMember (type):
1492 for member in type.members:
1493 if member.getType() in COMPOSITE_TYPES:
1497 return type.typeClass == CompositeType.CLASS_STRUCT and \
1498 type.members[0].getType() != "VkStructureType" and \
1499 not type.name in QUERY_RESULT_TYPES and \
1500 not hasArrayMember(type) and \
1501 not hasCompositeMember(type)
1504 for type in api.compositeTypes:
1505 if not isSimpleStruct(type) or type.isAlias:
1508 name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
1511 yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
1513 yield "\t%s res;" % type.name
1514 for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1516 yield "\treturn res;"
1519 writeInlFile(filename, INL_HEADER, gen())
1521 def writeDriverIds(filename):
1523 driverIdsString = []
1524 driverIdsString.append("static const struct\n"
1526 "\tstd::string driver;\n"
1528 "} driverIds [] =\n"
1531 vulkanCore = readFile(os.path.join(VULKAN_H_DIR, "vulkan_core.h"))
1533 items = re.search(r'(?:typedef\s+enum\s+VkDriverId\s*{)((.*\n)*)(?:}\s*VkDriverId\s*;)', vulkanCore).group(1).split(',')
1534 driverItems = dict()
1537 splitted = item.split('=')
1538 key = splitted[0].strip()
1539 value_str = splitted[1].strip()
1540 try: # is this previously defined value?
1541 value = driverItems[value_str]
1546 value_str = "\t// " + value_str
1547 driverItems[key] = value
1548 if not item == items[-1]:
1549 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}," + value_str)
1551 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}" + value_str)
1552 driverItems[key] = value
1554 driverIdsString.append("};")
1556 writeInlFile(filename, INL_HEADER, driverIdsString)
1559 def writeSupportedExtenions(api, filename):
1561 def writeExtensionsForVersions(map):
1564 result.append(" if (coreVersion >= " + str(version) + ")")
1566 for extension in map[version]:
1567 result.append(' dst.push_back("' + extension.name + '");')
1576 for ext in api.extensions:
1577 if ext.versionInCore != None:
1578 if ext.versionInCore[0] == 'INSTANCE':
1579 list = instanceMap.get(Version(ext.versionInCore[1:]))
1580 instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1582 list = deviceMap.get(Version(ext.versionInCore[1:]))
1583 deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1584 versionSet.add(Version(ext.versionInCore[1:]))
1586 lines = addVersionDefines(versionSet) + [
1588 "void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""),
1589 "{"] + writeExtensionsForVersions(deviceMap) + [
1592 "void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""),
1593 "{"] + writeExtensionsForVersions(instanceMap) + [
1595 ""] + removeVersionDefines(versionSet)
1596 writeInlFile(filename, INL_HEADER, lines)
1598 def writeExtensionFunctions (api, filename):
1600 def isInstanceExtension (ext):
1601 if ext.name and ext.functions:
1602 if ext.functions[0].getType() == Function.TYPE_INSTANCE:
1607 def isDeviceExtension (ext):
1608 if ext.name and ext.functions:
1609 if ext.functions[0].getType() == Function.TYPE_DEVICE:
1614 def writeExtensionNameArrays ():
1615 instanceExtensionNames = []
1616 deviceExtensionNames = []
1617 for ext in api.extensions:
1618 if ext.name and isInstanceExtension(ext):
1619 instanceExtensionNames += [ext.name]
1620 elif ext.name and isDeviceExtension(ext):
1621 deviceExtensionNames += [ext.name]
1622 yield '::std::string instanceExtensionNames[] =\n{'
1623 for instanceExtName in instanceExtensionNames:
1624 if (instanceExtName == instanceExtensionNames[len(instanceExtensionNames) - 1]):
1625 yield '\t"%s"' % instanceExtName
1627 yield '\t"%s",' % instanceExtName
1629 yield '::std::string deviceExtensionNames[] =\n{'
1630 for deviceExtName in deviceExtensionNames:
1631 if (deviceExtName == deviceExtensionNames[len(deviceExtensionNames) - 1]):
1632 yield '\t"%s"' % deviceExtName
1634 yield '\t"%s",' % deviceExtName
1637 def writeExtensionFunctions (functionType):
1639 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
1640 if functionType == Function.TYPE_INSTANCE:
1641 yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1642 dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
1643 elif functionType == Function.TYPE_DEVICE:
1644 yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1645 dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
1646 for ext in api.extensions:
1649 for func in ext.functions:
1650 if func.getType() == functionType:
1651 # only add functions with same vendor as extension
1652 # this is a workaroudn for entrypoints requiring more
1653 # than one excetions and lack of the dependency in vulkan_core.h
1654 vendor = ext.name.split('_')[1]
1655 if func.name.endswith(vendor):
1656 funcNames.append(func.name)
1658 yield '\tif (extName == "%s")' % ext.name
1660 for funcName in funcNames:
1661 if funcName in dg_list:
1662 yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
1664 yield '\t\tfunctions.push_back("%s");' % funcName
1665 if ext.name == "VK_KHR_device_group":
1666 for dg_func in dg_list:
1667 yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
1670 isFirstWrite = False
1671 if not isFirstWrite:
1672 yield '\tDE_FATAL("Extension name not found");'
1676 for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
1679 for line in writeExtensionFunctions(Function.TYPE_DEVICE):
1682 for line in writeExtensionNameArrays():
1685 writeInlFile(filename, INL_HEADER, lines)
1687 def writeCoreFunctionalities(api, filename):
1688 functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1689 lines = addVersionDefines(api.versions) + [
1691 'enum FunctionOrigin', '{'] + [line for line in indentLines([
1692 '\t' + functionOriginValues[0] + '\t= 0,',
1693 '\t' + functionOriginValues[1] + ',',
1694 '\t' + functionOriginValues[2]])] + [
1697 "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1698 "typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1699 "typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;",
1701 "void initApisMap (ApisMap& apis)",
1703 " apis.clear();"] + [
1704 " apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + str(v) + ", FunctionInfosList()));" for v in api.versions] + [
1708 for index, v in enumerate(api.versions):
1710 apiVersions.append("VK_VERSION_{0}_{1}".format(v.major, v.minor))
1711 # iterate over all functions that are core in latest vulkan version
1712 # note that first item in api.extension array are actually all definitions that are in vulkan.h.in before section with extensions
1713 for fun in api.extensions[0].functions:
1714 if fun.apiVersion in apiVersions:
1715 funcs.append(' apis[' + str(v) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));')
1716 lines = lines + [line for line in indentLines(funcs)] + [""]
1718 lines = lines + ["}", ""] + removeVersionDefines(api.versions)
1719 writeInlFile(filename, INL_HEADER, lines)
1721 def writeDeviceFeatures2(api, filename):
1722 # list of structures that should be tested with getPhysicalDeviceFeatures2
1723 # this is not posible to determine from vulkan_core.h, if new feature structures
1724 # are added they should be manualy added to this list
1725 testedStructures = [
1726 'VkPhysicalDeviceConditionalRenderingFeaturesEXT',
1727 'VkPhysicalDeviceScalarBlockLayoutFeatures',
1728 'VkPhysicalDevicePerformanceQueryFeaturesKHR',
1729 'VkPhysicalDevice16BitStorageFeatures',
1730 'VkPhysicalDeviceMultiviewFeatures',
1731 'VkPhysicalDeviceProtectedMemoryFeatures',
1732 'VkPhysicalDeviceSamplerYcbcrConversionFeatures',
1733 'VkPhysicalDeviceVariablePointersFeatures',
1734 'VkPhysicalDevice8BitStorageFeatures',
1735 'VkPhysicalDeviceShaderAtomicInt64Features',
1736 'VkPhysicalDeviceShaderFloat16Int8Features',
1737 'VkPhysicalDeviceBufferDeviceAddressFeaturesEXT',
1738 'VkPhysicalDeviceBufferDeviceAddressFeatures',
1739 'VkPhysicalDeviceDescriptorIndexingFeatures',
1740 'VkPhysicalDeviceTimelineSemaphoreFeatures',
1741 'VkPhysicalDeviceFragmentDensityMapFeaturesEXT',
1742 'VkPhysicalDeviceFragmentDensityMap2FeaturesEXT'
1744 # helper class used to encapsulate all data needed during generation
1745 class StructureDetail:
1746 def __init__ (self, name):
1747 nameResult = re.search('(.*)Features(.*)', name[len('VkPhysicalDevice'):])
1749 # generate structure type name from structure name
1750 # note that sometimes digits are separated with '_':
1751 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT
1752 # but mostly they are not:
1753 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES
1754 if (nameResult.group(1) == 'FragmentDensityMap2'):
1755 nameSplitUp = ['FRAGMENT', 'DENSITY', 'MAP', '2', 'FEATURES']
1757 nameSplit = re.findall(r'[1-9A-Z]+(?:[a-z1-9]+|[A-Z]*(?=[A-Z]|$))', nameResult.group(1))
1758 nameSplitUp = map(str.upper, nameSplit)
1759 nameSplitUp = list(nameSplitUp) + ['FEATURES']
1760 # check if there is extension suffix
1761 if (len(nameResult.group(2)) != 0):
1762 nameSplitUp.append(nameResult.group(2))
1764 self.sType = 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_' + '_'.join(nameSplitUp)
1765 self.instanceName = 'd' + name[11:]
1766 self.flagName = 'is' + name[16:]
1767 self.extension = None
1771 # helper extension class used in algorith below
1772 class StructureFoundContinueToNextOne(Exception):
1774 testedStructureDetail = [StructureDetail(struct) for struct in testedStructures]
1775 # iterate over all searched structures and find extensions that enable them
1776 for structureDetail in testedStructureDetail:
1778 # iterate over all extensions
1779 for extension in api.extensions[1:]:
1780 # check composite types and typedefs in case extension is part of core
1781 for structureList in [extension.compositeTypes, extension.typedefs]:
1782 # iterate over all structures added by extension
1783 for extensionStructure in structureList:
1784 # compare checked structure name to name of structure from extension
1785 if structureDetail.name == extensionStructure.name:
1786 structureDetail.extension = extension.name
1787 if extension.versionInCore is not None:
1788 structureDetail.major = extension.versionInCore[1]
1789 structureDetail.minor = extension.versionInCore[2]
1790 raise StructureFoundContinueToNextOne
1791 except StructureFoundContinueToNextOne:
1793 for structureDetail in testedStructureDetail:
1794 for compositeType in api.compositeTypes:
1795 if structureDetail.name != compositeType.name:
1797 structureMembers = compositeType.members[2:]
1798 structureDetail.members = [m.name for m in structureMembers]
1799 if structureDetail.major is not None:
1801 # if structure was not added with extension then check if
1802 # it was added directly with one of vulkan versions
1803 apiVersion = compositeType.apiVersion
1804 if apiVersion is None:
1806 structureDetail.major = apiVersion.major
1807 structureDetail.minor = apiVersion.minor
1809 # generate file content
1810 structureDefinitions = []
1811 featureEnabledFlags = []
1812 clearStructures = []
1815 verifyStructures = []
1816 for index, structureDetail in enumerate(testedStructureDetail):
1817 # create two instances of each structure
1818 nameSpacing = '\t' * int((55 - len(structureDetail.name)) / 4)
1819 structureDefinitions.append(structureDetail.name + nameSpacing + structureDetail.instanceName + '[count];')
1820 # create flags that check if proper extension or vulkan version is available
1822 extension = structureDetail.extension
1823 major = structureDetail.major
1824 if extension is not None:
1825 condition = ' checkExtension(properties, "' + extension + '")'
1826 if major is not None:
1828 condition += '\t' * int((39 - len(extension)) / 4) + '|| '
1830 condition += '\t' * 17 + ' '
1831 condition += 'context.contextSupports(vk::ApiVersion(' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
1833 nameSpacing = '\t' * int((40 - len(structureDetail.flagName)) / 4)
1834 featureEnabledFlags.append('const bool ' + structureDetail.flagName + nameSpacing + '=' + condition)
1835 # clear memory of each structure
1836 nameSpacing = '\t' * int((43 - len(structureDetail.instanceName)) / 4)
1837 clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx],' + nameSpacing + '0xFF * ndx, sizeof(' + structureDetail.name + '));')
1838 # construct structure chain
1839 nextInstanceName = 'DE_NULL';
1840 if index < len(testedStructureDetail)-1:
1841 nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
1842 structureChain.append('\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.sType + ';')
1843 structureChain.append('\t' + structureDetail.instanceName + '[ndx].pNext = ' + nextInstanceName + ';\n')
1844 # construct log section
1845 logStructures.append('if (' + structureDetail.flagName + ')')
1846 logStructures.append('\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;')
1847 #construct verification section
1848 verifyStructures.append('if (' + structureDetail.flagName + ' &&')
1849 for index, m in enumerate(structureDetail.members):
1850 prefix = '\t(' if index == 0 else '\t '
1851 postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
1852 verifyStructures.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
1853 verifyStructures.append('{\n\t\tTCU_FAIL("Mismatch between ' + structureDetail.name + '");\n}')
1854 # construct file content
1856 stream.extend(structureDefinitions)
1858 stream.extend(featureEnabledFlags)
1859 stream.append('\nfor (int ndx = 0; ndx < count; ++ndx)\n{')
1860 stream.extend(clearStructures)
1862 stream.extend(structureChain)
1863 stream.append('\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
1864 '\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
1865 '\textFeatures.pNext = &' + testedStructureDetail[0].instanceName + '[ndx];\n'
1866 '\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);\n}\n')
1867 stream.extend(logStructures)
1869 stream.extend(verifyStructures)
1870 writeInlFile(filename, INL_HEADER, stream)
1872 def generateDeviceFeaturesDefs(src):
1873 # look for definitions
1874 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_FEATURES(\w*)\s*='
1875 matches = re.findall(ptrnSType, src, re.M)
1876 matches = sorted(matches, key=lambda m: m[0])
1877 # construct final list
1879 for sType, sSuffix in matches:
1880 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1881 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Features' + sSuffix.replace('_', '') + ')'
1882 matchStructName = re.search(ptrnStructName, src, re.IGNORECASE)
1884 # handle special cases
1885 if sType == "EXCLUSIVE_SCISSOR":
1886 sType = "SCISSOR_EXCLUSIVE"
1887 elif sType == "ASTC_DECODE":
1888 sType = "ASTC_DECODE_MODE"
1889 if sType in {'VULKAN_1_1', 'VULKAN_1_2'}:
1891 # end handling special cases
1892 ptrnExtensionName = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_EXTENSION_NAME).+$'
1893 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1894 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_SPEC_VERSION).+$'
1895 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1896 defs.append( (sType, '', sSuffix, matchStructName.group(1), \
1897 matchExtensionName.group(0) if matchExtensionName else None,
1898 matchExtensionName.group(1) if matchExtensionName else None,
1899 matchSpecVersion.group(1) if matchSpecVersion else '0') )
1902 def generateDevicePropertiesDefs(src):
1903 # look for definitions
1904 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
1905 matches = re.findall(ptrnSType, src, re.M)
1906 matches = sorted(matches, key=lambda m: m[0])
1907 # construct final list
1909 for sType, sSuffix in matches:
1910 # handle special cases
1911 if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
1913 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
1914 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
1916 sExtSuffix = sSuffix
1917 suffixStart = sSuffix.rfind('_')
1919 sVerSuffix = sSuffix[:suffixStart]
1920 sExtSuffix = sSuffix[suffixStart:]
1921 # handle special case
1925 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1926 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
1927 matchStructName = re.search(ptrnStructName, src, re.M)
1930 if extType == "MAINTENANCE_3":
1931 extType = "MAINTENANCE3"
1932 elif extType == "DISCARD_RECTANGLE":
1933 extType = "DISCARD_RECTANGLES"
1934 elif extType == "DRIVER":
1935 extType = "DRIVER_PROPERTIES"
1936 elif extType == "POINT_CLIPPING":
1937 extType = "MAINTENANCE2"
1938 elif extType == "SHADER_CORE":
1939 extType = "SHADER_CORE_PROPERTIES"
1940 elif extType == "DRM":
1941 extType = "PHYSICAL_DEVICE_DRM"
1942 # end handling special cases
1943 ptrnExtensionName = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
1944 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1945 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
1946 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1947 defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
1948 matchExtensionName.group(0) if matchExtensionName else None,
1949 matchExtensionName.group(1) if matchExtensionName else None,
1950 matchSpecVersion.group (1) if matchSpecVersion else '0') )
1953 def writeDeviceFeatures(api, dfDefs, filename):
1954 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
1955 # and construct dictionary with all of their attributes
1958 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
1959 for structureType in api.compositeTypes:
1960 match = blobPattern.match(structureType.name)
1962 allMembers = [member.name for member in structureType.members]
1963 vkVersion = match.group(1)
1964 blobMembers[vkVersion] = allMembers[2:]
1965 blobStructs[vkVersion] = set()
1966 initFromBlobDefinitions = []
1967 emptyInitDefinitions = []
1968 # iterate over all feature structures
1969 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
1970 nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
1971 for structureType in api.compositeTypes:
1972 # skip structures that are not feature structures
1973 if not allFeaturesPattern.match(structureType.name):
1975 # skip structures that were previously identified as blobs
1976 if blobPattern.match(structureType.name):
1978 if structureType.isAlias:
1980 # skip sType and pNext and just grab third and next attributes
1981 structureMembers = structureType.members[2:]
1982 notPartOfBlob = True
1983 if nonExtFeaturesPattern.match(structureType.name):
1984 # check if this member is part of any of the blobs
1985 for blobName, blobMemberList in blobMembers.items():
1986 # if just one member is not part of this blob go to the next blob
1987 # (we asume that all members are part of blob - no need to check all)
1988 if structureMembers[0].name not in blobMemberList:
1990 # add another feature structure name to this blob
1991 blobStructs[blobName].add(structureType)
1992 # add specialization for this feature structure
1994 for member in structureMembers:
1995 memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
1997 "template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
2000 "}}".format(structureType.name, memberCopying)
2001 initFromBlobDefinitions.append(wholeFunction)
2002 notPartOfBlob = False
2003 # assuming that all members are part of blob, goto next
2005 # add empty template definition as on Fedora there are issue with
2006 # linking using just generic template - all specializations are needed
2008 emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2009 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2010 extensionDefines = []
2011 makeFeatureDescDefinitions = []
2012 featureStructWrappers = []
2013 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dfDefs):
2014 extensionNameDefinition = extName
2015 if not extensionNameDefinition:
2016 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2017 # construct defines with names
2019 extensionDefines.append(extLine)
2021 extensionDefines.append('#define {0} "not_existent_feature"'.format(extensionNameDefinition))
2022 # handle special cases
2023 if sType == "SCISSOR_EXCLUSIVE":
2024 sType = "EXCLUSIVE_SCISSOR"
2025 elif sType == "ASTC_DECODE_MODE":
2026 sType = "ASTC_DECODE"
2027 # end handling special cases
2028 # construct makeFeatureDesc template function definitions
2029 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2030 makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2031 "{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dfDefs)-idx))
2032 # construct CreateFeatureStruct wrapper block
2033 featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2034 # construct method that will check if structure sType is part of blob
2035 blobChecker = "bool isPartOfBlobFeatures (VkStructureType sType)\n{\n" \
2036 "\tconst std::vector<VkStructureType> sTypeVect =" \
2038 # iterate over blobs with list of structures
2039 for blobName in sorted(blobStructs.keys()):
2040 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2041 # iterate over all feature structures in current blob
2042 structuresList = list(blobStructs[blobName])
2043 structuresList = sorted(structuresList, key=lambda s: s.name)
2044 for structType in structuresList:
2045 # find definition of this structure in dfDefs
2046 structName = structType.name
2047 # handle special cases
2048 if structName == 'VkPhysicalDeviceShaderDrawParameterFeatures':
2049 structName = 'VkPhysicalDeviceShaderDrawParametersFeatures'
2050 # end handling special cases
2051 structDef = [s for s in dfDefs if s[3] == structName][0]
2052 sType = structDef[0]
2053 sSuffix = structDef[1] + structDef[2]
2054 # handle special cases
2055 if sType == "SCISSOR_EXCLUSIVE":
2056 sType = "EXCLUSIVE_SCISSOR"
2057 # end handling special cases
2058 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2059 blobChecker += "\t\t{0},\n".format(sTypeName)
2060 blobChecker += "\t};\n" \
2061 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2063 # combine all definition lists
2065 '#include "vkDeviceFeatures.hpp"\n',
2067 stream.extend(extensionDefines)
2069 stream.extend(initFromBlobDefinitions)
2070 stream.append('\n// generic template is not enough for some compilers')
2071 stream.extend(emptyInitDefinitions)
2073 stream.extend(makeFeatureDescDefinitions)
2075 stream.append('static const FeatureStructCreationData featureStructCreationArray[] =\n{')
2076 stream.extend(featureStructWrappers)
2077 stream.append('};\n')
2078 stream.append(blobChecker)
2079 stream.append('} // vk\n')
2080 writeInlFile(filename, INL_HEADER, stream)
2082 def writeDeviceProperties(api, dpDefs, filename):
2083 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2084 # and construct dictionary with all of their attributes
2087 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2088 for structureType in api.compositeTypes:
2089 match = blobPattern.match(structureType.name)
2091 allMembers = [member.name for member in structureType.members]
2092 vkVersion = match.group(1)
2093 blobMembers[vkVersion] = allMembers[2:]
2094 blobStructs[vkVersion] = set()
2095 initFromBlobDefinitions = []
2096 emptyInitDefinitions = []
2097 # iterate over all property structures
2098 allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2099 nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2100 for structureType in api.compositeTypes:
2101 # skip structures that are not property structures
2102 if not allPropertiesPattern.match(structureType.name):
2104 # skip structures that were previously identified as blobs
2105 if blobPattern.match(structureType.name):
2107 if structureType.isAlias:
2109 # skip sType and pNext and just grab third and next attributes
2110 structureMembers = structureType.members[2:]
2111 notPartOfBlob = True
2112 if nonExtPropertiesPattern.match(structureType.name):
2113 # check if this member is part of any of the blobs
2114 for blobName, blobMemberList in blobMembers.items():
2115 # if just one member is not part of this blob go to the next blob
2116 # (we asume that all members are part of blob - no need to check all)
2117 if structureMembers[0].name not in blobMemberList:
2119 # add another property structure name to this blob
2120 blobStructs[blobName].add(structureType)
2121 # add specialization for this property structure
2123 for member in structureMembers:
2124 if not member.arraySize:
2125 # handle special case
2126 if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2127 blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2128 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2129 # end handling special case
2131 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2133 memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type[0], member.arraySize[1:-1])
2135 "template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2138 "}}".format(structureType.name, memberCopying)
2139 initFromBlobDefinitions.append(wholeFunction)
2140 notPartOfBlob = False
2141 # assuming that all members are part of blob, goto next
2143 # add empty template definition as on Fedora there are issue with
2144 # linking using just generic template - all specializations are needed
2146 emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2147 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2148 extensionDefines = []
2149 makePropertyDescDefinitions = []
2150 propertyStructWrappers = []
2151 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dpDefs):
2152 extensionNameDefinition = extName
2153 if not extensionNameDefinition:
2154 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2155 # construct defines with names
2157 extensionDefines.append(extLine)
2159 extensionDefines.append('#define {0} "core_property"'.format(extensionNameDefinition))
2160 # construct makePropertyDesc template function definitions
2161 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2162 makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2163 "{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dpDefs)-idx))
2164 # construct CreateProperty struct wrapper block
2165 propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2166 # construct method that will check if structure sType is part of blob
2167 blobChecker = "bool isPartOfBlobProperties (VkStructureType sType)\n{\n" \
2168 "\tconst std::vector<VkStructureType> sTypeVect =" \
2170 # iterate over blobs with list of structures
2171 for blobName in sorted(blobStructs.keys()):
2172 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2173 # iterate over all feature structures in current blob
2174 structuresList = list(blobStructs[blobName])
2175 structuresList = sorted(structuresList, key=lambda s: s.name)
2176 for structType in structuresList:
2177 # find definition of this structure in dpDefs
2178 structName = structType.name
2179 structDef = [s for s in dpDefs if s[3] == structName][0]
2180 sType = structDef[0]
2181 sSuffix = structDef[1] + structDef[2]
2182 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2183 blobChecker += "\t\t{0},\n".format(sTypeName)
2184 blobChecker += "\t};\n" \
2185 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2187 # combine all definition lists
2189 '#include "vkDeviceProperties.hpp"\n',
2191 stream.extend(extensionDefines)
2193 stream.extend(initFromBlobDefinitions)
2194 stream.append('\n// generic template is not enough for some compilers')
2195 stream.extend(emptyInitDefinitions)
2197 stream.extend(makePropertyDescDefinitions)
2199 stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2200 stream.extend(propertyStructWrappers)
2201 stream.append('};\n')
2202 stream.append(blobChecker)
2203 stream.append('} // vk\n')
2204 writeInlFile(filename, INL_HEADER, stream)
2206 def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
2208 for _, _, _, extStruct, _, _, _ in dfDefs:
2209 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2210 stream.append(pattern.format(extStruct, nameSubStr))
2211 writeInlFile(filename, INL_HEADER, indentLines(stream))
2213 def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
2214 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
2215 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2217 def writeDeviceFeaturesContextDecl(dfDefs, filename):
2218 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2219 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2221 def writeDeviceFeaturesContextDefs(dfDefs, filename):
2222 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2223 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2225 def genericDevicePropertiesWriter(dfDefs, pattern, filename):
2227 for _, _, _, extStruct, _, _, _ in dfDefs:
2228 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2229 if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
2231 stream.append(pattern.format(extStruct, nameSubStr))
2232 writeInlFile(filename, INL_HEADER, indentLines(stream))
2234 def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
2235 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
2236 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2238 def writeDevicePropertiesContextDecl(dfDefs, filename):
2239 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2240 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2242 def writeDevicePropertiesContextDefs(dfDefs, filename):
2243 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2244 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2246 def splitWithQuotation(line):
2248 splitted = re.findall(r'[^"\s]\S*|".+?"', line)
2250 result.append(s.replace('"', ''))
2253 def writeMandatoryFeatures(filename):
2255 pattern = r'\s*([\w]+)\s+FEATURES\s+\((.*)\)\s+REQUIREMENTS\s+\((.*)\)'
2256 mandatoryFeatures = readFile(os.path.join(VULKAN_H_DIR, "mandatory_features.txt"))
2257 matches = re.findall(pattern, mandatoryFeatures)
2261 allRequirements = splitWithQuotation(m[2])
2262 dictData.append( [ m[0], m[1].strip(), allRequirements ] )
2263 if m[0] != 'VkPhysicalDeviceFeatures' :
2264 if (m[0] not in dictStructs):
2265 dictStructs[m[0]] = [m[0][2:3].lower() + m[0][3:]]
2266 if (allRequirements[0]):
2267 if (allRequirements[0] not in dictStructs[m[0]][1:]):
2268 dictStructs[m[0]].append(allRequirements[0])
2270 stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
2271 '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
2272 '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
2274 '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
2275 '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
2276 '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
2278 '\ttcu::TestLog& log = context.getTestContext().getLog();',
2279 '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
2280 '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
2281 '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
2282 '\tvoid** nextPtr = &coreFeatures.pNext;',
2285 listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
2286 for k, v in listStruct:
2287 if (v[1].startswith("ApiVersion")):
2288 cond = '\tif (context.contextSupports(vk::' + v[1] + '))'
2290 cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[1] + '"))'
2291 stream.extend(['\tvk::' + k + ' ' + v[0]+ ';',
2292 '\tdeMemset(&' + v[0] + ', 0, sizeof(' + v[0] + '));',
2297 for i, req in enumerate(reqs) :
2298 if (req.startswith("ApiVersion")):
2299 cond = cond + 'context.contextSupports(vk::' + req + ')'
2301 cond = cond + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2302 if i+1 < len(reqs) :
2303 cond = cond + ' || '
2305 stream.append('\t' + cond)
2306 stream.extend(['\t{',
2307 '\t\t' + v[0] + '.sType = getStructureType<' + k + '>();',
2308 '\t\t*nextPtr = &' + v[0] + ';',
2309 '\t\tnextPtr = &' + v[0] + '.pNext;',
2312 stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
2313 '\tbool result = true;',
2318 structName = 'coreFeatures.features';
2319 if v[0] != 'VkPhysicalDeviceFeatures' :
2320 structName = dictStructs[v[0]][0]
2323 for i, req in enumerate(v[2]) :
2324 if (req.startswith("ApiVersion")):
2325 condition = condition + 'context.contextSupports(vk::' + req + ')'
2327 condition = condition + req
2329 condition = condition + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2330 if i+1 < len(v[2]) :
2331 condition = condition + ' && '
2332 condition = condition + ' )'
2333 stream.append('\t' + condition)
2334 stream.append('\t{')
2335 # Don't need to support an AND case since that would just be another line in the .txt
2336 if len(v[1].split(" ")) == 1:
2337 stream.append('\t\tif ( ' + structName + '.' + v[1] + ' == VK_FALSE )')
2340 for i, feature in enumerate(v[1].split(" ")):
2342 condition = condition + ' && '
2343 condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
2344 condition = condition + ' )'
2345 stream.append('\t\t' + condition)
2346 featureSet = v[1].replace(" ", " or ")
2347 stream.extend(['\t\t{',
2348 '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
2349 '\t\t\tresult = false;',
2353 stream.append('\treturn result;')
2354 stream.append('}\n')
2355 writeInlFile(filename, INL_HEADER, stream)
2357 def writeExtensionList(filename, patternPart):
2359 stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(patternPart.title()))
2360 extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
2361 pattern = r'\s*([^\s]+)\s+{0}\s*[0-9_]*'.format(patternPart)
2362 matches = re.findall(pattern, extensionsData)
2364 stream.append('\t"' + m + '",')
2365 stream.append('};\n')
2366 writeInlFile(filename, INL_HEADER, stream)
2368 def preprocessTopInclude(src, dir):
2369 pattern = r'#include\s+"([^\n]+)"'
2371 inc = re.search(pattern, src)
2374 incFileName = inc.string[inc.start(1):inc.end(1)]
2375 patternIncNamed = r'#include\s+"' + incFileName + '"'
2376 incBody = readFile(os.path.join(dir, incFileName)) if incFileName != 'vulkan/vk_platform.h' else ''
2377 incBodySanitized = re.sub(pattern, '', incBody)
2378 bodyEndSanitized = re.sub(patternIncNamed, '', src[inc.end(0):])
2379 src = src[0:inc.start(0)] + incBodySanitized + bodyEndSanitized
2382 if __name__ == "__main__":
2383 # Read all .h files, with vulkan_core.h first
2384 files = os.listdir(VULKAN_H_DIR)
2385 files = [f for f in files if f.endswith(".h")]
2387 files.remove("vulkan_core.h")
2388 first = ["vk_video/vulkan_video_codecs_common.h", "vulkan_core.h"]
2389 files = first + files
2393 src += preprocessTopInclude(readFile(os.path.join(VULKAN_H_DIR,file)), VULKAN_H_DIR)
2395 src = re.sub('\s*//[^\n]*', '', src)
2396 src = re.sub('\n\n', '\n', src)
2400 platformFuncs = [Function.TYPE_PLATFORM]
2401 instanceFuncs = [Function.TYPE_INSTANCE]
2402 deviceFuncs = [Function.TYPE_DEVICE]
2404 dfd = generateDeviceFeaturesDefs(src)
2405 writeDeviceFeatures (api, dfd, os.path.join(VULKAN_DIR, "vkDeviceFeatures.inl"))
2406 writeDeviceFeaturesDefaultDeviceDefs (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
2407 writeDeviceFeaturesContextDecl (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDecl.inl"))
2408 writeDeviceFeaturesContextDefs (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDefs.inl"))
2410 dpd = generateDevicePropertiesDefs(src)
2411 writeDeviceProperties (api, dpd, os.path.join(VULKAN_DIR, "vkDeviceProperties.inl"))
2413 writeDevicePropertiesDefaultDeviceDefs (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
2414 writeDevicePropertiesContextDecl (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDecl.inl"))
2415 writeDevicePropertiesContextDefs (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDefs.inl"))
2417 writeHandleType (api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
2418 writeBasicTypes (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
2419 writeCompositeTypes (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
2420 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"), platformFuncs, False)
2421 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"), instanceFuncs, False)
2422 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"), deviceFuncs, False)
2423 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"), platformFuncs, True)
2424 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"), instanceFuncs, True)
2425 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"), deviceFuncs, True)
2426 writeFunctionPtrTypes (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
2427 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"), platformFuncs)
2428 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"), instanceFuncs)
2429 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"), deviceFuncs)
2430 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr")
2431 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"), instanceFuncs)
2432 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"), deviceFuncs)
2433 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver")
2434 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver")
2435 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver")
2436 writeStrUtilProto (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
2437 writeStrUtilImpl (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
2438 writeRefUtilProto (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
2439 writeRefUtilImpl (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
2440 writeStructTraitsImpl (api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl"))
2441 writeNullDriverImpl (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
2442 writeTypeUtil (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
2443 writeSupportedExtenions (api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl"))
2444 writeCoreFunctionalities (api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl"))
2445 writeExtensionFunctions (api, os.path.join(VULKAN_DIR, "vkExtensionFunctions.inl"))
2446 writeDeviceFeatures2 (api, os.path.join(VULKAN_DIR, "vkDeviceFeatures2.inl"))
2447 writeMandatoryFeatures ( os.path.join(VULKAN_DIR, "vkMandatoryFeatures.inl"))
2448 writeExtensionList ( os.path.join(VULKAN_DIR, "vkInstanceExtensions.inl"), 'INSTANCE')
2449 writeExtensionList ( os.path.join(VULKAN_DIR, "vkDeviceExtensions.inl"), 'DEVICE')
2450 writeDriverIds ( os.path.join(VULKAN_DIR, "vkKnownDriverIds.inl"))
2451 writeObjTypeImpl (api, os.path.join(VULKAN_DIR, "vkObjTypeImpl.inl"))