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"], "deUintptr",),
70 (["VisualID"], ["XlibVisualID"], "uint32_t"),
73 (["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"),
74 (["xcb_window_t"], ["XcbWindow"], "deUintptr"),
75 (["xcb_visualid_t"], ["XcbVisualid"], "uint32_t"),
77 # VK_KHR_wayland_surface
78 (["struct", "wl_display","*"], ["WaylandDisplayPtr"], "void*"),
79 (["struct", "wl_surface", "*"], ["WaylandSurfacePtr"], "void*"),
82 (["MirConnection", "*"], ["MirConnectionPtr"], "void*"),
83 (["MirSurface", "*"], ["MirSurfacePtr"], "void*"),
85 # VK_KHR_android_surface
86 (["ANativeWindow", "*"], ["AndroidNativeWindowPtr"], "void*"),
88 # VK_KHR_win32_surface
89 (["HINSTANCE"], ["Win32InstanceHandle"], "void*"),
90 (["HWND"], ["Win32WindowHandle"], "void*"),
91 (["HANDLE"], ["Win32Handle"], "void*"),
92 (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"),
93 (["AHardwareBuffer", "*"], ["AndroidHardwareBufferPtr"], "void*"),
94 (["HMONITOR"], ["Win32MonitorHandle"], "void*"),
95 (["LPCWSTR"], ["Win32LPCWSTR"], "const void*"),
97 # VK_EXT_acquire_xlib_display
98 (["RROutput"], ["RROutput"], "void*"),
100 (["zx_handle_t"], ["zx_handle_t"], "int32_t"),
101 (["GgpFrameToken"], ["GgpFrameToken"], "int32_t"),
102 (["GgpStreamDescriptor"], ["GgpStreamDescriptor"], "int32_t"),
103 (["CAMetalLayer"], ["CAMetalLayer"], "void*"),
106 PLATFORM_TYPE_NAMESPACE = "pt"
108 TYPE_SUBSTITUTIONS = [
109 ("uint8_t", "deUint8"),
110 ("uint16_t", "deUint16"),
111 ("uint64_t", "deUint64"),
112 ("int8_t", "deInt8"),
113 ("int16_t", "deInt16"),
114 ("int64_t", "deInt64"),
115 ("bool32_t", "deUint32"),
116 ("size_t", "deUintptr"),
119 ("DWORD", "deUint32"),
120 ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
123 EXTENSION_POSTFIXES = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK", "FUCHSIA", "GGP", "AMD"]
124 EXTENSION_POSTFIXES_STANDARD = ["KHR", "EXT"]
126 def prefixName (prefix, name):
127 name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
128 name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
131 name = name.replace("YCB_CR_", "YCBCR_")
132 name = name.replace("WIN_32_", "WIN32_")
133 name = name.replace("8_BIT_", "8BIT_")
134 name = name.replace("16_BIT_", "16BIT_")
135 name = name.replace("INT_64_", "INT64_")
136 name = name.replace("D_3_D_12_", "D3D12_")
137 name = name.replace("IOSSURFACE_", "IOS_SURFACE_")
138 name = name.replace("MAC_OS", "MACOS_")
139 name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_")
140 name = name.replace("VIEWPORT_W", "VIEWPORT_W_")
141 name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES")
142 name = name.replace("PHYSICAL_DEVICE_SHADER_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES")
143 name = name.replace("_PCIBUS_", "_PCI_BUS_")
144 name = name.replace("ASTCD", "ASTC_D")
145 name = name.replace("AABBNV", "AABB_NV")
146 name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
147 name = name.replace("SMBUILTINS", "SM_BUILTINS")
148 name = name.replace("ASTCHDRFEATURES", "ASTC_HDR_FEATURES")
149 name = name.replace("UINT_8", "UINT8")
150 name = name.replace("VULKAN_11_FEATURES", "VULKAN_1_1_FEATURES")
151 name = name.replace("VULKAN_11_PROPERTIES", "VULKAN_1_1_PROPERTIES")
152 name = name.replace("VULKAN_12_FEATURES", "VULKAN_1_2_FEATURES")
153 name = name.replace("VULKAN_12_PROPERTIES", "VULKAN_1_2_PROPERTIES")
154 name = name.replace("INT_8_", "INT8_")
155 name = name.replace("AABBNV", "AABB_NV")
156 name = name.replace("_H_264_", "_H264_")
157 name = name.replace("_H_265_", "_H265_")
158 name = name.replace("RDMAFEATURES", "RDMA_FEATURES")
164 def __init__ (self, versionTuple):
165 self.major = versionTuple[0]
166 self.minor = versionTuple[1]
167 self.patch = versionTuple[2]
171 return "VK_API_VERSION_%d_%d" % (self.major, self.minor)
172 return '0x%Xu' % (hash(self))
174 def isStandardVersion (self):
181 def getBestRepresentation (self):
182 if self.isStandardVersion():
183 return self.getInHex()
184 return self.getDefineName()
186 def getDefineName (self):
187 return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch)
190 return (self.major << 22) | (self.minor << 12) | self.patch
192 def __eq__ (self, other):
193 return self.major == other.major and self.minor == other.minor and self.patch == other.patch
196 return self.getBestRepresentation()
203 def __init__ (self, type, name):
209 def getHandleType (self):
210 return prefixName("HANDLE_TYPE_", self.name)
212 def checkAliasValidity (self):
216 return '%s (%s, %s)' % (self.name, self.alias, self.isAlias)
219 def __init__ (self, type, name, value):
227 return '%s = %s (%s)' % (self.name, self.value, self.type)
230 def __init__ (self, name, values):
236 def checkAliasValidity (self):
237 if self.alias != None:
238 if len(self.values) != len(self.alias.values):
239 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
240 for index, value in enumerate(self.values):
241 aliasVal = self.alias.values[index]
242 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
243 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
246 return '%s (%s) %s' % (self.name, self.alias, self.values)
249 def __init__ (self, name, values):
255 def checkAliasValidity (self):
256 if self.alias != None:
257 if len(self.values) != len(self.alias.values):
258 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
259 for index, value in enumerate(self.values):
260 aliasVal = self.alias.values[index]
261 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
262 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
265 return '%s (%s)' % (self.name, self.alias)
268 def __init__ (self, type, name, arraySizeOrFieldWidth):
269 type = type.replace('*',' *').replace('&',' &')
270 for src, dst in TYPE_SUBSTITUTIONS:
271 type = type.replace(src, dst)
272 self.type = type.split(' ')
273 for platformType, substitute, compat in PLATFORM_TYPES:
274 range = self.contains(self.type, platformType)
276 self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:]
279 if len(arraySizeOrFieldWidth) > 0 and arraySizeOrFieldWidth[0] == ':':
281 self.fieldWidth = arraySizeOrFieldWidth
283 self.arraySize = arraySizeOrFieldWidth
286 def contains(self, big, small):
287 for i in range(len(big)-len(small)+1):
288 for j in range(len(small)):
289 if big[i+j] != small[j]:
292 return i, i+len(small)
296 return ' '.join(self.type).replace(' *','*').replace(' &','&')
298 def getAsString (self, separator):
299 return '%s%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize, self.fieldWidth)
301 def getAsStringForArgumentList (self, separator):
302 return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize)
305 return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize)
307 def __eq__ (self, other):
308 if len(self.type) != len(other.type):
310 for index, type in enumerate(self.type):
311 if "*" == type or "&" == type or "const" == type or "volatile" == type:
312 if type != other.type[index]:
314 elif type != other.type[index] and \
315 type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \
316 other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD):
318 return self.arraySize == other.arraySize
320 def __ne__ (self, other):
321 return not self == other
327 def __init__ (self, typeClass, name, members, apiVersion = None):
328 self.typeClass = typeClass
330 self.members = members
333 self.apiVersion = apiVersion
335 def getClassName (self):
336 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
337 return names[self.typeClass]
339 def checkAliasValidity (self):
340 if self.alias != None:
341 if len(self.members) != len(self.alias.members):
342 raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name))
343 for index, member in enumerate(self.members ):
345 #if member != self.alias.members[index]:
346 #raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name))
347 #raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".")
349 return '%s (%s)' % (self.name, self.alias)
352 TYPE_PLATFORM = 0 # Not bound to anything
353 TYPE_INSTANCE = 1 # Bound to VkInstance
354 TYPE_DEVICE = 2 # Bound to VkDevice
356 def __init__ (self, name, returnType, arguments, apiVersion = None):
358 self.returnType = returnType
359 self.arguments = arguments
362 self.apiVersion = apiVersion
366 if self.name == "vkGetInstanceProcAddr":
367 return Function.TYPE_PLATFORM
368 assert len(self.arguments) > 0
369 firstArgType = self.arguments[0].getType()
370 if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
371 return Function.TYPE_INSTANCE
372 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
373 return Function.TYPE_DEVICE
375 return Function.TYPE_PLATFORM
377 def checkAliasValidity (self):
378 if self.alias != None:
379 if len(self.arguments) != len(self.alias.arguments):
380 raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name))
381 if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)):
382 raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name))
383 for index, argument in enumerate(self.arguments):
384 if argument != self.alias.arguments[index]:
385 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))
388 return '%s (%s)' % (self.name, self.alias)
391 def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, typedefs, versionInCore):
393 self.definitions = definitions
394 self.additionalDefs = additionalDefinitions
395 self.handles = handles
397 self.bitfields = bitfields
398 self.compositeTypes = compositeTypes
399 self.functions = functions
400 self.typedefs = typedefs
401 self.versionInCore = versionInCore
404 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)
407 def __init__ (self, versions, definitions, handles, enums, bitfields, bitfields64, compositeTypes, functions, extensions):
408 self.versions = versions
409 self.definitions = definitions
410 self.handles = handles
412 self.bitfields = bitfields
413 self.bitfields64 = bitfields64
414 self.compositeTypes = compositeTypes
415 self.functions = functions # \note contains extension functions as well
416 self.extensions = extensions
418 def readFile (filename):
419 with open(filename, 'rt') as f:
422 IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*'
423 WIDTH_PTRN = r'[:0-9]*'
424 TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
426 def getInterfaceName (function):
427 assert function.name[:2] == "vk"
428 return function.name[2].lower() + function.name[3:]
430 def getFunctionTypeName (function):
431 assert function.name[:2] == "vk"
432 return function.name[2:] + "Func"
434 def endsWith (str, postfix):
435 return str[-len(postfix):] == postfix
437 def splitNameExtPostfix (name):
438 knownExtPostfixes = EXTENSION_POSTFIXES
439 for postfix in knownExtPostfixes:
440 if endsWith(name, postfix):
441 return (name[:-len(postfix)], postfix)
444 def getBitEnumNameForBitfield (bitfieldName):
445 bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
446 assert bitfieldName[-1] == "s"
447 return bitfieldName[:-1] + "Bits" + postfix
449 def getBitfieldNameForBitEnum (bitEnumName):
450 bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
451 assert bitEnumName[-4:] == "Bits"
452 return bitEnumName[:-4] + "s" + postfix
454 def parsePreprocDefinedValue (src, name):
455 value = parsePreprocDefinedValueOptional(src, name)
457 raise Exception("No such definition: %s" % name)
460 def parsePreprocDefinedValueOptional (src, name):
461 definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
462 if definition is None:
464 value = definition.group(1).strip()
465 if value == "UINT32_MAX":
469 def parseEnum (name, src):
470 keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,\n}]+)\s*[,\n}]'
471 return Enum(name, re.findall(keyValuePtrn, src))
473 # \note Parses raw enums, some are mapped to bitfields later
474 def parseEnums (src):
475 matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
477 for enumname, contents, typename in matches:
478 enums.append(parseEnum(typename, contents))
481 def parseCompositeType (type, name, src):
482 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\]|\s*:\s*[0-9]+)*)\s*;'
483 matches = re.findall(typeNamePtrn, src)
484 members = [Variable(t.strip(), n.strip(), a.replace(' ', '')) for t, n, a, _ in matches]
485 return CompositeType(type, name, members)
487 def parseCompositeTypes (src):
488 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
489 matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
491 for type, structname, contents, typename in matches:
492 types.append(parseCompositeType(typeMap[type], typename, contents))
495 def parseCompositeTypesByVersion (src, versionsData):
497 # find occurence of extension is a place where
498 # we cant assign apiVersion to found structures
499 extPtrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
500 versionEnd = re.search(extPtrn, src)
501 versions = [Version((v[2], v[3], 0)) for v in versionsData]
502 versions.append(None)
504 # construct list of locations where version definitions start, and add the end of the file to it
505 sectionLocations = [versionDef[1] for versionDef in versionsData]
506 sectionLocations.append(versionEnd.start())
507 sectionLocations.append(len(src))
509 # construct function declaration pattern
510 ptrn = r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;'
511 regPtrn = re.compile(ptrn)
513 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
515 # iterate over all versions and find all structure definitions
516 for index, v in enumerate(versions):
517 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
518 for type, structname, contents, typename in matches:
519 compositeType = parseCompositeType(typeMap[type], typename, contents)
520 compositeType.apiVersion = v
521 types.append(compositeType)
524 def parseVersions (src):
525 # returns list of tuples each with four items:
526 # 1. string with version token (without ' 1' at the end)
527 # 2. starting point off version specific definitions in vulkan.h.in
528 # 3. major version number
529 # 4. minor version number
530 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)]
532 def parseHandles (src):
533 matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
535 typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
536 for type, name in matches:
537 handle = Handle(typeMap[type], name)
538 handles.append(handle)
541 def parseArgList (src):
542 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*'
544 for rawArg in src.split(','):
545 m = re.search(typeNamePtrn, rawArg)
546 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
549 def removeTypeExtPostfix (name):
550 for extPostfix in EXTENSION_POSTFIXES_STANDARD:
551 if endsWith(name, extPostfix):
552 return name[0:-len(extPostfix)]
555 def populateExtensionAliases(allObjects, extensionObjects):
556 for object in extensionObjects:
557 withoutPostfix = removeTypeExtPostfix(object.name)
558 if withoutPostfix != None and withoutPostfix in allObjects:
559 # max 1 alias is assumed by functions in this file
560 assert allObjects[withoutPostfix].alias == None
561 allObjects[withoutPostfix].alias = object
562 object.isAlias = True
563 for object in extensionObjects:
564 object.checkAliasValidity()
566 def populateAliasesWithTypedefs (objects, src):
568 for object in objects:
569 objectsByName[object.name] = object
570 ptrn = r'\s*typedef\s+' + object.name + r'\s+([^;]+)'
571 stash = re.findall(ptrn, src)
573 objExt = copy.deepcopy(object)
574 objExt.name = stash[0]
575 object.alias = objExt
576 objExt.isAlias = True
577 objects.append(objExt)
579 def removeAliasedValues (enum):
581 for name, value in enum.values:
582 valueByName[name] = value
584 def removeDefExtPostfix (name):
585 for extPostfix in EXTENSION_POSTFIXES:
586 if endsWith(name, "_" + extPostfix):
587 return name[0:-(len(extPostfix)+1)]
591 for name, value in enum.values:
592 withoutPostfix = removeDefExtPostfix(name)
593 if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value:
595 newValues.append((name, value))
596 enum.values = newValues
598 def parseFunctions (src):
599 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
600 matches = re.findall(ptrn, src)
602 for returnType, name, argList in matches:
603 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
606 def parseFunctionsByVersion (src, versions):
607 # construct list of locations where version definitions start, and add the end of the file to it
608 sectionLocations = [versionDef[1] for versionDef in versions]
609 sectionLocations.append(len(src))
611 # construct function declaration pattern
612 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
613 regPtrn = re.compile(ptrn)
616 # iterate over all versions and find all function definitions
617 for index, v in enumerate(versions):
618 matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
619 for returnType, name, argList in matches:
620 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), v[0]))
623 def splitByExtension (src):
624 ptrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
625 # Construct long pattern that will be used to split whole source by extensions
626 match = "#define\s+("
627 for part in re.finditer(ptrn, src):
628 match += part.group(1)+"|"
629 match = match[:-1] + ")\s+1"
630 parts = re.split(match, src)
632 # First part is core, following tuples contain extension name and all its definitions
633 byExtension = [(None, parts[0])]
634 for ndx in range(1, len(parts), 2):
635 byExtension.append((parts[ndx], parts[ndx+1]))
638 def parseDefinitions (extensionName, src):
640 def skipDefinition (extensionName, definition):
641 if extensionName == None:
643 extNameUpper = extensionName.upper()
644 extNameUpper = extNameUpper.replace("VK_KHR_SYNCHRONIZATION2", "VK_KHR_SYNCHRONIZATION_2")
645 extNameUpper = extNameUpper.replace("VK_INTEL_SHADER_INTEGER_FUNCTIONS2", "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2")
646 extNameUpper = extNameUpper.replace("VK_EXT_ROBUSTNESS2", "VK_EXT_ROBUSTNESS_2")
647 extNameUpper = extNameUpper.replace("VK_EXT_FRAGMENT_DENSITY_MAP2", "VK_EXT_FRAGMENT_DENSITY_MAP_2")
648 extNameUpper = extNameUpper.replace("VK_AMD_SHADER_CORE_PROPERTIES2", "VK_AMD_SHADER_CORE_PROPERTIES_2")
649 extNameUpper = extNameUpper.replace("VK_EXT_EXTENDED_DYNAMIC_STATE2", "VK_EXT_EXTENDED_DYNAMIC_STATE_2")
651 if definition[0].startswith(extNameUpper) and definition[1].isdigit():
653 if definition[0].startswith(extNameUpper):
655 if definition[1].isdigit():
659 ptrn = r'#define\s+([^\s]+)\s+([^\r\n]+)'
660 matches = re.findall(ptrn, src)
662 return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)]
664 def parseTypedefs (src):
666 ptrn = r'typedef\s+([^\s]+)\s+([^\r\n]+);'
667 matches = re.findall(ptrn, src)
669 return [Definition(None, match[0], match[1]) for match in matches]
671 def parseExtensions (src, versions, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions):
673 def getCoreVersion (extensionName, extensionsData):
674 # returns None when extension was not added to core for any Vulkan version
675 # returns array containing DEVICE or INSTANCE string followed by the vulkan version in which this extension is core
676 # note that this function is also called for vulkan 1.0 source for which extName is None
677 if not extensionName:
679 ptrn = extensionName + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)'
680 coreVersion = re.search(ptrn, extensionsData, re.I)
681 if coreVersion != None:
682 return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]]
685 extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
686 splitSrc = splitByExtension(src)
688 functionsByName = {function.name: function for function in allFunctions}
689 compositeTypesByName = {compType.name: compType for compType in allCompositeTypes}
690 enumsByName = {enum.name: enum for enum in allEnums}
691 bitfieldsByName = {bitfield.name: bitfield for bitfield in allBitfields}
692 handlesByName = {handle.name: handle for handle in allHandles}
693 definitionsByName = {definition.name: definition for definition in allDefinitions}
695 for extensionName, extensionSrc in splitSrc:
696 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValueOptional(extensionSrc, v.getInHex())) for v in versions]
697 definitions.extend([Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS])
698 definitions = [definition for definition in definitions if definition.value != None]
699 additionalDefinitions = parseDefinitions(extensionName, extensionSrc)
700 handles = parseHandles(extensionSrc)
701 functions = parseFunctions(extensionSrc)
702 compositeTypes = parseCompositeTypes(extensionSrc)
703 rawEnums = parseEnums(extensionSrc)
704 bitfieldNames = parseBitfieldNames(extensionSrc)
705 typedefs = parseTypedefs(extensionSrc)
706 enumBitfieldNames = [getBitEnumNameForBitfield(name) for name in bitfieldNames]
707 enums = [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
709 extCoreVersion = getCoreVersion(extensionName, extensionsData)
710 extFunctions = [functionsByName[function.name] for function in functions]
711 extCompositeTypes = [compositeTypesByName[compositeType.name] for compositeType in compositeTypes]
712 extEnums = [enumsByName[enum.name] for enum in enums]
713 extBitfields = [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames]
714 extHandles = [handlesByName[handle.name] for handle in handles]
715 extDefinitions = [definitionsByName[definition.name] for definition in definitions]
717 if extCoreVersion != None:
718 populateExtensionAliases(functionsByName, extFunctions)
719 populateExtensionAliases(handlesByName, extHandles)
720 populateExtensionAliases(enumsByName, extEnums)
721 populateExtensionAliases(bitfieldsByName, extBitfields)
722 populateExtensionAliases(compositeTypesByName, extCompositeTypes)
723 extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, typedefs, extCoreVersion))
726 def parseBitfieldNames (src):
727 ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
728 matches = re.findall(ptrn, src)
732 def parse64bitBitfieldNames (src):
733 ptrn = r'typedef\s+VkFlags64\s(' + IDENT_PTRN + r')\s*;'
734 matches = re.findall(ptrn, src)
738 def parse64bitBitfieldValues (src, bitfieldNamesList):
741 for bitfieldName in bitfieldNamesList:
742 ptrn = r'static const ' + bitfieldName + r'\s*(' + IDENT_PTRN + r')\s*=\s*([a-zA-Z0-9_]+)\s*;'
743 matches = re.findall(ptrn, src)
744 bitfields64.append(Bitfield(bitfieldName, matches))
749 versionsData = parseVersions(src)
750 versions = [Version((v[2], v[3], 0)) for v in versionsData]
751 definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValue(src, v.getInHex())) for v in versions] +\
752 [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
754 handles = parseHandles(src)
755 rawEnums = parseEnums(src)
756 bitfieldNames = parseBitfieldNames(src)
757 bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
758 bitfield64Names = parse64bitBitfieldNames(src)
759 bitfields64 = parse64bitBitfieldValues(src, bitfield64Names)
762 compositeTypes = parseCompositeTypesByVersion(src, versionsData)
763 allFunctions = parseFunctionsByVersion(src, versionsData)
765 for enum in rawEnums:
766 if enum.name in bitfieldEnums:
767 bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
771 for bitfieldName in bitfieldNames:
772 if not bitfieldName in [bitfield.name for bitfield in bitfields]:
774 bitfields.append(Bitfield(bitfieldName, []))
776 extensions = parseExtensions(src, versions, allFunctions, compositeTypes, enums, bitfields, handles, definitions)
778 # Populate alias fields
779 populateAliasesWithTypedefs(compositeTypes, src)
780 populateAliasesWithTypedefs(enums, src)
781 populateAliasesWithTypedefs(bitfields, src)
782 populateAliasesWithTypedefs(handles, src)
785 removeAliasedValues(enum)
787 # Make generator to create Deleter<VkAccelerationStructureNV>
788 for f in allFunctions:
789 if (f.name == 'vkDestroyAccelerationStructureNV'):
790 f.arguments[1].type[0] = 'VkAccelerationStructureNV'
792 # Dealias handles VkAccelerationStructureNV and VkAccelerationStructureKHR
793 for handle in handles:
794 if handle.name == 'VkAccelerationStructureKHR':
796 if handle.name == 'VkAccelerationStructureNV':
797 handle.isAlias = False
800 definitions = definitions,
803 bitfields = bitfields,
804 bitfields64 = bitfields64,
805 compositeTypes = compositeTypes,
806 functions = allFunctions,
807 extensions = extensions)
809 def splitUniqueAndDuplicatedEntries (handles):
810 listOfUniqueHandles = []
811 duplicates = OrderedDict()
812 for handle in handles:
813 if handle.alias != None:
814 duplicates[handle.alias] = handle
815 if not handle.isAlias:
816 listOfUniqueHandles.append(handle)
817 return listOfUniqueHandles, duplicates
819 def writeHandleType (api, filename):
820 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles)
823 yield "\t%s\t= 0," % uniqeHandles[0].getHandleType()
824 for handle in uniqeHandles[1:]:
825 yield "\t%s," % handle.getHandleType()
826 for duplicate in duplicatedHandles:
827 yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType())
828 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType())
830 def genHandlesBlock ():
831 yield "enum HandleType"
834 for line in indentLines(genHandles()):
840 writeInlFile(filename, INL_HEADER, genHandlesBlock())
842 def getEnumValuePrefix (enum):
843 prefix = enum.name[0]
844 for i in range(1, len(enum.name)):
845 if enum.name[i].isupper() and not enum.name[i-1].isupper():
847 prefix += enum.name[i].upper()
850 def parseInt (value):
851 if value[:2] == "0x":
852 return int(value, 16)
854 return int(value, 10)
856 def areEnumValuesLinear (enum):
858 for name, value in enum.values:
859 if value[:2] != "VK":
860 intValue = parseInt(value)
861 if intValue != curIndex:
862 # consider enums containing *_MAX_ENUM = 0x7FFFFFFF as linear
863 if intValue == 0x7FFFFFFF:
869 def genEnumSrc (enum):
870 yield "enum %s" % enum.name
873 lines = ["\t%s\t= %s," % v for v in enum.values]
874 if areEnumValuesLinear(enum):
875 lastItem = "\t%s_LAST," % getEnumValuePrefix(enum)
876 if parseInt(enum.values[-1][1]) == 0x7FFFFFFF:
877 # if last enum item is *_MAX_ENUM then we need to make sure
878 # it stays last entry also if we append *_LAST to generated
879 # source (without this value of *_LAST won't be correct)
880 lines.insert(-1, lastItem)
882 lines.append(lastItem)
884 for line in indentLines(lines):
889 def genBitfieldSrc (bitfield):
890 if len(bitfield.values) > 0:
891 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
893 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
896 yield "typedef uint32_t %s;" % bitfield.name
898 def genBitfield64Src (bitfield64):
899 yield "typedef deUint64 %s;" % bitfield64.name
900 if len(bitfield64.values) > 0:
901 ptrn = "static const " + bitfield64.name + " %s\t= %s;"
902 for line in indentLines([ptrn % v for v in bitfield64.values]):
906 def genCompositeTypeSrc (type):
907 yield "%s %s" % (type.getClassName(), type.name)
909 for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]):
913 def genHandlesSrc (handles):
914 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles)
916 def genLines (handles):
917 for handle in uniqeHandles:
918 if handle.type == Handle.TYPE_DISP:
919 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
920 elif handle.type == Handle.TYPE_NONDISP:
921 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
923 for duplicate in duplicatedHandles:
924 if duplicate.type == Handle.TYPE_DISP:
925 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
926 elif duplicate.type == Handle.TYPE_NONDISP:
927 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
929 for line in indentLines(genLines(handles)):
932 def stripTrailingComment(str):
933 index = str.find("//")
938 def genDefinitionsSrc (definitions):
939 for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, stripTrailingComment(definition.value)) for definition in definitions]:
942 def genDefinitionsAliasSrc (definitions):
943 for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]:
944 if definition.value != definitions[definition].value and definition.value != definitions[definition].name:
945 raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value))
948 def genMaxFrameworkVersion (definitions):
949 maxApiVersionMajor = 1
950 maxApiVersionMinor = 0
951 for definition in definitions:
952 match = re.match("VK_API_VERSION_(\d+)_(\d+)", definition.name)
954 apiVersionMajor = int(match.group(1))
955 apiVersionMinor = int(match.group(2))
956 if apiVersionMajor > maxApiVersionMajor:
957 maxApiVersionMajor = apiVersionMajor
958 maxApiVersionMinor = apiVersionMinor
959 elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
960 maxApiVersionMinor = apiVersionMinor
961 yield "#define VK_API_MAX_FRAMEWORK_VERSION\tVK_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
963 def writeBasicTypes (api, filename):
966 definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
968 for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
972 for line in genHandlesSrc(api.handles):
976 for enum in api.enums:
978 for line in genEnumSrc(enum):
981 for enum2 in api.enums:
982 if enum2.alias == enum:
983 yield "typedef %s %s;" % (enum2.name, enum.name)
986 for bitfield in api.bitfields:
987 if not bitfield.isAlias:
988 for line in genBitfieldSrc(bitfield):
991 for bitfield2 in api.bitfields:
992 if bitfield2.alias == bitfield:
993 yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
996 for bitfield64 in api.bitfields64:
997 for line in genBitfield64Src(bitfield64):
1000 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
1003 for ext in api.extensions:
1004 if ext.additionalDefs != None:
1005 for definition in ext.additionalDefs:
1006 yield "#define " + definition.name + " " + definition.value
1008 writeInlFile(filename, INL_HEADER, gen())
1010 def writeCompositeTypes (api, filename):
1012 for type in api.compositeTypes:
1013 type.checkAliasValidity()
1015 if not type.isAlias:
1016 for line in genCompositeTypeSrc(type):
1019 for type2 in api.compositeTypes:
1020 if type2.alias == type:
1021 yield "typedef %s %s;" % (type2.name, type.name)
1024 writeInlFile(filename, INL_HEADER, gen())
1026 def argListToStr (args):
1027 return ", ".join(v.getAsStringForArgumentList(' ') for v in args)
1029 def writeInterfaceDecl (api, filename, functionTypes, concrete):
1031 postfix = "" if concrete else " = 0"
1032 for function in api.functions:
1033 if not function.getType() in functionTypes:
1035 if not function.isAlias:
1036 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
1038 writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1040 def writeFunctionPtrTypes (api, filename):
1042 for function in api.functions:
1043 yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
1045 writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1047 def writeFunctionPointers (api, filename, functionTypes):
1048 def FunctionsYielder ():
1049 for function in api.functions:
1050 if function.getType() in functionTypes:
1051 if function.isAlias:
1052 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1053 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1055 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1057 writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1059 def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1060 def makeInitFunctionPointers ():
1061 for function in api.functions:
1062 if function.getType() in functionTypes and (cond == None or cond(function)):
1063 interfaceName = getInterfaceName(function)
1064 if function.isAlias:
1065 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1066 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1068 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1069 if function.alias != None:
1070 yield "if (!m_vk.%s)" % (getInterfaceName(function))
1071 yield " m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name)
1072 lines = [line.replace(' ', '\t') for line in indentLines(makeInitFunctionPointers())]
1073 writeInlFile(filename, INL_HEADER, lines)
1075 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1076 def makeFuncPtrInterfaceImpl ():
1077 for function in api.functions:
1078 if function.getType() in functionTypes and not function.isAlias:
1080 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
1082 if function.name == "vkEnumerateInstanceVersion":
1083 yield " if (m_vk.enumerateInstanceVersion)"
1084 yield " return m_vk.enumerateInstanceVersion(pApiVersion);"
1086 yield " *pApiVersion = VK_API_VERSION_1_0;"
1087 yield " return VK_SUCCESS;"
1088 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None:
1089 yield " vk::VkPhysicalDeviceProperties props;"
1090 yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1091 yield " if (props.apiVersion >= VK_API_VERSION_1_1)"
1092 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1094 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments))
1096 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1099 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1101 def writeStrUtilProto (api, filename):
1102 def makeStrUtilProto ():
1103 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]):
1106 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]):
1109 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]):
1112 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']):
1115 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]):
1118 writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1120 def writeStrUtilImpl (api, filename):
1121 def makeStrUtilImpl ():
1122 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]):
1126 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1129 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):
1134 for enum in api.enums:
1138 yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1140 yield "\tswitch (value)"
1142 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;"]):
1147 for bitfield in api.bitfields:
1148 if bitfield.isAlias:
1149 if bitfield.name != 'VkBuildAccelerationStructureFlagsNV':
1152 yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
1155 if len(bitfield.values) > 0:
1156 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1158 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
1161 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1163 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
1166 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
1168 for type in api.compositeTypes:
1169 if not type.isAlias:
1171 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1173 yield "\ts << \"%s = {\\n\";" % type.name
1174 for member in type.members:
1175 memberName = member.name
1178 if member.getType() in bitfieldTypeNames:
1179 valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name)
1180 elif member.getType() == "const char*" or member.getType() == "char*":
1181 valFmt = "getCharPtrStr(value.%s)" % member.name
1182 elif member.getType() == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1183 valFmt = "getWStr(value.%s)" % member.name
1184 elif member.arraySize != '':
1185 singleDimensional = not '][' in member.arraySize
1186 if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1187 valFmt = "(const char*)value.%s" % member.name
1188 elif singleDimensional and (member.getType() == 'char' or member.getType() == 'deUint8'):
1189 newLine = "'\\n' << "
1190 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)
1192 if member.name == "memoryTypes" or member.name == "memoryHeaps":
1193 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1195 endIter = "DE_ARRAY_END(value.%s)" % member.name
1196 newLine = "'\\n' << "
1197 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1198 memberName = member.name
1200 valFmt = "value.%s" % member.name
1201 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1205 writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1208 def writeObjTypeImpl (api, filename):
1209 def makeObjTypeImpl ():
1211 yield "namespace vk"
1214 yield "template<typename T> VkObjectType getObjectType (void);"
1216 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]):
1221 writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1223 class ConstructorFunction:
1224 def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1227 self.objectType = objectType
1228 self.ifaceArgs = ifaceArgs
1229 self.arguments = arguments
1231 def getConstructorFunctions (api):
1234 Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")],
1235 Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")],
1236 Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")]
1238 for function in api.functions:
1239 if function.isAlias:
1241 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1242 if function.name == "vkCreateDisplayModeKHR":
1243 continue # No way to delete display modes (bug?)
1245 # \todo [pyry] Rather hacky
1246 ifaceArgs = ifacesDict[function.getType()]
1247 if function.name == "vkCreateDevice":
1248 ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs
1250 assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"])
1252 objectType = function.arguments[-1].type[0] #not getType() but type[0] on purpose
1253 arguments = function.arguments[:-1]
1254 funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments))
1257 def addVersionDefines(versionSpectrum):
1258 output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1261 def removeVersionDefines(versionSpectrum):
1262 output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()]
1265 def writeRefUtilProto (api, filename):
1266 functions = getConstructorFunctions(api)
1268 def makeRefUtilProto ():
1270 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]):
1273 writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1275 def writeRefUtilImpl (api, filename):
1276 functions = getConstructorFunctions(api)
1278 def makeRefUtilImpl ():
1279 yield "namespace refdetails"
1283 for function in api.functions:
1284 if function.getType() == Function.TYPE_DEVICE \
1285 and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1286 and not function.name == "vkDestroyDevice" \
1287 and not function.isAlias:
1288 objectType = function.arguments[-2].getType()
1290 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1292 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
1296 yield "} // refdetails"
1300 Function.TYPE_PLATFORM: "object",
1301 Function.TYPE_INSTANCE: "instance",
1302 Function.TYPE_DEVICE: "device"
1305 for function in functions:
1306 deleterArgsString = ''
1307 if function.name == "createDevice":
1308 # createDevice requires two additional parameters to setup VkDevice deleter
1309 deleterArgsString = "vkp, instance, object, " + function.arguments[-1].name
1311 deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1313 yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1315 yield "\t%s object = 0;" % function.objectType
1316 yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1317 yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1321 writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1323 def writeStructTraitsImpl (api, filename):
1325 for type in api.compositeTypes:
1326 if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias and type.name != "VkBaseOutStructure" and type.name != "VkBaseInStructure":
1327 yield "template<> VkStructureType getStructureType<%s> (void)" % type.name
1329 yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name)
1333 writeInlFile(filename, INL_HEADER, gen())
1335 def writeNullDriverImpl (api, filename):
1336 def genNullDriverImpl ():
1337 specialFuncNames = [
1338 "vkCreateGraphicsPipelines",
1339 "vkCreateComputePipelines",
1340 "vkCreateRayTracingPipelinesNV",
1341 "vkCreateRayTracingPipelinesKHR",
1342 "vkGetInstanceProcAddr",
1343 "vkGetDeviceProcAddr",
1344 "vkEnumeratePhysicalDevices",
1345 "vkEnumerateInstanceExtensionProperties",
1346 "vkEnumerateDeviceExtensionProperties",
1347 "vkGetPhysicalDeviceFeatures",
1348 "vkGetPhysicalDeviceFeatures2KHR",
1349 "vkGetPhysicalDeviceProperties",
1350 "vkGetPhysicalDeviceProperties2KHR",
1351 "vkGetPhysicalDeviceQueueFamilyProperties",
1352 "vkGetPhysicalDeviceMemoryProperties",
1353 "vkGetPhysicalDeviceFormatProperties",
1354 "vkGetPhysicalDeviceImageFormatProperties",
1356 "vkGetBufferMemoryRequirements",
1357 "vkGetBufferMemoryRequirements2KHR",
1358 "vkGetImageMemoryRequirements",
1359 "vkGetImageMemoryRequirements2KHR",
1363 "vkAllocateDescriptorSets",
1364 "vkFreeDescriptorSets",
1365 "vkResetDescriptorPool",
1366 "vkAllocateCommandBuffers",
1367 "vkFreeCommandBuffers",
1368 "vkCreateDisplayModeKHR",
1369 "vkCreateSharedSwapchainsKHR",
1370 "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1371 "vkGetPhysicalDeviceImageFormatProperties2KHR",
1372 "vkGetMemoryAndroidHardwareBufferANDROID",
1375 coreFunctions = [f for f in api.functions if not f.isAlias]
1376 specialFuncs = [f for f in coreFunctions if f.name in specialFuncNames]
1377 createFuncs = [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1378 destroyFuncs = [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1379 dummyFuncs = [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs]
1381 def getHandle (name):
1382 for handle in api.handles:
1383 if handle.name == name[0]:
1385 raise Exception("No such handle: %s" % name)
1387 for function in createFuncs:
1388 objectType = function.arguments[-1].type[:-1]
1389 argsStr = ", ".join([a.name for a in function.arguments[:-1]])
1391 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1393 yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1395 if getHandle(objectType).type == Handle.TYPE_NONDISP:
1396 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1398 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1402 for function in destroyFuncs:
1403 objectArg = function.arguments[-2]
1405 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1407 for arg in function.arguments[:-2]:
1408 yield "\tDE_UNREF(%s);" % arg.name
1410 if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
1411 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1413 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1418 for function in dummyFuncs:
1419 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1421 for arg in function.arguments:
1422 yield "\tDE_UNREF(%s);" % arg.name
1423 if function.returnType != "void":
1424 yield "\treturn VK_SUCCESS;"
1428 def genFuncEntryTable (type, name):
1429 funcs = [f for f in api.functions if f.getType() == type]
1431 for f in api.functions:
1433 refFuncs[f.alias] = f
1435 yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1437 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]):
1443 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1446 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1449 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1452 writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1454 def writeTypeUtil (api, filename):
1455 # Structs filled by API queries are not often used in test code
1456 QUERY_RESULT_TYPES = set([
1457 "VkPhysicalDeviceFeatures",
1458 "VkPhysicalDeviceLimits",
1459 "VkFormatProperties",
1460 "VkImageFormatProperties",
1461 "VkPhysicalDeviceSparseProperties",
1462 "VkQueueFamilyProperties",
1465 "StdVideoH264SpsVuiFlags",
1466 "StdVideoH264SpsFlags",
1467 "StdVideoH264PpsFlags",
1468 "StdVideoDecodeH264PictureInfoFlags",
1469 "StdVideoDecodeH264ReferenceInfoFlags",
1470 "StdVideoDecodeH264MvcElementFlags",
1471 "StdVideoEncodeH264SliceHeaderFlags",
1472 "StdVideoEncodeH264PictureInfoFlags",
1473 "StdVideoEncodeH264RefMgmtFlags",
1474 "StdVideoH265HrdFlags",
1475 "StdVideoH265VpsFlags",
1476 "StdVideoH265SpsVuiFlags",
1477 "StdVideoH265SpsFlags",
1478 "StdVideoH265PpsFlags",
1479 "StdVideoDecodeH265PictureInfoFlags",
1480 "StdVideoDecodeH265ReferenceInfoFlags",
1481 "StdVideoEncodeH265PictureInfoFlags"
1483 COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias])
1485 def isSimpleStruct (type):
1486 def hasArrayMember (type):
1487 for member in type.members:
1488 if member.arraySize != '':
1492 def hasCompositeMember (type):
1493 for member in type.members:
1494 if member.getType() in COMPOSITE_TYPES:
1498 return type.typeClass == CompositeType.CLASS_STRUCT and \
1499 type.members[0].getType() != "VkStructureType" and \
1500 not type.name in QUERY_RESULT_TYPES and \
1501 not hasArrayMember(type) and \
1502 not hasCompositeMember(type)
1505 for type in api.compositeTypes:
1506 if not isSimpleStruct(type) or type.isAlias:
1509 name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
1512 yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
1514 yield "\t%s res;" % type.name
1515 for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1517 yield "\treturn res;"
1520 writeInlFile(filename, INL_HEADER, gen())
1522 def writeDriverIds(filename):
1524 driverIdsString = []
1525 driverIdsString.append("static const struct\n"
1527 "\tstd::string driver;\n"
1529 "} driverIds [] =\n"
1532 vulkanCore = readFile(os.path.join(VULKAN_H_DIR, "vulkan_core.h"))
1534 items = re.search(r'(?:typedef\s+enum\s+VkDriverId\s*{)((.*\n)*)(?:}\s*VkDriverId\s*;)', vulkanCore).group(1).split(',')
1535 driverItems = dict()
1538 splitted = item.split('=')
1539 key = splitted[0].strip()
1540 value_str = splitted[1].strip()
1541 try: # is this previously defined value?
1542 value = driverItems[value_str]
1547 value_str = "\t// " + value_str
1548 driverItems[key] = value
1549 if not item == items[-1]:
1550 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}," + value_str)
1552 driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}" + value_str)
1553 driverItems[key] = value
1555 driverIdsString.append("};")
1557 writeInlFile(filename, INL_HEADER, driverIdsString)
1560 def writeSupportedExtenions(api, filename):
1562 def writeExtensionsForVersions(map):
1565 result.append(" if (coreVersion >= " + str(version) + ")")
1567 for extension in map[version]:
1568 result.append(' dst.push_back("' + extension.name + '");')
1577 for ext in api.extensions:
1578 if ext.versionInCore != None:
1579 if ext.versionInCore[0] == 'INSTANCE':
1580 list = instanceMap.get(Version(ext.versionInCore[1:]))
1581 instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1583 list = deviceMap.get(Version(ext.versionInCore[1:]))
1584 deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1585 versionSet.add(Version(ext.versionInCore[1:]))
1587 lines = addVersionDefines(versionSet) + [
1589 "void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""),
1590 "{"] + writeExtensionsForVersions(deviceMap) + [
1593 "void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""),
1594 "{"] + writeExtensionsForVersions(instanceMap) + [
1596 ""] + removeVersionDefines(versionSet)
1597 writeInlFile(filename, INL_HEADER, lines)
1599 def writeExtensionFunctions (api, filename):
1601 def isInstanceExtension (ext):
1602 if ext.name and ext.functions:
1603 if ext.functions[0].getType() == Function.TYPE_INSTANCE:
1608 def isDeviceExtension (ext):
1609 if ext.name and ext.functions:
1610 if ext.functions[0].getType() == Function.TYPE_DEVICE:
1615 def writeExtensionNameArrays ():
1616 instanceExtensionNames = []
1617 deviceExtensionNames = []
1618 for ext in api.extensions:
1619 if ext.name and isInstanceExtension(ext):
1620 instanceExtensionNames += [ext.name]
1621 elif ext.name and isDeviceExtension(ext):
1622 deviceExtensionNames += [ext.name]
1623 yield '::std::string instanceExtensionNames[] =\n{'
1624 for instanceExtName in instanceExtensionNames:
1625 if (instanceExtName == instanceExtensionNames[len(instanceExtensionNames) - 1]):
1626 yield '\t"%s"' % instanceExtName
1628 yield '\t"%s",' % instanceExtName
1630 yield '::std::string deviceExtensionNames[] =\n{'
1631 for deviceExtName in deviceExtensionNames:
1632 if (deviceExtName == deviceExtensionNames[len(deviceExtensionNames) - 1]):
1633 yield '\t"%s"' % deviceExtName
1635 yield '\t"%s",' % deviceExtName
1638 def writeExtensionFunctions (functionType):
1640 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
1641 if functionType == Function.TYPE_INSTANCE:
1642 yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1643 dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
1644 elif functionType == Function.TYPE_DEVICE:
1645 yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1646 dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
1647 for ext in api.extensions:
1650 for func in ext.functions:
1651 if func.getType() == functionType:
1652 # only add functions with same vendor as extension
1653 # this is a workaroudn for entrypoints requiring more
1654 # than one excetions and lack of the dependency in vulkan_core.h
1655 vendor = ext.name.split('_')[1]
1656 if func.name.endswith(vendor):
1657 funcNames.append(func.name)
1659 yield '\tif (extName == "%s")' % ext.name
1661 for funcName in funcNames:
1662 if funcName in dg_list:
1663 yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
1665 yield '\t\tfunctions.push_back("%s");' % funcName
1666 if ext.name == "VK_KHR_device_group":
1667 for dg_func in dg_list:
1668 yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
1671 isFirstWrite = False
1672 if not isFirstWrite:
1673 yield '\tDE_FATAL("Extension name not found");'
1677 for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
1680 for line in writeExtensionFunctions(Function.TYPE_DEVICE):
1683 for line in writeExtensionNameArrays():
1686 writeInlFile(filename, INL_HEADER, lines)
1688 def writeCoreFunctionalities(api, filename):
1689 functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1690 lines = addVersionDefines(api.versions) + [
1692 'enum FunctionOrigin', '{'] + [line for line in indentLines([
1693 '\t' + functionOriginValues[0] + '\t= 0,',
1694 '\t' + functionOriginValues[1] + ',',
1695 '\t' + functionOriginValues[2]])] + [
1698 "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1699 "typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1700 "typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;",
1702 "void initApisMap (ApisMap& apis)",
1704 " apis.clear();"] + [
1705 " apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + str(v) + ", FunctionInfosList()));" for v in api.versions] + [
1709 for index, v in enumerate(api.versions):
1711 apiVersions.append("VK_VERSION_{0}_{1}".format(v.major, v.minor))
1712 # iterate over all functions that are core in latest vulkan version
1713 # note that first item in api.extension array are actually all definitions that are in vulkan.h.in before section with extensions
1714 for fun in api.extensions[0].functions:
1715 if fun.apiVersion in apiVersions:
1716 funcs.append(' apis[' + str(v) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));')
1717 lines = lines + [line for line in indentLines(funcs)] + [""]
1719 lines = lines + ["}", ""] + removeVersionDefines(api.versions)
1720 writeInlFile(filename, INL_HEADER, lines)
1722 def writeDeviceFeatures2(api, filename):
1723 # list of structures that should be tested with getPhysicalDeviceFeatures2
1724 # this is not posible to determine from vulkan_core.h, if new feature structures
1725 # are added they should be manualy added to this list
1726 testedStructures = [
1727 'VkPhysicalDeviceConditionalRenderingFeaturesEXT',
1728 'VkPhysicalDeviceScalarBlockLayoutFeatures',
1729 'VkPhysicalDevicePerformanceQueryFeaturesKHR',
1730 'VkPhysicalDevice16BitStorageFeatures',
1731 'VkPhysicalDeviceMultiviewFeatures',
1732 'VkPhysicalDeviceProtectedMemoryFeatures',
1733 'VkPhysicalDeviceSamplerYcbcrConversionFeatures',
1734 'VkPhysicalDeviceVariablePointersFeatures',
1735 'VkPhysicalDevice8BitStorageFeatures',
1736 'VkPhysicalDeviceShaderAtomicInt64Features',
1737 'VkPhysicalDeviceShaderFloat16Int8Features',
1738 'VkPhysicalDeviceBufferDeviceAddressFeaturesEXT',
1739 'VkPhysicalDeviceBufferDeviceAddressFeatures',
1740 'VkPhysicalDeviceDescriptorIndexingFeatures',
1741 'VkPhysicalDeviceTimelineSemaphoreFeatures',
1742 'VkPhysicalDeviceFragmentDensityMapFeaturesEXT',
1743 'VkPhysicalDeviceFragmentDensityMap2FeaturesEXT'
1745 # helper class used to encapsulate all data needed during generation
1746 class StructureDetail:
1747 def __init__ (self, name):
1748 nameResult = re.search('(.*)Features(.*)', name[len('VkPhysicalDevice'):])
1750 # generate structure type name from structure name
1751 # note that sometimes digits are separated with '_':
1752 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT
1753 # but mostly they are not:
1754 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES
1755 if (nameResult.group(1) == 'FragmentDensityMap2'):
1756 nameSplitUp = ['FRAGMENT', 'DENSITY', 'MAP', '2', 'FEATURES']
1758 nameSplit = re.findall(r'[1-9A-Z]+(?:[a-z1-9]+|[A-Z]*(?=[A-Z]|$))', nameResult.group(1))
1759 nameSplitUp = map(str.upper, nameSplit)
1760 nameSplitUp = list(nameSplitUp) + ['FEATURES']
1761 # check if there is extension suffix
1762 if (len(nameResult.group(2)) != 0):
1763 nameSplitUp.append(nameResult.group(2))
1765 self.sType = 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_' + '_'.join(nameSplitUp)
1766 self.instanceName = 'd' + name[11:]
1767 self.flagName = 'is' + name[16:]
1768 self.extension = None
1772 # helper extension class used in algorith below
1773 class StructureFoundContinueToNextOne(Exception):
1775 testedStructureDetail = [StructureDetail(struct) for struct in testedStructures]
1776 # iterate over all searched structures and find extensions that enable them
1777 for structureDetail in testedStructureDetail:
1779 # iterate over all extensions
1780 for extension in api.extensions[1:]:
1781 # check composite types and typedefs in case extension is part of core
1782 for structureList in [extension.compositeTypes, extension.typedefs]:
1783 # iterate over all structures added by extension
1784 for extensionStructure in structureList:
1785 # compare checked structure name to name of structure from extension
1786 if structureDetail.name == extensionStructure.name:
1787 structureDetail.extension = extension.name
1788 if extension.versionInCore is not None:
1789 structureDetail.major = extension.versionInCore[1]
1790 structureDetail.minor = extension.versionInCore[2]
1791 raise StructureFoundContinueToNextOne
1792 except StructureFoundContinueToNextOne:
1794 for structureDetail in testedStructureDetail:
1795 for compositeType in api.compositeTypes:
1796 if structureDetail.name != compositeType.name:
1798 structureMembers = compositeType.members[2:]
1799 structureDetail.members = [m.name for m in structureMembers]
1800 if structureDetail.major is not None:
1802 # if structure was not added with extension then check if
1803 # it was added directly with one of vulkan versions
1804 apiVersion = compositeType.apiVersion
1805 if apiVersion is None:
1807 structureDetail.major = apiVersion.major
1808 structureDetail.minor = apiVersion.minor
1810 # generate file content
1811 structureDefinitions = []
1812 featureEnabledFlags = []
1813 clearStructures = []
1816 verifyStructures = []
1817 for index, structureDetail in enumerate(testedStructureDetail):
1818 # create two instances of each structure
1819 nameSpacing = '\t' * int((55 - len(structureDetail.name)) / 4)
1820 structureDefinitions.append(structureDetail.name + nameSpacing + structureDetail.instanceName + '[count];')
1821 # create flags that check if proper extension or vulkan version is available
1823 extension = structureDetail.extension
1824 major = structureDetail.major
1825 if extension is not None:
1826 condition = ' checkExtension(properties, "' + extension + '")'
1827 if major is not None:
1829 condition += '\t' * int((39 - len(extension)) / 4) + '|| '
1831 condition += '\t' * 17 + ' '
1832 condition += 'context.contextSupports(vk::ApiVersion(' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
1834 nameSpacing = '\t' * int((40 - len(structureDetail.flagName)) / 4)
1835 featureEnabledFlags.append('const bool ' + structureDetail.flagName + nameSpacing + '=' + condition)
1836 # clear memory of each structure
1837 nameSpacing = '\t' * int((43 - len(structureDetail.instanceName)) / 4)
1838 clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx],' + nameSpacing + '0xFF * ndx, sizeof(' + structureDetail.name + '));')
1839 # construct structure chain
1840 nextInstanceName = 'DE_NULL';
1841 if index < len(testedStructureDetail)-1:
1842 nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
1843 structureChain.append('\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.sType + ';')
1844 structureChain.append('\t' + structureDetail.instanceName + '[ndx].pNext = ' + nextInstanceName + ';\n')
1845 # construct log section
1846 logStructures.append('if (' + structureDetail.flagName + ')')
1847 logStructures.append('\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;')
1848 #construct verification section
1849 verifyStructures.append('if (' + structureDetail.flagName + ' &&')
1850 for index, m in enumerate(structureDetail.members):
1851 prefix = '\t(' if index == 0 else '\t '
1852 postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
1853 verifyStructures.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
1854 verifyStructures.append('{\n\t\tTCU_FAIL("Mismatch between ' + structureDetail.name + '");\n}')
1855 # construct file content
1857 stream.extend(structureDefinitions)
1859 stream.extend(featureEnabledFlags)
1860 stream.append('\nfor (int ndx = 0; ndx < count; ++ndx)\n{')
1861 stream.extend(clearStructures)
1863 stream.extend(structureChain)
1864 stream.append('\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
1865 '\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
1866 '\textFeatures.pNext = &' + testedStructureDetail[0].instanceName + '[ndx];\n'
1867 '\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);\n}\n')
1868 stream.extend(logStructures)
1870 stream.extend(verifyStructures)
1871 writeInlFile(filename, INL_HEADER, stream)
1873 def generateDeviceFeaturesDefs(src):
1874 # look for definitions
1875 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_FEATURES(\w*)\s*='
1876 matches = re.findall(ptrnSType, src, re.M)
1877 matches = sorted(matches, key=lambda m: m[0])
1878 # construct final list
1880 for sType, sSuffix in matches:
1881 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1882 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Features' + sSuffix.replace('_', '') + ')'
1883 matchStructName = re.search(ptrnStructName, src, re.IGNORECASE)
1885 # handle special cases
1886 if sType == "EXCLUSIVE_SCISSOR":
1887 sType = "SCISSOR_EXCLUSIVE"
1888 elif sType == "ASTC_DECODE":
1889 sType = "ASTC_DECODE_MODE"
1890 if sType in {'VULKAN_1_1', 'VULKAN_1_2'}:
1892 # end handling special cases
1893 ptrnExtensionName = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_EXTENSION_NAME).+$'
1894 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1895 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_SPEC_VERSION).+$'
1896 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1897 defs.append( (sType, '', sSuffix, matchStructName.group(1), \
1898 matchExtensionName.group(0) if matchExtensionName else None,
1899 matchExtensionName.group(1) if matchExtensionName else None,
1900 matchSpecVersion.group(1) if matchSpecVersion else '0') )
1903 def generateDevicePropertiesDefs(src):
1904 # look for definitions
1905 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
1906 matches = re.findall(ptrnSType, src, re.M)
1907 matches = sorted(matches, key=lambda m: m[0])
1908 # construct final list
1910 for sType, sSuffix in matches:
1911 # handle special cases
1912 if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
1914 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
1915 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
1917 sExtSuffix = sSuffix
1918 suffixStart = sSuffix.rfind('_')
1920 sVerSuffix = sSuffix[:suffixStart]
1921 sExtSuffix = sSuffix[suffixStart:]
1922 # handle special case
1926 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1927 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
1928 matchStructName = re.search(ptrnStructName, src, re.M)
1931 if extType == "MAINTENANCE_3":
1932 extType = "MAINTENANCE3"
1933 elif extType == "DISCARD_RECTANGLE":
1934 extType = "DISCARD_RECTANGLES"
1935 elif extType == "DRIVER":
1936 extType = "DRIVER_PROPERTIES"
1937 elif extType == "POINT_CLIPPING":
1938 extType = "MAINTENANCE2"
1939 elif extType == "SHADER_CORE":
1940 extType = "SHADER_CORE_PROPERTIES"
1941 elif extType == "DRM":
1942 extType = "PHYSICAL_DEVICE_DRM"
1943 # end handling special cases
1944 ptrnExtensionName = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
1945 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
1946 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
1947 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
1948 defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
1949 matchExtensionName.group(0) if matchExtensionName else None,
1950 matchExtensionName.group(1) if matchExtensionName else None,
1951 matchSpecVersion.group (1) if matchSpecVersion else '0') )
1954 def writeDeviceFeatures(api, dfDefs, filename):
1955 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
1956 # and construct dictionary with all of their attributes
1959 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
1960 for structureType in api.compositeTypes:
1961 match = blobPattern.match(structureType.name)
1963 allMembers = [member.name for member in structureType.members]
1964 vkVersion = match.group(1)
1965 blobMembers[vkVersion] = allMembers[2:]
1966 blobStructs[vkVersion] = set()
1967 initFromBlobDefinitions = []
1968 emptyInitDefinitions = []
1969 # iterate over all feature structures
1970 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
1971 nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
1972 for structureType in api.compositeTypes:
1973 # skip structures that are not feature structures
1974 if not allFeaturesPattern.match(structureType.name):
1976 # skip structures that were previously identified as blobs
1977 if blobPattern.match(structureType.name):
1979 if structureType.isAlias:
1981 # skip sType and pNext and just grab third and next attributes
1982 structureMembers = structureType.members[2:]
1983 notPartOfBlob = True
1984 if nonExtFeaturesPattern.match(structureType.name):
1985 # check if this member is part of any of the blobs
1986 for blobName, blobMemberList in blobMembers.items():
1987 # if just one member is not part of this blob go to the next blob
1988 # (we asume that all members are part of blob - no need to check all)
1989 if structureMembers[0].name not in blobMemberList:
1991 # add another feature structure name to this blob
1992 blobStructs[blobName].add(structureType)
1993 # add specialization for this feature structure
1995 for member in structureMembers:
1996 memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
1998 "template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
2001 "}}".format(structureType.name, memberCopying)
2002 initFromBlobDefinitions.append(wholeFunction)
2003 notPartOfBlob = False
2004 # assuming that all members are part of blob, goto next
2006 # add empty template definition as on Fedora there are issue with
2007 # linking using just generic template - all specializations are needed
2009 emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2010 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2011 extensionDefines = []
2012 makeFeatureDescDefinitions = []
2013 featureStructWrappers = []
2014 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dfDefs):
2015 extensionNameDefinition = extName
2016 if not extensionNameDefinition:
2017 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2018 # construct defines with names
2020 extensionDefines.append(extLine)
2022 extensionDefines.append('#define {0} "not_existent_feature"'.format(extensionNameDefinition))
2023 # handle special cases
2024 if sType == "SCISSOR_EXCLUSIVE":
2025 sType = "EXCLUSIVE_SCISSOR"
2026 elif sType == "ASTC_DECODE_MODE":
2027 sType = "ASTC_DECODE"
2028 # end handling special cases
2029 # construct makeFeatureDesc template function definitions
2030 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2031 makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2032 "{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dfDefs)-idx))
2033 # construct CreateFeatureStruct wrapper block
2034 featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2035 # construct method that will check if structure sType is part of blob
2036 blobChecker = "bool isPartOfBlobFeatures (VkStructureType sType)\n{\n" \
2037 "\tconst std::vector<VkStructureType> sTypeVect =" \
2039 # iterate over blobs with list of structures
2040 for blobName in sorted(blobStructs.keys()):
2041 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2042 # iterate over all feature structures in current blob
2043 structuresList = list(blobStructs[blobName])
2044 structuresList = sorted(structuresList, key=lambda s: s.name)
2045 for structType in structuresList:
2046 # find definition of this structure in dfDefs
2047 structName = structType.name
2048 # handle special cases
2049 if structName == 'VkPhysicalDeviceShaderDrawParameterFeatures':
2050 structName = 'VkPhysicalDeviceShaderDrawParametersFeatures'
2051 # end handling special cases
2052 structDef = [s for s in dfDefs if s[3] == structName][0]
2053 sType = structDef[0]
2054 sSuffix = structDef[1] + structDef[2]
2055 # handle special cases
2056 if sType == "SCISSOR_EXCLUSIVE":
2057 sType = "EXCLUSIVE_SCISSOR"
2058 # end handling special cases
2059 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2060 blobChecker += "\t\t{0},\n".format(sTypeName)
2061 blobChecker += "\t};\n" \
2062 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2064 # combine all definition lists
2066 '#include "vkDeviceFeatures.hpp"\n',
2068 stream.extend(extensionDefines)
2070 stream.extend(initFromBlobDefinitions)
2071 stream.append('\n// generic template is not enough for some compilers')
2072 stream.extend(emptyInitDefinitions)
2074 stream.extend(makeFeatureDescDefinitions)
2076 stream.append('static const FeatureStructCreationData featureStructCreationArray[] =\n{')
2077 stream.extend(featureStructWrappers)
2078 stream.append('};\n')
2079 stream.append(blobChecker)
2080 stream.append('} // vk\n')
2081 writeInlFile(filename, INL_HEADER, stream)
2083 def writeDeviceProperties(api, dpDefs, filename):
2084 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2085 # and construct dictionary with all of their attributes
2088 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2089 for structureType in api.compositeTypes:
2090 match = blobPattern.match(structureType.name)
2092 allMembers = [member.name for member in structureType.members]
2093 vkVersion = match.group(1)
2094 blobMembers[vkVersion] = allMembers[2:]
2095 blobStructs[vkVersion] = set()
2096 initFromBlobDefinitions = []
2097 emptyInitDefinitions = []
2098 # iterate over all property structures
2099 allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2100 nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2101 for structureType in api.compositeTypes:
2102 # skip structures that are not property structures
2103 if not allPropertiesPattern.match(structureType.name):
2105 # skip structures that were previously identified as blobs
2106 if blobPattern.match(structureType.name):
2108 if structureType.isAlias:
2110 # skip sType and pNext and just grab third and next attributes
2111 structureMembers = structureType.members[2:]
2112 notPartOfBlob = True
2113 if nonExtPropertiesPattern.match(structureType.name):
2114 # check if this member is part of any of the blobs
2115 for blobName, blobMemberList in blobMembers.items():
2116 # if just one member is not part of this blob go to the next blob
2117 # (we asume that all members are part of blob - no need to check all)
2118 if structureMembers[0].name not in blobMemberList:
2120 # add another property structure name to this blob
2121 blobStructs[blobName].add(structureType)
2122 # add specialization for this property structure
2124 for member in structureMembers:
2125 if not member.arraySize:
2126 # handle special case
2127 if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2128 blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2129 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2130 # end handling special case
2132 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2134 memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type[0], member.arraySize[1:-1])
2136 "template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2139 "}}".format(structureType.name, memberCopying)
2140 initFromBlobDefinitions.append(wholeFunction)
2141 notPartOfBlob = False
2142 # assuming that all members are part of blob, goto next
2144 # add empty template definition as on Fedora there are issue with
2145 # linking using just generic template - all specializations are needed
2147 emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2148 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2149 extensionDefines = []
2150 makePropertyDescDefinitions = []
2151 propertyStructWrappers = []
2152 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dpDefs):
2153 extensionNameDefinition = extName
2154 if not extensionNameDefinition:
2155 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2156 # construct defines with names
2158 extensionDefines.append(extLine)
2160 extensionDefines.append('#define {0} "core_property"'.format(extensionNameDefinition))
2161 # construct makePropertyDesc template function definitions
2162 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2163 makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2164 "{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dpDefs)-idx))
2165 # construct CreateProperty struct wrapper block
2166 propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2167 # construct method that will check if structure sType is part of blob
2168 blobChecker = "bool isPartOfBlobProperties (VkStructureType sType)\n{\n" \
2169 "\tconst std::vector<VkStructureType> sTypeVect =" \
2171 # iterate over blobs with list of structures
2172 for blobName in sorted(blobStructs.keys()):
2173 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2174 # iterate over all feature structures in current blob
2175 structuresList = list(blobStructs[blobName])
2176 structuresList = sorted(structuresList, key=lambda s: s.name)
2177 for structType in structuresList:
2178 # find definition of this structure in dpDefs
2179 structName = structType.name
2180 structDef = [s for s in dpDefs if s[3] == structName][0]
2181 sType = structDef[0]
2182 sSuffix = structDef[1] + structDef[2]
2183 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2184 blobChecker += "\t\t{0},\n".format(sTypeName)
2185 blobChecker += "\t};\n" \
2186 "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2188 # combine all definition lists
2190 '#include "vkDeviceProperties.hpp"\n',
2192 stream.extend(extensionDefines)
2194 stream.extend(initFromBlobDefinitions)
2195 stream.append('\n// generic template is not enough for some compilers')
2196 stream.extend(emptyInitDefinitions)
2198 stream.extend(makePropertyDescDefinitions)
2200 stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2201 stream.extend(propertyStructWrappers)
2202 stream.append('};\n')
2203 stream.append(blobChecker)
2204 stream.append('} // vk\n')
2205 writeInlFile(filename, INL_HEADER, stream)
2207 def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
2209 for _, _, _, extStruct, _, _, _ in dfDefs:
2210 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2211 stream.append(pattern.format(extStruct, nameSubStr))
2212 writeInlFile(filename, INL_HEADER, indentLines(stream))
2214 def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
2215 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
2216 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2218 def writeDeviceFeaturesContextDecl(dfDefs, filename):
2219 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2220 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2222 def writeDeviceFeaturesContextDefs(dfDefs, filename):
2223 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2224 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2226 def genericDevicePropertiesWriter(dfDefs, pattern, filename):
2228 for _, _, _, extStruct, _, _, _ in dfDefs:
2229 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2230 if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
2232 stream.append(pattern.format(extStruct, nameSubStr))
2233 writeInlFile(filename, INL_HEADER, indentLines(stream))
2235 def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
2236 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
2237 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2239 def writeDevicePropertiesContextDecl(dfDefs, filename):
2240 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2241 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2243 def writeDevicePropertiesContextDefs(dfDefs, filename):
2244 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2245 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2247 def splitWithQuotation(line):
2249 splitted = re.findall(r'[^"\s]\S*|".+?"', line)
2251 result.append(s.replace('"', ''))
2254 def writeMandatoryFeatures(filename):
2256 pattern = r'\s*([\w]+)\s+FEATURES\s+\((.*)\)\s+REQUIREMENTS\s+\((.*)\)'
2257 mandatoryFeatures = readFile(os.path.join(VULKAN_H_DIR, "mandatory_features.txt"))
2258 matches = re.findall(pattern, mandatoryFeatures)
2262 allRequirements = splitWithQuotation(m[2])
2263 dictData.append( [ m[0], m[1].strip(), allRequirements ] )
2264 if m[0] != 'VkPhysicalDeviceFeatures' :
2265 if (m[0] not in dictStructs):
2266 dictStructs[m[0]] = [m[0][2:3].lower() + m[0][3:]]
2267 if (allRequirements[0]):
2268 if (allRequirements[0] not in dictStructs[m[0]][1:]):
2269 dictStructs[m[0]].append(allRequirements[0])
2271 stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
2272 '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
2273 '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
2275 '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
2276 '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
2277 '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
2279 '\ttcu::TestLog& log = context.getTestContext().getLog();',
2280 '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
2281 '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
2282 '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
2283 '\tvoid** nextPtr = &coreFeatures.pNext;',
2286 listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
2287 for k, v in listStruct:
2288 if (v[1].startswith("ApiVersion")):
2289 cond = '\tif (context.contextSupports(vk::' + v[1] + '))'
2291 cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[1] + '"))'
2292 stream.extend(['\tvk::' + k + ' ' + v[0]+ ';',
2293 '\tdeMemset(&' + v[0] + ', 0, sizeof(' + v[0] + '));',
2298 for i, req in enumerate(reqs) :
2299 if (req.startswith("ApiVersion")):
2300 cond = cond + 'context.contextSupports(vk::' + req + ')'
2302 cond = cond + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2303 if i+1 < len(reqs) :
2304 cond = cond + ' || '
2306 stream.append('\t' + cond)
2307 stream.extend(['\t{',
2308 '\t\t' + v[0] + '.sType = getStructureType<' + k + '>();',
2309 '\t\t*nextPtr = &' + v[0] + ';',
2310 '\t\tnextPtr = &' + v[0] + '.pNext;',
2313 stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
2314 '\tbool result = true;',
2319 structName = 'coreFeatures.features';
2320 if v[0] != 'VkPhysicalDeviceFeatures' :
2321 structName = dictStructs[v[0]][0]
2324 for i, req in enumerate(v[2]) :
2325 if (req.startswith("ApiVersion")):
2326 condition = condition + 'context.contextSupports(vk::' + req + ')'
2328 condition = condition + req
2330 condition = condition + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2331 if i+1 < len(v[2]) :
2332 condition = condition + ' && '
2333 condition = condition + ' )'
2334 stream.append('\t' + condition)
2335 stream.append('\t{')
2336 # Don't need to support an AND case since that would just be another line in the .txt
2337 if len(v[1].split(" ")) == 1:
2338 stream.append('\t\tif ( ' + structName + '.' + v[1] + ' == VK_FALSE )')
2341 for i, feature in enumerate(v[1].split(" ")):
2343 condition = condition + ' && '
2344 condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
2345 condition = condition + ' )'
2346 stream.append('\t\t' + condition)
2347 featureSet = v[1].replace(" ", " or ")
2348 stream.extend(['\t\t{',
2349 '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
2350 '\t\t\tresult = false;',
2354 stream.append('\treturn result;')
2355 stream.append('}\n')
2356 writeInlFile(filename, INL_HEADER, stream)
2358 def writeExtensionList(filename, patternPart):
2360 stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(patternPart.title()))
2361 extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
2362 pattern = r'\s*([^\s]+)\s+{0}\s*[0-9_]*'.format(patternPart)
2363 matches = re.findall(pattern, extensionsData)
2365 stream.append('\t"' + m + '",')
2366 stream.append('};\n')
2367 writeInlFile(filename, INL_HEADER, stream)
2369 def preprocessTopInclude(src, dir):
2370 pattern = r'#include\s+"([^\n]+)"'
2372 inc = re.search(pattern, src)
2375 incFileName = inc.string[inc.start(1):inc.end(1)]
2376 patternIncNamed = r'#include\s+"' + incFileName + '"'
2377 incBody = readFile(os.path.join(dir, incFileName)) if incFileName != 'vulkan/vk_platform.h' else ''
2378 incBodySanitized = re.sub(pattern, '', incBody)
2379 bodyEndSanitized = re.sub(patternIncNamed, '', src[inc.end(0):])
2380 src = src[0:inc.start(0)] + incBodySanitized + bodyEndSanitized
2383 if __name__ == "__main__":
2384 # Read all .h files, with vulkan_core.h first
2385 files = os.listdir(VULKAN_H_DIR)
2386 files = [f for f in files if f.endswith(".h")]
2388 files.remove("vulkan_core.h")
2389 first = ["vk_video/vulkan_video_codecs_common.h", "vulkan_core.h"]
2390 files = first + files
2394 src += preprocessTopInclude(readFile(os.path.join(VULKAN_H_DIR,file)), VULKAN_H_DIR)
2396 src = re.sub('\s*//[^\n]*', '', src)
2397 src = re.sub('\n\n', '\n', src)
2401 platformFuncs = [Function.TYPE_PLATFORM]
2402 instanceFuncs = [Function.TYPE_INSTANCE]
2403 deviceFuncs = [Function.TYPE_DEVICE]
2405 dfd = generateDeviceFeaturesDefs(src)
2406 writeDeviceFeatures (api, dfd, os.path.join(VULKAN_DIR, "vkDeviceFeatures.inl"))
2407 writeDeviceFeaturesDefaultDeviceDefs (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
2408 writeDeviceFeaturesContextDecl (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDecl.inl"))
2409 writeDeviceFeaturesContextDefs (dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDefs.inl"))
2411 dpd = generateDevicePropertiesDefs(src)
2412 writeDeviceProperties (api, dpd, os.path.join(VULKAN_DIR, "vkDeviceProperties.inl"))
2414 writeDevicePropertiesDefaultDeviceDefs (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
2415 writeDevicePropertiesContextDecl (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDecl.inl"))
2416 writeDevicePropertiesContextDefs (dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDefs.inl"))
2418 writeHandleType (api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
2419 writeBasicTypes (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
2420 writeCompositeTypes (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
2421 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"), platformFuncs, False)
2422 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"), instanceFuncs, False)
2423 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"), deviceFuncs, False)
2424 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"), platformFuncs, True)
2425 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"), instanceFuncs, True)
2426 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"), deviceFuncs, True)
2427 writeFunctionPtrTypes (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
2428 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"), platformFuncs)
2429 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"), instanceFuncs)
2430 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"), deviceFuncs)
2431 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr")
2432 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"), instanceFuncs)
2433 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"), deviceFuncs)
2434 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver")
2435 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver")
2436 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver")
2437 writeStrUtilProto (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
2438 writeStrUtilImpl (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
2439 writeRefUtilProto (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
2440 writeRefUtilImpl (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
2441 writeStructTraitsImpl (api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl"))
2442 writeNullDriverImpl (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
2443 writeTypeUtil (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
2444 writeSupportedExtenions (api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl"))
2445 writeCoreFunctionalities (api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl"))
2446 writeExtensionFunctions (api, os.path.join(VULKAN_DIR, "vkExtensionFunctions.inl"))
2447 writeDeviceFeatures2 (api, os.path.join(VULKAN_DIR, "vkDeviceFeatures2.inl"))
2448 writeMandatoryFeatures ( os.path.join(VULKAN_DIR, "vkMandatoryFeatures.inl"))
2449 writeExtensionList ( os.path.join(VULKAN_DIR, "vkInstanceExtensions.inl"), 'INSTANCE')
2450 writeExtensionList ( os.path.join(VULKAN_DIR, "vkDeviceExtensions.inl"), 'DEVICE')
2451 writeDriverIds ( os.path.join(VULKAN_DIR, "vkKnownDriverIds.inl"))
2452 writeObjTypeImpl (api, os.path.join(VULKAN_DIR, "vkObjTypeImpl.inl"))