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