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