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