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