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 glob 27import json 28import argparse 29import datetime 30import collections 31import ast 32import logging 33from lxml import etree 34 35scriptPath = os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts") 36sys.path.insert(0, scriptPath) 37 38from ctsbuild.common import * 39from khr_util.format import indentLines, writeInlFile 40 41sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "scripts")) 42 43from reg import stripNonmatchingAPIs 44 45VULKAN_XML_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "xml") 46SCRIPTS_SRC_DIR = os.path.join(os.path.dirname(__file__), "src") 47DEFAULT_OUTPUT_DIR = { "" : os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkan"), 48 "SC" : os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkansc") } 49 50INL_HEADER = """\ 51/* WARNING: This is auto-generated file. Do not modify, since changes will 52 * be lost! Modify the generating script instead. 53 * This file was generated by /scripts/gen_framework.py 54 */\ 55 56""" 57 58DEFINITIONS = { 59 "VK_MAX_PHYSICAL_DEVICE_NAME_SIZE": "size_t", 60 "VK_MAX_EXTENSION_NAME_SIZE": "size_t", 61 "VK_MAX_DRIVER_NAME_SIZE": "size_t", 62 "VK_MAX_DRIVER_INFO_SIZE": "size_t", 63 "VK_UUID_SIZE": "size_t", 64 "VK_LUID_SIZE": "size_t", 65 "VK_MAX_MEMORY_TYPES": "size_t", 66 "VK_MAX_MEMORY_HEAPS": "size_t", 67 "VK_MAX_DESCRIPTION_SIZE": "size_t", 68 "VK_MAX_DEVICE_GROUP_SIZE": "size_t", 69 "VK_ATTACHMENT_UNUSED": "uint32_t", 70 "VK_SUBPASS_EXTERNAL": "uint32_t", 71 "VK_QUEUE_FAMILY_IGNORED": "uint32_t", 72 "VK_QUEUE_FAMILY_EXTERNAL": "uint32_t", 73 "VK_REMAINING_MIP_LEVELS": "uint32_t", 74 "VK_REMAINING_ARRAY_LAYERS": "uint32_t", 75 "VK_WHOLE_SIZE": "vk::VkDeviceSize", 76 "VK_TRUE": "vk::VkBool32", 77 "VK_FALSE": "vk::VkBool32", 78} 79 80PLATFORM_TYPES = [ 81 # VK_KHR_xlib_surface 82 (["Display","*"], ["XlibDisplayPtr"], "void*"), 83 (["Window"], ["XlibWindow"], "uintptr_t",), 84 (["VisualID"], ["XlibVisualID"], "uint32_t"), 85 86 # VK_KHR_xcb_surface 87 (["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"), 88 (["xcb_window_t"], ["XcbWindow"], "uintptr_t"), 89 (["xcb_visualid_t"], ["XcbVisualid"], "uint32_t"), 90 91 # VK_KHR_wayland_surface 92 (["struct", "wl_display","*"], ["WaylandDisplayPtr"], "void*"), 93 (["struct", "wl_surface", "*"], ["WaylandSurfacePtr"], "void*"), 94 95 # VK_KHR_mir_surface 96 (["MirConnection", "*"], ["MirConnectionPtr"], "void*"), 97 (["MirSurface", "*"], ["MirSurfacePtr"], "void*"), 98 99 # VK_KHR_android_surface 100 (["ANativeWindow", "*"], ["AndroidNativeWindowPtr"], "void*"), 101 102 # VK_KHR_win32_surface 103 (["HINSTANCE"], ["Win32InstanceHandle"], "void*"), 104 (["HWND"], ["Win32WindowHandle"], "void*"), 105 (["HANDLE"], ["Win32Handle"], "void*"), 106 (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"), 107 (["AHardwareBuffer", "*"], ["AndroidHardwareBufferPtr"], "void*"), 108 (["HMONITOR"], ["Win32MonitorHandle"], "void*"), 109 (["LPCWSTR"], ["Win32LPCWSTR"], "const void*"), 110 111 # VK_EXT_acquire_xlib_display 112 (["RROutput"], ["RROutput"], "void*"), 113 114 (["zx_handle_t"], ["zx_handle_t"], "uint32_t"), 115 (["GgpFrameToken"], ["GgpFrameToken"], "int32_t"), 116 (["GgpStreamDescriptor"], ["GgpStreamDescriptor"], "int32_t"), 117 (["CAMetalLayer"], ["CAMetalLayer"], "void*"), 118 (["struct", "_screen_context", "*"], ["QNXScreenContextPtr"], "void*"), 119 (["struct", "_screen_window", "*"], ["QNXScreenWindowPtr"], "void*"), 120 121 # VK_EXT_metal_objects 122 (["MTLDevice_id"], ["MTLDevice_id"], "void*"), 123 (["MTLCommandQueue_id"], ["MTLCommandQueue_id"], "void*"), 124 (["MTLBuffer_id"], ["MTLBuffer_id"], "void*"), 125 (["MTLTexture_id"], ["MTLTexture_id"], "void*"), 126 (["IOSurfaceRef"], ["IOSurfaceRef"], "void*"), 127 (["MTLSharedEvent_id"], ["MTLSharedEvent_id"], "void*"), 128 129 # VK_NV_external_sci_sync 130 (["NvSciBufObj"], ["NvSciBufObj"], "int"), 131 (["NvSciSyncObj"], ["NvSciSyncObj"], "int"), 132 (["NvSciSyncFence"], ["NvSciSyncFence"], "int"), 133 (["NvSciBufAttrList"], ["NvSciBufAttrList"], "int"), 134 (["NvSciSyncAttrList"], ["NvSciSyncAttrList"], "int"), 135] 136 137PLATFORM_TYPE_NAMESPACE = "pt" 138 139TYPE_SUBSTITUTIONS = [ 140 # Platform-specific 141 ("DWORD", "uint32_t"), 142 ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"), 143] 144 145EXTENSION_POSTFIXES_STANDARD = ["KHR", "EXT"] 146EXTENSION_POSTFIXES_VENDOR = ["AMD", "ARM", "NV", 'INTEL', "NVX", "KHX", "NN", "MVK", "FUCHSIA", 'QCOM', "GGP", "QNX", "ANDROID", 'VALVE', 'HUAWEI'] 147EXTENSION_POSTFIXES = EXTENSION_POSTFIXES_STANDARD + EXTENSION_POSTFIXES_VENDOR 148 149# Converts the dependecies expression into an Abstract Syntax Tree that uses boolean operators 150def parseDependsEpression(string): 151 try: 152 # Parse the input string into an abstract syntax tree (AST) 153 tree = ast.parse(string.replace('+', ' and ').replace(',', ' or '), mode='eval') 154 expression = tree.body 155 return expression 156 except SyntaxError as e: 157 print(f"Syntax error in the input string: {e}") 158 return None 159 160# Checks the dependencies AST against the passed extensions 161def checkDependencyAST(node, extensions): 162 if isinstance(node, ast.BoolOp): 163 assert(len(node.values) >= 2) 164 value = checkDependencyAST(node.values.pop(), extensions) 165 while node.values: 166 nextValue = checkDependencyAST(node.values.pop(), extensions) 167 if isinstance(node.op, ast.And): 168 value = value and nextValue 169 if isinstance(node.op, ast.Or): 170 value = value or nextValue 171 return value 172 elif isinstance(node, ast.Name): 173 if '_VERSION_' in node.id: 174 return True 175 for ext in extensions: 176 if node.id == ext.name: 177 return True 178 return False 179 elif isinstance(node, ast.Constant): 180 return node.value 181 182# helper function that check if dependency is in list of extension 183def isDependencyMet(dependsExpression, extensionList): 184 if dependsExpression is None: 185 return True 186 tree = parseDependsEpression(dependsExpression) 187 # check if requirement dependencies are meet; if not then struct/function is not used 188 ret = checkDependencyAST(tree, extensionList) 189 return ret 190 191def substituteType(object): # both CompositeMember and FunctionArgument can be passed to this function 192 for src, dst in TYPE_SUBSTITUTIONS: 193 object.type = object.type.replace(src, dst) 194 for platformType, substitute, _ in PLATFORM_TYPES: 195 platformTypeName = platformType[0] 196 platformTypeName = platformType[-2] if "*" in platformType else platformType[0] 197 if object.type == platformTypeName: 198 object.type = PLATFORM_TYPE_NAMESPACE + '::' + substitute[0] 199 object.qualifiers = None if 'struct' in platformType else object.qualifiers 200 object.qualifiers = None if 'const' in platformType else object.qualifiers 201 if "*" in platformType: 202 object.pointer = "*" if object.pointer == "**" else None 203 204class Define: 205 def __init__ (self, name, aType, alias, value): 206 self.name = name 207 self.type = aType 208 self.alias = alias 209 self.value = value 210 211class Handle: 212 def __init__ (self, name, aType, alias, parent, objtypeenum): 213 self.name = name 214 self.type = aType 215 self.alias = alias 216 self.parent = parent 217 self.objtypeenum = objtypeenum 218 219class Bitmask: 220 def __init__ (self, name, aType, requires, bitvalues): 221 self.name = name 222 self.type = aType 223 self.alias = None # initialy None but may be filled while parsing next tag 224 self.requires = requires 225 self.bitvalues = bitvalues 226 227class Enumerator: 228 def __init__ (self, name, value, bitpos): 229 self.name = name 230 self.aliasList = [] # list of strings 231 self.value = value # some enums specify value and some bitpos 232 self.bitpos = bitpos 233 self.extension = None # name of extension that added this enumerator 234 235class Enum: 236 def __init__ (self, name): 237 self.name = name 238 self.alias = None # name of enum alias or None 239 self.type = None # enum or bitmask 240 self.bitwidth = "32" 241 self.enumeratorList = [] # list of Enumerator objects 242 243 def areValuesLinear (self): 244 if self.type == 'bitmask': 245 return False 246 curIndex = 0 247 for enumerator in self.enumeratorList: 248 intValue = parseInt(enumerator.value) 249 if intValue != curIndex: 250 return False 251 curIndex += 1 252 return True 253 254class CompositeMember: 255 def __init__ (self, name, aType, pointer, qualifiers, arraySizeList, optional, limittype, values, fieldWidth): 256 self.name = name 257 self.type = aType # member type 258 self.pointer = pointer # None, '*' or '**' 259 self.qualifiers = qualifiers # 'const' or 'struct' or None 260 self.arraySizeList = arraySizeList # can contain digits or enums 261 self.optional = optional 262 self.limittype = limittype 263 self.values = values # allowed member values 264 self.fieldWidth = fieldWidth # ':' followed by number of bits 265 266 # check if type should be swaped 267 substituteType(self) 268 269class Composite: 270 def __init__ (self, name, category, allowduplicate, structextends, returnedonly, members): 271 self.name = name 272 self.category = category # is it struct or union 273 self.aliasList = [] # most composite types have single alias but there are cases like VkPhysicalDeviceVariablePointersFeatures that have 3 274 self.allowduplicate = allowduplicate 275 self.structextends = structextends 276 self.returnedonly = returnedonly 277 self.members = members # list of CompositeMember objects 278 279class FunctionArgument: 280 def __init__ (self, name, qualifiers, aType, pointer = None, secondPointerIsConst = False, arraySize = None, len = None): 281 self.name = name 282 self.qualifiers = qualifiers 283 self.type = aType 284 self.pointer = pointer # None, '*' or '**' 285 self.secondPointerIsConst = secondPointerIsConst 286 self.arraySize = arraySize 287 self.len = len 288 289 # check if type should be swaped 290 substituteType(self) 291 292class Function: 293 TYPE_PLATFORM = 0 # Not bound to anything 294 TYPE_INSTANCE = 1 # Bound to VkInstance 295 TYPE_DEVICE = 2 # Bound to VkDevice 296 297 def __init__ (self, name, returnType = None, arguments = None): 298 self.name = name 299 self.aliasList = [] 300 self.queuesList = [] 301 self.returnType = returnType 302 self.arguments = arguments # list of FunctionArgument objects 303 self.functionType = Function.TYPE_PLATFORM 304 305 # Determine function type based on first argument but use TYPE_PLATFORM for vkGetInstanceProcAddr 306 if self.name == "vkGetInstanceProcAddr": 307 return 308 assert len(self.arguments) > 0 309 firstArgType = self.arguments[0].type 310 if firstArgType in ["VkInstance", "VkPhysicalDevice"]: 311 self.functionType = Function.TYPE_INSTANCE 312 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]: 313 self.functionType = Function.TYPE_DEVICE 314 315 def getType (self): 316 return self.functionType 317 318class FeatureEnumerator: 319 def __init__ (self, name, extends): 320 self.name = name 321 self.extends = extends 322 323class FeatureRequirement: 324 def __init__ (self, operation, comment, enumList, typeList, commandList): 325 self.operation = operation # "require" or "remove" 326 self.comment = comment 327 self.enumList = enumList # list of FeatureEnumerator objects 328 self.typeList = typeList # list of strings, each representing required structure name 329 self.commandList = commandList # list of strings, each representing required function name 330 331class Feature: 332 def __init__ (self, api, name, number, requirementsList): 333 self.api = api 334 self.name = name 335 self.number = number 336 self.requirementsList = requirementsList # list of FeatureRequirement objects 337 338class ExtensionEnumerator: 339 def __init__ (self, name, extends, alias, value, extnumber, offset, bitpos, vdir, comment): 340 self.name = name 341 self.extends = extends 342 self.alias = alias 343 self.value = value 344 self.extnumber = extnumber 345 self.offset = offset 346 self.bitpos = bitpos 347 self.dir = vdir 348 self.comment = comment # note: comment is used to mark not promoted features for partially promoted extensions 349 350class ExtensionCommand: 351 def __init__ (self, name, comment): 352 self.name = name 353 self.comment = comment 354 355class ExtensionType: 356 def __init__ (self, name, comment): 357 self.name = name 358 self.comment = comment 359 360class ExtensionRequirements: 361 def __init__ (self, depends, extendedEnums, newCommands, newTypes): 362 self.depends = depends # None when requirement apply to all implementations of extension or string with dependencies 363 # string with extension name when requirements apply to implementations that also support given extension 364 self.extendedEnums = extendedEnums # list of ExtensionEnumerator objects 365 self.newCommands = newCommands # list of ExtensionCommand objects 366 self.newTypes = newTypes # list of ExtensionType objects 367 368class Extension: 369 def __init__ (self, name, number, type, depends, platform, promotedto, partiallyPromoted, requirementsList): 370 self.name = name # extension name 371 self.number = number # extension version 372 self.type = type # extension type - "device" or "instance" 373 self.depends = depends # string containig grammar for required core vulkan version and/or other extensions 374 self.platform = platform # None, "win32", "ios", "android" etc. 375 self.promotedto = promotedto # vulkan version, other extension or None 376 self.partiallyPromoted = partiallyPromoted # when True then some of requirements were not promoted 377 self.requirementsList = requirementsList # list of ExtensionRequirements objects 378 379class API: 380 def __init__ (self, apiName): 381 self.apiName = apiName # string "vulkan" or "vulkansc" 382 self.versions = [] 383 self.basetypes = {} # dictionary, e.g. one of keys is VkFlags and its value is uint32_t 384 self.defines = [] 385 self.handles = [] # list of Handle objects 386 self.bitmasks = [] # list of Bitmask objects 387 self.enums = [] # list of Enum objects - each contains individual enum definition (including extension enums) 388 self.compositeTypes = [] # list of Composite objects - each contains individual structure/union definition (including extension structures) 389 self.functions = [] # list of Function objects - each contains individual command definition (including extension functions) 390 self.features = [] # list of Feature objects 391 self.extensions = [] # list of Extension objects - each contains individual, supported extension definition 392 self.notSupportedExtensions = [] # list of Extension objects - it contains NOT supported extensions; this is filled and needed only for SC 393 self.basicCTypes = [] # list of basic C types e.g. 'void', 'int8_t' 394 self.tempAliasesList = [] # list of aliases for enums that could not be added because enum is defined later than its alias; this is needed for SC 395 396 # read all files from extensions directory 397 additionalExtensionData = {} 398 for fileName in glob.glob(os.path.join(SCRIPTS_SRC_DIR, "extensions", "*.json")): 399 if "schema.json" in fileName: 400 continue 401 extensionName = os.path.basename(fileName)[:-5] 402 fileContent = readFile(fileName) 403 try: 404 additionalExtensionData[extensionName] = json.loads(fileContent) 405 except ValueError as err: 406 print("Error in %s: %s" % (os.path.basename(fileName), str(err))) 407 sys.exit(-1) 408 self.additionalExtensionData = sorted(additionalExtensionData.items(), key=lambda e: e[0]) 409 410 def addEnumerator(self, targetEnum, name, value, offset, extnumber, bitpos, dir = None): 411 # calculate enumerator value if offset attribute is present 412 if value is None and offset is not None: 413 value = 1000000000 + (int(extnumber) - 1) * 1000 + int(offset) 414 # check if value should be negative 415 value = -value if dir == "-" else value 416 # convert to string so that type matches the type in which values 417 # are stored for enums that were read from enums xml section 418 value = str(value) 419 # add new enumerator 420 targetEnum.enumeratorList.append(Enumerator(name, value, bitpos)) 421 422 def addAliasToEnumerator (self, targetEnum, name, alias): 423 assert(alias is not None) 424 for e in reversed(targetEnum.enumeratorList): 425 if alias == e.name or alias in e.aliasList: 426 # make sure same alias is not already on the list; this handles special case like 427 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR alais which is defined in three places 428 if name not in e.aliasList: 429 e.aliasList.append(name) 430 return True 431 return False 432 433 def readEnum (self, enumsNode): 434 enumName = enumsNode.get("name") 435 # special case for vulkan hardcoded constants that are specified as enum in vk.xml 436 if enumName == "API Constants": 437 for enumItem in enumsNode: 438 self.defines.append(Define( 439 enumItem.get("name"), 440 enumItem.get("type"), 441 enumItem.get("alias"), 442 enumItem.get("value") 443 )) 444 return 445 # initial enum definition is read while processing types section; 446 # we need to find this enum definition and add data to it 447 enumDefinition = [enumDef for enumDef in self.enums if enumName == enumDef.name][0] 448 # add type and bitwidth to enum definition 449 enumDefinition.type = enumsNode.get("type") 450 enumDefinition.bitwidth = enumsNode.get("bitwidth") 451 if enumDefinition.bitwidth is None: 452 enumDefinition.bitwidth = "32" 453 # add components to enum definition 454 for enumeratorItem in enumsNode: 455 # skip comment tags 456 if enumeratorItem.tag != "enum": 457 continue 458 name = enumeratorItem.get("name") 459 alias = enumeratorItem.get("alias") 460 if alias is None: 461 self.addEnumerator( 462 enumDefinition, 463 name, 464 enumeratorItem.get("value"), 465 enumeratorItem.get("offset"), 466 enumeratorItem.get("extnumber"), 467 enumeratorItem.get("bitpos"), 468 enumeratorItem.get("dir")) 469 else: 470 self.addAliasToEnumerator(enumDefinition, name, alias) 471 472 def readCommand (self, commandNode): 473 protoNode = None # proto is a first child of every command node 474 # check if this is alias 475 alias = commandNode.get("alias") 476 # if node is alias then use the fact that alias definition follows aliased structure 477 if alias is not None: 478 # aliased command has usually been added recently, so we iterate in reverse order 479 found = False 480 for f in reversed(self.functions): 481 found = (f.name == alias) 482 if found: 483 f.aliasList.append(commandNode.get("name")) 484 break 485 assert found 486 # go to next node 487 return 488 # memorize all parameters 489 functionParams = [] 490 queuesList = [] 491 492 for paramNode in commandNode: 493 # memorize prototype node 494 if paramNode.tag == "proto": 495 protoNode = paramNode 496 continue 497 # skip implicitexternsyncparams 498 if paramNode.tag != "param": 499 continue 500 nameNode = paramNode.find("name") 501 typeNode = paramNode.find("type") 502 starCount = typeNode.tail.count('*') 503 lenAttr = paramNode.get("len") 504 functionParams.append(FunctionArgument( 505 nameNode.text, 506 paramNode.text, 507 paramNode.find("type").text, 508 '*' * starCount if starCount > 0 else None, 509 'const' in typeNode.tail, 510 nameNode.tail, 511 lenAttr 512 )) 513 514 queuesAttr = commandNode.get("queues") 515 if queuesAttr: 516 queuesList = queuesAttr.split(",") 517 518 # memorize whole function 519 func = Function( 520 protoNode.find("name").text, 521 protoNode.find("type").text, 522 functionParams, 523 ) 524 525 func.queuesList = queuesList 526 self.functions.append(func) 527 528 def readExtension (self, extensionNode): 529 # check to which list this extension should be added 530 supportedList = extensionNode.get("supported") 531 isExtensionSupported = self.apiName in supportedList.split(',') 532 targetExtensionList = self.extensions if isExtensionSupported else self.notSupportedExtensions 533 # read extension definition to proper list 534 extensionName = extensionNode.get("name") 535 extensionNumber = extensionNode.get("number") 536 partiallyPromoted = False 537 # before reading extension data first read extension 538 # requirements by iterating over all require tags 539 requirementsList = [] 540 for requireItem in extensionNode: 541 extendedEnums = [] 542 newCommands = [] 543 newTypes = [] 544 # iterate over all children in current require tag 545 # and add them to proper list 546 for individualRequirement in requireItem: 547 requirementName = individualRequirement.get("name") 548 requirementComment = individualRequirement.get("comment") 549 # check if this requirement was not promoted and mark 550 # this extension as not fully promoted 551 if requirementComment is not None and "Not promoted to" in requirementComment: 552 partiallyPromoted = True 553 # check if this requirement describes enum, command or type 554 if individualRequirement.tag == "enum": 555 extendedEnumName = individualRequirement.get("extends") 556 extendedEnums.append(ExtensionEnumerator( 557 requirementName, 558 extendedEnumName, 559 individualRequirement.get("alias"), 560 individualRequirement.get("value"), 561 individualRequirement.get("extnumber"), 562 individualRequirement.get("offset"), 563 individualRequirement.get("bitpos"), 564 individualRequirement.get("dir"), 565 requirementComment)) 566 elif individualRequirement.tag == "command": 567 newCommands.append(ExtensionCommand(requirementName, requirementComment)) 568 elif individualRequirement.tag == "type": 569 newTypes.append(ExtensionType(requirementName, requirementComment)) 570 elif individualRequirement.tag == "comment" and "not promoted to" in individualRequirement.text: 571 # partial promotion of VK_EXT_ycbcr_2plane_444_formats and VK_EXT_4444_formats 572 # is marked with comment tag in first require section 573 partiallyPromoted = True 574 # construct requirement object and add it to the list 575 requirementsList.append(ExtensionRequirements( 576 requireItem.get("depends"), # dependencies that can include "and/or" grammar 577 extendedEnums, # extendedEnums 578 newCommands, # newCommands 579 newTypes # newTypes 580 )) 581 # add extension definition to proper api object 582 targetExtensionList.append(Extension( 583 extensionName, # name 584 extensionNumber, # number 585 extensionNode.get("type"), # type 586 extensionNode.get("depends"), # depends 587 extensionNode.get("platform"), # platform 588 extensionNode.get("promotedto"), # promotedto 589 partiallyPromoted, # partiallyPromoted 590 requirementsList # requirementsList 591 )) 592 593 def readFeature (self, featureNode): 594 requirementsList = [] 595 for requirementGroup in featureNode: 596 enumList = [] 597 typeList = [] 598 commandList = [] 599 for requirement in requirementGroup: 600 requirementName = requirement.get("name") 601 if requirement.tag == "enum": 602 extendedEnumName = requirement.get("extends") 603 enumList.append(FeatureEnumerator(requirementName, extendedEnumName)) 604 if extendedEnumName is not None: 605 # find extended enum in api.enums list 606 for e in self.enums: 607 if extendedEnumName == e.name: 608 # read enumerator and add it to enum 609 alias = requirement.get("alias") 610 if alias is None: 611 self.addEnumerator( 612 e, 613 requirementName, 614 requirement.get("value"), 615 requirement.get("offset"), 616 requirement.get("extnumber"), 617 requirement.get("bitpos"), 618 requirement.get("dir")) 619 elif not self.addAliasToEnumerator(e, requirementName, alias): 620 self.tempAliasesList.append((e, requirementName, alias)) 621 break 622 elif requirement.tag == "type": 623 typeList.append(requirementName) 624 elif requirement.tag == "command": 625 commandList.append(requirementName) 626 requirementsList.append(FeatureRequirement( 627 requirementGroup.tag, 628 requirementGroup.get("comment"), 629 enumList, 630 typeList, 631 commandList 632 )) 633 self.features.append(Feature( 634 featureNode.get("api"), 635 featureNode.get("name"), 636 featureNode.get("number"), 637 requirementsList 638 )) 639 640 def readType (self, typeNode): 641 name = typeNode.get("name") 642 alias = typeNode.get("alias") 643 category = typeNode.get("category") 644 if category == "enum": 645 if alias is None: 646 self.enums.append(Enum(name)) 647 else: 648 for e in reversed(self.enums): 649 if alias == e.name: 650 e.alias = name 651 break 652 elif category == "handle": 653 type = None 654 if alias is None: 655 name = typeNode.find("name").text 656 type = typeNode.find("type").text 657 self.handles.append(Handle( 658 name, 659 type, 660 alias, 661 typeNode.get("parent"), 662 typeNode.get("objtypeenum"), 663 )) 664 else: 665 for h in reversed(self.handles): 666 if alias == h.name: 667 h.alias = name 668 break 669 elif category == "basetype": 670 # processing only those basetypes that have type child 671 type = typeNode.find("type") 672 if type is not None: 673 self.basetypes[typeNode.find("name").text] = type.text 674 elif category == "bitmask": 675 # if node is alias then use the fact that alias definition follows aliased bitmasks; 676 # in majoriti of cases it follows directly aliased bitmasks but in some cases there 677 # is a unrelated bitmasks definition in between - to handle this traverse in reverse order 678 if alias is not None: 679 for bm in reversed(self.bitmasks): 680 if alias == bm.name: 681 bm.alias = name 682 break 683 else: 684 self.bitmasks.append(Bitmask( 685 typeNode.find("name").text, 686 typeNode.find("type").text, 687 typeNode.get("requires"), 688 typeNode.get("bitvalues") 689 )) 690 elif category in ["struct", "union"]: 691 # if node is alias then use the fact that alias definition follows aliased structure; 692 # in majoriti of cases it follows directly aliased structure but in some cases there 693 # is a unrelated structure definition in between - to handle this traverse in reverse order 694 if alias is not None: 695 for ct in reversed(self.compositeTypes): 696 if alias == ct.name: 697 ct.aliasList.append(name) 698 break 699 # go to next node 700 return 701 # read structure members 702 structMembers = [] 703 for memberNode in typeNode: 704 if memberNode.tag != "member": 705 continue 706 # handle enum nodes that can be used for array dimensions 707 arraySizeList = [] 708 for node in memberNode: 709 if node.tag == "enum": 710 arraySizeList.append(node.text) 711 # check if there are array dimension that are not enums 712 if '[' in node.tail and len(node.tail) > 2: 713 arraySizeList += node.tail.replace(']', ' ').replace('[', ' ').split() 714 # handle additional text after name tag; it can represent array 715 # size like in VkPipelineFragmentShadingRateEnumStateCreateInfoNV 716 # or number of bits like in VkAccelerationStructureInstanceKHR 717 nameNode = memberNode.find("name") 718 nameTail = nameNode.tail 719 fieldWidth = None 720 if nameTail: 721 if ':' in nameTail: 722 fieldWidth = nameTail.replace(':', '').replace(' ', '') 723 elif '[' in nameTail and ']' in nameTail: 724 nameTail = nameTail.replace(']', ' ').replace('[', ' ') 725 arraySizeList = nameTail.split() + arraySizeList 726 # handle additional text after type tag; it can represent pointers like *pNext 727 memberTypeNode = memberNode.find("type") 728 pointer = memberTypeNode.tail.strip() if memberTypeNode.tail is not None else None 729 structMembers.append(CompositeMember( 730 nameNode.text, # name 731 memberTypeNode.text, # type 732 pointer, # pointer 733 memberNode.text, # qualifiers 734 arraySizeList, # arraySizeList 735 memberNode.get("optional"), # optional 736 memberNode.get("limittype"), # limittype 737 memberNode.get("values"), # values 738 fieldWidth # fieldWidth 739 )) 740 # create structure definition 741 self.compositeTypes.append(Composite( 742 name, 743 category, 744 typeNode.get("allowduplicate"), 745 typeNode.get("structextends"), 746 typeNode.get("returnedonly"), 747 structMembers 748 )) 749 elif category == "define": 750 nNode = typeNode.find("name") 751 tNode = typeNode.find("type") 752 if nNode == None or tNode == None: 753 return 754 requires = typeNode.get("requires") 755 name = nNode.text 756 if "API_VERSION_" in name or requires == "VK_MAKE_VIDEO_STD_VERSION": 757 value = tNode.tail 758 value = tNode.text + value[:value.find(')')+1] 759 value = value.replace('VKSC_API_VARIANT', '1') 760 self.defines.append(Define( 761 name, 762 "uint32_t", 763 None, 764 value 765 )) 766 else: 767 requires = typeNode.get("requires") 768 if requires == 'vk_platform': 769 self.basicCTypes.append(name) 770 771 def build (self, rawVkXml): 772 # iterate over all *.xml root children 773 for rootChild in rawVkXml.getroot(): 774 775 # each enum is defined in separate enums node directly under root node 776 if rootChild.tag == "enums": 777 self.readEnum(rootChild) 778 779 # read function definitions 780 if rootChild.tag == "commands": 781 commandsNode = rootChild 782 for commandItem in commandsNode: 783 self.readCommand(commandItem) 784 785 # read vulkan versions 786 if rootChild.tag == "feature": 787 self.readFeature(rootChild) 788 789 # read extensions 790 if rootChild.tag == "extensions": 791 extensionsNode = rootChild 792 for extensionItem in extensionsNode: 793 self.readExtension(extensionItem) 794 795 # "types" is a first child of root so it's optimal to check for it 796 # last and don't repeat this check for all other iterations 797 if rootChild.tag == "types": 798 typesNode = rootChild 799 for typeItem in typesNode: 800 self.readType(typeItem) 801 802 # Verify that promotedto extensions are supported by the api 803 for ext in self.extensions: 804 if ext.promotedto is not None and "VK_VERSION" not in ext.promotedto: 805 if not any(x.name == ext.promotedto for x in self.extensions): 806 ext.promotedto = None 807 808 def postProcess (self): 809 810 # temporary workaround for extensions that are marked only for vulkan api in xml while 811 # they are need by vulkan_json_data.hpp and vulkan_json_parser.hpp in vulkansc 812 if self.apiName == "vulkansc": 813 deviceDiagnosticCheckpoints = [e for e in self.notSupportedExtensions if e.name == "VK_NV_device_diagnostic_checkpoints"] 814 if len(deviceDiagnosticCheckpoints): 815 deviceDiagnosticCheckpoints = deviceDiagnosticCheckpoints[0] 816 self.extensions.append(deviceDiagnosticCheckpoints) 817 self.notSupportedExtensions.remove(deviceDiagnosticCheckpoints) 818 formatFeatureFlags2 = [e for e in self.notSupportedExtensions if e.name == "VK_KHR_format_feature_flags2"] 819 if len(formatFeatureFlags2): 820 formatFeatureFlags2 = formatFeatureFlags2[0] 821 self.extensions.append(formatFeatureFlags2) 822 self.notSupportedExtensions.remove(formatFeatureFlags2) 823 824 # add new enumerators that were added by extensions to api.enums 825 # we have to do it at the end for SC because some enums are dependent from extensions/api versions 826 # and those dependencies can be checked only after all extensions were read 827 for ext in self.extensions: 828 for requirement in ext.requirementsList: 829 # check if this requirement is supported by current implementation 830 isRequirementSupported = isDependencyMet(requirement.depends, self.extensions) 831 # add enumerator to proper enum from api.enums 832 if isRequirementSupported: 833 for enumerator in requirement.extendedEnums: 834 if enumerator.extends is None: 835 continue 836 # find enum in api.enums 837 matchedEnum = [enum for enum in self.enums if enumerator.extends == enum.name][0] 838 # add enumerator only when it is not already in enum 839 if len([e for e in matchedEnum.enumeratorList if e.name == enumerator.name]) == 0: 840 if enumerator.alias == None: 841 self.addEnumerator( 842 matchedEnum, 843 enumerator.name, 844 enumerator.value, 845 enumerator.offset, 846 enumerator.extnumber if enumerator.extnumber else ext.number, 847 enumerator.bitpos, 848 enumerator.dir) 849 elif not self.addAliasToEnumerator(matchedEnum, enumerator.name, enumerator.alias): 850 # we might not be able to add alias as we might be missing what we are aliasing 851 # this will hapen when aliased enum is added later then definition of alias 852 self.tempAliasesList.append((matchedEnum, enumerator.name, enumerator.alias)) 853 else: 854 logging.warning("Skipping requirement in extension %s because dependencies are not met: %s" % (ext.name, requirement.depends)) 855 856 # add aliases to enumerators that were defined after alias definition 857 for enum, name, alias in self.tempAliasesList: 858 if not self.addAliasToEnumerator(enum, name, alias): 859 # if enumerator that should be aliased was not found then try to insert it without alias 860 # (this happens for vulkansc as in xml enumerator might be defined in extension that is not supported by sc) 861 def tryToFindEnumValue(searchedName): 862 for nsExt in self.notSupportedExtensions: 863 for r in nsExt.requirementsList: 864 for enumerator in r.extendedEnums: 865 if enumerator.name == searchedName: 866 self.addEnumerator( 867 enum, 868 name, 869 enumerator.value, 870 enumerator.offset, 871 enumerator.extnumber if enumerator.extnumber else ext.number, 872 enumerator.bitpos, 873 enumerator.dir) 874 # there are ~2 cases where alias that is not part of SC still needs to be added for SC 875 self.addAliasToEnumerator(enum, alias, name) 876 return 877 # using function for easy stack unwinding 878 tryToFindEnumValue(alias) 879 self.tempAliasesList = None 880 881 if self.apiName == "vulkan": 882 def removeExtensionFromApi(extName, structureNameList, commandNameList): 883 extObjectList = [e for e in api.extensions if e.name == extName] 884 if len(extObjectList) > 0: 885 api.extensions.remove(extObjectList[0]) 886 structObjectList = [ct for ct in api.compositeTypes if ct.name in structureNameList] 887 for s in structObjectList: 888 api.compositeTypes.remove(s) 889 commandObjectList = [f for f in api.functions if f.name in commandNameList] 890 for f in commandObjectList: 891 api.functions.remove(f) 892 893 # remove structures and commands added by VK_EXT_directfb_surface extension 894 removeExtensionFromApi("VK_EXT_directfb_surface", 895 ["VkDirectFBSurfaceCreateFlagsEXT", "VkDirectFBSurfaceCreateInfoEXT"], 896 ["vkCreateDirectFBSurfaceEXT", "vkGetPhysicalDeviceDirectFBPresentationSupportEXT"]) 897 898 # remove structures and commands added by disabled VK_ANDROID_native_buffer extension; 899 # disabled extensions aren't read but their structures and commands will be in types and commands sections in vk.xml 900 removeExtensionFromApi("VK_ANDROID_native_buffer", 901 ["VkNativeBufferANDROID", "VkSwapchainImageCreateInfoANDROID", 902 "VkPhysicalDevicePresentationPropertiesANDROID", "VkNativeBufferUsage2ANDROID", 903 "VkSwapchainImageUsageFlagBitsANDROID", "VkSwapchainImageUsageFlagsANDROID"], 904 ["vkGetSwapchainGrallocUsageANDROID", "vkAcquireImageANDROID", 905 "vkQueueSignalReleaseImageANDROID", "vkGetSwapchainGrallocUsage2ANDROID"]) 906 907 # remove empty enums e.g. VkQueryPoolCreateFlagBits, VkDeviceCreateFlagBits 908 enumsToRemove = [enum for enum in self.enums if len(enum.enumeratorList) == 0] 909 for er in enumsToRemove: 910 self.enums.remove(er) 911 912 # add alias for VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR (in vk.xml for this struct alias is defined before struct 913 # where in all other cases it is defined after structure definition) 914 barycentricFeaturesStruct = [c for c in api.compositeTypes if c.name == 'VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR'][0] 915 barycentricFeaturesStruct.aliasList.append('VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV') 916 917 elif self.apiName == "vulkansc": 918 # remove commands that are marked with <remove> tag in SC feature specification; 919 # e.g. there is no vkCreateShaderModule in SC 920 functionsToRemove = [] 921 scFeatures = [f for f in self.features if f.api == "vulkansc"][0] 922 for featureRequirement in scFeatures.requirementsList: 923 if featureRequirement.operation == "remove": 924 for removeFun in featureRequirement.commandList: 925 # find function in the list of all functions 926 for fun in self.functions: 927 if removeFun == fun.name: 928 functionsToRemove.append(fun) 929 break 930 for fun in functionsToRemove: 931 self.functions.remove(fun) 932 # sc is based on vk1.2 so we need to check features of vk1.3+ 933 # and rename functions and structures that were promoted in 934 # those versions to their previous names (aliases) 935 renamedStructuresDict = {} 936 for feature in self.features: 937 # skip vk versions smaller than 1.3 938 if int(feature.number[-1]) < 3: 939 continue 940 # iterate over all requirements and enums/commands/structs added in them 941 for featureRequirement in feature.requirementsList: 942 for promotedEnumerator in featureRequirement.enumList: 943 # iterate over all enums and find one that was extended 944 for enum in self.enums: 945 if enum.name != promotedEnumerator.extends: 946 continue 947 enumeratorReplaced = False 948 # find enumerator that should have changed name 949 for enumerator in enum.enumeratorList: 950 if enumerator.name != promotedEnumerator.name or len(enumerator.aliasList) == 0: 951 continue 952 # replace enumerator name with its first alias 953 enumerator.name = enumerator.aliasList[0] 954 enumerator.aliasList = enumerator.aliasList[1:] 955 # first member of almost all structures is VkStructureType and in xml that member 956 # has defined value - we need to change those values to versions supported by SC 957 if "STRUCTURE_TYPE" in enumerator.name: 958 for struct in self.compositeTypes: 959 if struct.members[0].values == promotedEnumerator.name: 960 struct.members[0].values = enumerator.name 961 break 962 enumeratorReplaced = True 963 break 964 if enumeratorReplaced: 965 break 966 renamedFunctionsList = [] 967 for promotedFun in featureRequirement.commandList: 968 # find promotedFun in list of all functions 969 for fun in self.functions: 970 if fun.name != promotedFun: 971 continue 972 # replace function name with its first alias 973 fun.name = fun.aliasList[0] 974 fun.aliasList = fun.aliasList[1:] 975 # memorize renamed functions 976 renamedFunctionsList.append(fun) 977 break 978 for promotedStruct in featureRequirement.typeList: 979 # find promotedStruct in list of all structures 980 for struct in self.compositeTypes: 981 if struct.name != promotedStruct: 982 continue 983 # skip structures without alias 984 if len(struct.aliasList) == 0: 985 break 986 # replace struct name with its first alias 987 struct.name = struct.aliasList[0] 988 struct.aliasList = struct.aliasList[1:] 989 # memorize all renamed structures 990 renamedStructuresDict[promotedStruct] = struct 991 # check all all renamed functions and make sure that argument types are also renamed 992 for renamedFun in renamedFunctionsList: 993 for arg in renamedFun.arguments: 994 if arg.type == promotedStruct: 995 arg.type = struct.name 996 break 997 # iterate over all renamed structures and make sure that all their attributes are also renamed 998 for newName in renamedStructuresDict: 999 for member in renamedStructuresDict[newName].members: 1000 if member.type in renamedStructuresDict: 1001 member.type = renamedStructuresDict[member.type].name 1002 1003 # remove enums that are not part of any vulkan version nor extension 1004 # (SC specific enums are in vk.xml without any attribute identifying that they are SC specific; same for enums for disabled extensions) 1005 def isEnumUsed(featureList, extensionList, enumName, enumAlias): 1006 for feature in featureList: 1007 for requirement in feature.requirementsList: 1008 for typeName in requirement.typeList: 1009 if (typeName == enumName) or (typeName == enumAlias): 1010 return True 1011 for ext in extensionList: 1012 for requirement in ext.requirementsList: 1013 for newType in requirement.newTypes: 1014 if (newType.name == enumName) or (newType.name == enumAlias): 1015 return True 1016 return False 1017 # do removal using above function 1018 enumsToRemove = [] 1019 for enum in self.enums: 1020 if isEnumUsed(self.features, self.extensions, enum.name, enum.alias): 1021 continue 1022 enumsToRemove.append(enum) 1023 for er in enumsToRemove: 1024 self.enums.remove(er) 1025 1026 # remove structures that are not part of any vulkan version nor extension 1027 # (SC specific structures are in vk.xml without any attribute identifying that they are SC specific) 1028 def isStructUsed(featureList, extensionList, structNameList): 1029 for feature in featureList: 1030 for requirement in feature.requirementsList: 1031 for typeName in requirement.typeList: 1032 if typeName in structNameList: 1033 return True 1034 for ext in extensionList: 1035 for requirement in ext.requirementsList: 1036 for newType in requirement.newTypes: 1037 if newType.name in structNameList: 1038 return isDependencyMet(requirement.depends, extensionList) 1039 return False 1040 1041 structsToRemove = [] 1042 for struct in self.compositeTypes: 1043 structNameList = [struct.name] + struct.aliasList 1044 if isStructUsed(self.features, self.extensions, structNameList): 1045 continue 1046 structsToRemove.append(struct) 1047 for st in structsToRemove: 1048 self.compositeTypes.remove(st) 1049 1050 # remove commands that are not part of any vulkan version nor extension 1051 # (SC specific commands are in vk.xml without any attribute identifying that they are SC specific) 1052 def isFunctionUsed(featureList, extensionList, functionNameList): 1053 for feature in featureList: 1054 for requirement in feature.requirementsList: 1055 for commandName in requirement.commandList: 1056 if commandName in functionNameList: 1057 return True 1058 for ext in extensionList: 1059 for requirement in ext.requirementsList: 1060 for newCommand in requirement.newCommands: 1061 if newCommand.name in functionNameList: 1062 return isDependencyMet(requirement.depends, extensionList) 1063 return False 1064 1065 functionsToRemove = [] 1066 for fun in self.functions: 1067 functionNameList = [fun.name] + fun.aliasList 1068 if isFunctionUsed(self.features, self.extensions, functionNameList): 1069 continue 1070 functionsToRemove.append(fun) 1071 for fun in functionsToRemove: 1072 logging.debug("Removing function %s because not used" % (fun.name)) 1073 self.functions.remove(fun) 1074 1075 # remove handles that are not part of any vulkan command or structure 1076 def isHandleUsed(structList, functionList, handleName): 1077 for struct in structList: 1078 for member in struct.members: 1079 if handleName in member.type: 1080 return True 1081 for fun in functionList: 1082 for arg in fun.arguments: 1083 if handleName in arg.type: 1084 return True 1085 return False 1086 1087 handlesToRemove = [] 1088 for h in self.handles: 1089 if isHandleUsed(self.compositeTypes, self.functions, h.name): 1090 continue 1091 handlesToRemove.append(h) 1092 for h in handlesToRemove: 1093 self.handles.remove(h) 1094 1095 # sort enumerators in enums 1096 sortLambda = lambda enumerator: int(enumerator.bitpos) if enumerator.value is None else int(enumerator.value, 16 if 'x' in enumerator.value else 10) 1097 for enum in self.enums: 1098 # skip enums that have no items or just one in enumeratorList (e.g. VkQueryPoolCreateFlagBits) 1099 if len(enum.enumeratorList) < 2: 1100 continue 1101 # construct list of enumerators in which value and bitpos are not None 1102 enumeratorsToSort = [e for e in enum.enumeratorList if e.value != e.bitpos] 1103 # construct list of enumerators in which value and bitpos are equal to None 1104 remainingEnumerators = [e for e in enum.enumeratorList if e.value == e.bitpos] 1105 # construct sorted enumerator list with aliases at the end 1106 enum.enumeratorList = sorted(enumeratorsToSort, key=sortLambda) 1107 enum.enumeratorList.extend(remainingEnumerators) 1108 1109def prefixName (prefix, name): 1110 name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:]) 1111 name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name) 1112 name = name.upper() 1113 return prefix + name 1114 1115def parseInt (value): 1116 return int(value, 16 if ("0x" in value) else 10) 1117 1118def getApiVariantIndexByName(variantName): 1119 apiVariant = { 1120 None : 0, 1121 '' : 0, 1122 'SC' : 1 1123 } 1124 return apiVariant[variantName] 1125 1126def getApiVariantNameByIndex(variantIndex): 1127 apiVariant = { 1128 None : '', 1129 0 : '', 1130 1 : 'SC' 1131 } 1132 return apiVariant[variantIndex] 1133 1134def readFile (filename): 1135 with open(filename, 'rt') as f: 1136 return f.read() 1137 1138def getInterfaceName (functionName): 1139 assert functionName[:2] == "vk" 1140 return functionName[2].lower() + functionName[3:] 1141 1142def getFunctionTypeName (functionName): 1143 assert functionName[:2] == "vk" 1144 return functionName[2:] + "Func" 1145 1146def endsWith (str, postfix): 1147 return str[-len(postfix):] == postfix 1148 1149def writeHandleType (api, filename): 1150 1151 def getHandleName (name): 1152 return prefixName("HANDLE_TYPE_", name) 1153 1154 def genHandles (): 1155 yield "\t%s\t= 0," % getHandleName(api.handles[0].name) 1156 for h in api.handles[1:]: 1157 yield "\t%s," % getHandleName(h.name) 1158 for h in api.handles: 1159 if h.alias is not None: 1160 yield "\t%s\t= %s," % (getHandleName(h.alias), getHandleName(h.name)) 1161 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (getHandleName(api.handles[-1].name)) 1162 1163 def genHandlesBlock (): 1164 yield "enum HandleType" 1165 yield "{" 1166 1167 for line in indentLines(genHandles()): 1168 yield line 1169 1170 yield "};" 1171 yield "" 1172 1173 writeInlFile(filename, INL_HEADER, genHandlesBlock()) 1174 1175def getEnumValuePrefixAndPostfix (enum): 1176 prefix = enum.name[0] 1177 for i in range(1, len(enum.name)): 1178 if enum.name[i].isupper() and not enum.name[i-1].isupper(): 1179 prefix += "_" 1180 prefix += enum.name[i].upper() 1181 for p in EXTENSION_POSTFIXES: 1182 if prefix.endswith(p): 1183 return prefix[:-len(p)-1], '_'+p 1184 return prefix, '' 1185 1186def genEnumSrc (enum): 1187 yield "enum %s" % enum.name 1188 yield "{" 1189 lines = [] 1190 for ed in enum.enumeratorList: 1191 if ed.value is not None: 1192 lines.append(f"\t{ed.name}\t= {ed.value},") 1193 for ed in enum.enumeratorList: 1194 for alias in ed.aliasList: 1195 lines.append(f"\t{alias}\t= {ed.name},") 1196 1197 # add *_LAST item when enum is linear 1198 prefix, postfix = getEnumValuePrefixAndPostfix(enum) 1199 if enum.areValuesLinear(): 1200 lines.append(f"\t{prefix}{postfix}_LAST,") 1201 1202 # add _MAX_ENUM item with the ext postifix at the end 1203 lines.append(f"\t{prefix}_MAX_ENUM{postfix}\t= 0x7FFFFFFF") 1204 1205 for line in indentLines(lines): 1206 yield line 1207 1208 yield "};" 1209 1210def genBitfieldSrc (bitfield): 1211 lines = [] 1212 for ev in bitfield.enumeratorList: 1213 # bitfields may use mix of bitpos and values 1214 if ev.bitpos is not None: 1215 value = pow(2, int(ev.bitpos)) 1216 lines.append(f"\t{ev.name}\t= {value:#010x},") 1217 if ev.value is not None: 1218 lines.append(f"\t{ev.name}\t= {ev.value},") 1219 for ev in bitfield.enumeratorList: 1220 for alias in ev.aliasList: 1221 lines.append(f"\t{alias}\t= {ev.name},") 1222 # add _MAX_ENUM item 1223 prefix, postfix = getEnumValuePrefixAndPostfix(bitfield) 1224 lines.append(f"\t{prefix}_MAX_ENUM{postfix}\t= 0x7FFFFFFF") 1225 yield f"enum {bitfield.name}" 1226 yield "{" 1227 for line in indentLines(lines): 1228 yield line 1229 yield "};" 1230 1231def genBitfield64Src (bitfield64): 1232 def generateEntry(lines, bitfieldName, entryName, bitpos, value): 1233 if entryName is None: 1234 return 1235 # bitfields may use mix of bitpos and values 1236 if ev.bitpos is not None: 1237 v = pow(2, int(bitpos)) 1238 lines.append(f"static const {bitfieldName} {entryName}\t= {v:#010x}ULL;") 1239 if value is not None: 1240 lines.append(f"static const {bitfieldName} {entryName}\t= {value}ULL;") 1241 1242 yield f"typedef uint64_t {bitfield64.name};" 1243 lines = [] 1244 for ev in bitfield64.enumeratorList: 1245 generateEntry(lines, bitfield64.name, ev.name, ev.bitpos, ev.value) 1246 for alias in ev.aliasList: 1247 generateEntry(lines, bitfield64.name, alias, ev.bitpos, ev.value) 1248 # write indented lines 1249 for line in indentLines(lines): 1250 yield line 1251 yield "" 1252 1253def genDefinesSrc (apiName, defines): 1254 def genLines (defines): 1255 for d in defines: 1256 if d.alias is not None: 1257 continue 1258 defineType = DEFINITIONS.get(d.name, d.type) 1259 yield f"#define {d.name}\t(static_cast<{defineType}>\t({d.value}))" 1260 for line in indentLines(genLines(defines)): 1261 yield line 1262 # add VK_API_MAX_FRAMEWORK_VERSION 1263 major, minor = api.features[-1].number.split('.') 1264 yield f"#define VK{apiName}_API_MAX_FRAMEWORK_VERSION\tVK{apiName}_API_VERSION_{major}_{minor}" 1265 1266def genHandlesSrc (handles): 1267 def genLines (handles): 1268 for h in handles: 1269 handleType = h.type 1270 handleObjtype = h.objtypeenum 1271 if h.alias is not None: 1272 # search for aliased handle 1273 for searchedHandle in handles: 1274 if h.alias == searchedHandle.name: 1275 handleType = searchedHandle.type 1276 handleObjtype = searchedHandle.objtypeenum 1277 break 1278 yield f"{handleType}\t({h.name},\tHANDLE{handleObjtype[9:]});" 1279 for line in indentLines(genLines(handles)): 1280 yield line 1281 1282def genHandlesSrc (handles): 1283 def genLines (handles): 1284 for h in handles: 1285 handleType = h.type 1286 handleObjtype = h.objtypeenum 1287 line = f"{handleType}\t({{}},\tHANDLE{handleObjtype[9:]});" 1288 yield line.format(h.name) 1289 if h.alias is not None: 1290 yield line.format(h.alias) 1291 1292 for line in indentLines(genLines(handles)): 1293 yield line 1294 1295def writeBasicTypes (api, filename): 1296 1297 def gen (): 1298 1299 for line in genDefinesSrc("SC" if api.apiName == "vulkansc" else "", api.defines): 1300 yield line 1301 yield "" 1302 1303 for line in genHandlesSrc(api.handles): 1304 yield line 1305 yield "" 1306 1307 for enum in api.enums: 1308 # skip empty enums only for vulkan 1309 # vulkan_json_data.hpp and vulkan_json_parser.hpp in SC need many empty enums 1310 if len(enum.enumeratorList) == 0 and api.apiName == "vulkan": 1311 continue 1312 if enum.type == "bitmask": 1313 if enum.bitwidth == "32": 1314 for line in genBitfieldSrc(enum): 1315 yield line 1316 else: 1317 for line in genBitfield64Src(enum): 1318 yield line 1319 else: 1320 for line in genEnumSrc(enum): 1321 yield line 1322 if enum.alias is not None: 1323 yield f"typedef {enum.name} {enum.alias};" 1324 yield "" 1325 1326 for bitmask in api.bitmasks: 1327 plainType = api.basetypes[bitmask.type] 1328 yield f"typedef {plainType} {bitmask.name};\n" 1329 if bitmask.alias: 1330 yield f"typedef {bitmask.name} {bitmask.alias};\n" 1331 1332 yield "" 1333 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s)" % (s[0], c) for n, s, c in PLATFORM_TYPES]): 1334 yield line 1335 yield "" 1336 1337 for ext in api.extensions: 1338 firstRequirementEnums = ext.requirementsList[0].extendedEnums 1339 for e in firstRequirementEnums: 1340 if e.extends is None and e.value is not None: 1341 yield "#define " + e.name + " " + e.value 1342 1343 writeInlFile(filename, INL_HEADER, gen()) 1344 1345def writeCompositeTypes (api, filename): 1346 # function that returns definition of structure member 1347 def memberAsString (member): 1348 result = '' 1349 if member.qualifiers: 1350 result += member.qualifiers 1351 result += member.type 1352 if member.pointer: 1353 result += member.pointer 1354 result += '\t' + member.name 1355 for size in member.arraySizeList: 1356 result += f"[{size}]" 1357 if member.fieldWidth: 1358 result += f":{member.fieldWidth}" 1359 return result 1360 1361 # function that prints single structure definition 1362 def genCompositeTypeSrc (type): 1363 structLines = "%s %s\n{\n" % (type.category, type.name) 1364 for line in indentLines(['\t'+memberAsString(m)+';' for m in type.members]): 1365 structLines += line + '\n' 1366 return structLines + "};\n" 1367 1368 # function that prints all structure definitions and alias typedefs 1369 def gen (): 1370 # structures in xml are not ordered in a correct way for C++ 1371 # we need to save structures that are used in other structures first 1372 allStructureNamesList = [s.name for s in api.compositeTypes] 1373 commonTypesList = api.basicCTypes + ['VkStructureType'] 1374 savedStructureNamesList = [] 1375 delayedStructureObjectsList = [] 1376 1377 # helper function that checks if all structure members were already saved 1378 def canStructBeSaved(compositeObject): 1379 for m in compositeObject.members: 1380 # check first commonTypesList to speed up the algorithm 1381 if m.type in commonTypesList: 1382 continue 1383 # make sure that member is not of same type as compositeObject 1384 # (this hadles cases like VkBaseOutStructure) 1385 if m.type == compositeObject.name: 1386 continue 1387 # if member is of compositeType that was not saved we cant save it now 1388 if m.type in allStructureNamesList and m.type not in savedStructureNamesList: 1389 return False 1390 return True 1391 1392 # iterate over all composite types 1393 lastDelayedComposite = None 1394 for ct in api.compositeTypes: 1395 # check if one of delayed structures can be saved 1396 delayedButSaved = [] 1397 for dct in delayedStructureObjectsList: 1398 if lastDelayedComposite != dct and canStructBeSaved(dct): 1399 yield genCompositeTypeSrc(dct) 1400 delayedButSaved.append(dct) 1401 lastDelayedComposite = None 1402 for dsct in delayedButSaved: 1403 savedStructureNamesList.append(dsct.name) 1404 delayedStructureObjectsList.remove(dsct) 1405 # check if current structure can be saved 1406 if canStructBeSaved(ct): 1407 yield genCompositeTypeSrc(ct) 1408 savedStructureNamesList.append(ct.name) 1409 else: 1410 delayedStructureObjectsList.append(ct) 1411 # memorize structure that was delayed in last iteration to 1412 # avoid calling for it canStructBeSaved in next iteration 1413 lastDelayedComposite = ct 1414 # save remaining delayed composite types (~4 video related structures) 1415 while len(delayedStructureObjectsList) > 0: 1416 for dct in delayedStructureObjectsList: 1417 if canStructBeSaved(dct): 1418 yield genCompositeTypeSrc(dct) 1419 savedStructureNamesList.append(dct.name) 1420 delayedStructureObjectsList.remove(dct) 1421 break 1422 # write all alias typedefs 1423 for ct in api.compositeTypes: 1424 for alias in ct.aliasList: 1425 yield "typedef %s %s;" % (ct.name, alias) 1426 yield "" 1427 1428 writeInlFile(filename, INL_HEADER, gen()) 1429 1430def argListToStr (args): 1431 def argumentToString(arg): 1432 # args can be instance of FunctionArgument or CompositeMember 1433 # but CompositeMember has no arraySize atrribute nor secondPointerIsConst 1434 workingOnFunctionArgument = True if hasattr(arg, 'arraySize') else False 1435 result = '' 1436 if arg.qualifiers: 1437 result += arg.qualifiers 1438 result += arg.type 1439 if arg.pointer: 1440 if workingOnFunctionArgument and arg.secondPointerIsConst: 1441 result += '* const*' 1442 else: 1443 result += arg.pointer 1444 result += ' ' + arg.name 1445 if workingOnFunctionArgument: 1446 if arg.arraySize: 1447 result += arg.arraySize 1448 return result 1449 return ", ".join(argumentToString(arg) for arg in args) 1450 1451def writeInterfaceDecl (api, filename, functionTypes, concrete): 1452 def genProtos (): 1453 postfix = "" if concrete else " = 0" 1454 for function in api.functions: 1455 if not function.getType() in functionTypes: 1456 continue 1457 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments), postfix) 1458 1459 writeInlFile(filename, INL_HEADER, indentLines(genProtos())) 1460 1461def writeFunctionPtrTypes (api, filename): 1462 def genTypes (): 1463 pattern = "typedef VKAPI_ATTR {}\t(VKAPI_CALL* {})\t({});" 1464 for function in api.functions: 1465 argList = argListToStr(function.arguments) 1466 yield pattern.format(function.returnType, getFunctionTypeName(function.name), argList) 1467 for alias in function.aliasList: 1468 yield pattern.format(function.returnType, getFunctionTypeName(alias), argList) 1469 1470 writeInlFile(filename, INL_HEADER, indentLines(genTypes())) 1471 1472def writeFunctionPointers (api, filename, functionTypes): 1473 def FunctionsYielder (): 1474 for function in api.functions: 1475 if function.getType() in functionTypes: 1476 interfaceName = getInterfaceName(function.name) 1477 functionTypeName = getFunctionTypeName(function.name) 1478 yield f"{functionTypeName}\t{interfaceName};" 1479 if function.getType() == Function.TYPE_INSTANCE: 1480 for alias in function.aliasList: 1481 interfaceName = getInterfaceName(alias) 1482 functionTypeName = getFunctionTypeName(alias) 1483 yield f"{functionTypeName}\t{interfaceName};" 1484 1485 writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder())) 1486 1487def getPromotedFunctions (api): 1488 apiNum = 0 if api.apiName == "vulkan" else 1 1489 promotedFunctions = collections.defaultdict(lambda: list()) 1490 for feature in api.features: 1491 versionSplit = feature.name.split('_') 1492 apiMajor = int(versionSplit[-2]) 1493 apiMinor = int(versionSplit[-1]) 1494 apiPrefix = '_'.join(versionSplit[:-2]) 1495 if apiNum == 0 and apiPrefix != 'VK_VERSION': 1496 continue 1497 if apiNum == 1 and apiPrefix == 'VK_VERSION': 1498 # Map of "standard" Vulkan versions to VulkanSC version. 1499 stdToSCMap = { 1500 (1, 0): (1, 0), 1501 (1, 1): (1, 0), 1502 (1, 2): (1, 0), 1503 } 1504 mapKey = (apiMajor, apiMinor) 1505 if mapKey not in stdToSCMap: 1506 continue 1507 (apiMajor, apiMinor) = stdToSCMap[mapKey] 1508 apituple = (apiNum, apiMajor, apiMinor) 1509 for featureRequirement in feature.requirementsList: 1510 for promotedFun in featureRequirement.commandList: 1511 promotedFunctions[promotedFun].append(apituple) 1512 return promotedFunctions 1513 1514def writeInitFunctionPointers (api, filename, functionTypes, cond = None): 1515 promotedFunctions = getPromotedFunctions(api) if Function.TYPE_DEVICE in functionTypes else None 1516 def makeInitFunctionPointers (): 1517 for function in api.functions: 1518 if function.getType() in functionTypes and (cond == None or cond(function)): 1519 condition = '' 1520 if function.getType() == Function.TYPE_DEVICE: 1521 versionCheck = '' 1522 if function.name in promotedFunctions: 1523 for versionTuple in promotedFunctions[function.name]: 1524 if len(versionCheck) > 0: 1525 versionCheck += ' || ' 1526 versionCheck = 'usedApiVersion >= VK_MAKE_API_VERSION(%s, %s, %s, 0)' % versionTuple 1527 if len(versionCheck) > 0: 1528 condition = f"if ({versionCheck})\n " 1529 interfaceName = getInterfaceName(function.name) 1530 functionTypeName = getFunctionTypeName(function.name) 1531 yield f"{condition}m_vk.{interfaceName} = ({functionTypeName}) GET_PROC_ADDR(\"{function.name}\");" 1532 for alias in function.aliasList: 1533 yield f"if (!m_vk.{interfaceName})" 1534 yield f" m_vk.{interfaceName} = ({functionTypeName}) GET_PROC_ADDR(\"{alias}\");" 1535 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].type == "VkPhysicalDevice": 1536 interfaceName = getInterfaceName(alias) 1537 functionTypeName = getFunctionTypeName(alias) 1538 yield f"m_vk.{interfaceName} = ({functionTypeName}) GET_PROC_ADDR(\"{alias}\");" 1539 1540 lines = makeInitFunctionPointers() 1541 writeInlFile(filename, INL_HEADER, lines) 1542 1543# List pre filled manually with commands forbidden for computation only implementations 1544computeOnlyForbiddenCommands = [ 1545 "destroyRenderPass", 1546 "createRenderPass2", 1547 "createRenderPass", 1548 "createGraphicsPipelines" 1549] 1550 1551computeOnlyRestrictedCommands = { 1552 "createComputePipelines" : "\t\tfor (uint32_t i=0; i<createInfoCount; ++i)\n\t\t\tif ((pCreateInfos[i].stage.stage & VK_SHADER_STAGE_ALL_GRAPHICS) != 0) THROW_NOT_SUPPORTED_COMPUTE_ONLY();", 1553 "createBuffer" : "\t\tif ((pCreateInfo->usage & ( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT )) !=0) THROW_NOT_SUPPORTED_COMPUTE_ONLY();", 1554} 1555 1556def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className): 1557 1558 # populate compute only forbidden commands 1559 for fun in api.functions: 1560 if "graphics" in fun.queuesList and "compute" not in fun.queuesList: 1561 # remove the 'vk' prefix and change the first character of the remaining string to lowercase 1562 commandName = fun.name[2:3].lower() + fun.name[3:] 1563 computeOnlyForbiddenCommands.append(commandName) 1564 1565 # if the command has an alias, also add it 1566 for alias_name in fun.aliasList: 1567 alias_name_without_vk = alias_name[2:3].lower() + alias_name[3:] 1568 computeOnlyForbiddenCommands.append(alias_name_without_vk) 1569 1570 def makeFuncPtrInterfaceImpl (): 1571 for function in api.functions: 1572 if function.getType() in functionTypes: 1573 yield "" 1574 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function.name), argListToStr(function.arguments)) 1575 yield "{" 1576 # Check for compute only forbidden commands 1577 if getInterfaceName(function.name) in computeOnlyForbiddenCommands: 1578 yield " if( m_computeOnlyMode ) THROW_NOT_SUPPORTED_COMPUTE_ONLY();" 1579 # Check for compute only restricted commands 1580 if getInterfaceName(function.name) in computeOnlyRestrictedCommands: 1581 yield "\tif( m_computeOnlyMode )" 1582 yield "\t{" 1583 yield computeOnlyRestrictedCommands[getInterfaceName(function.name)] 1584 yield "\t}" 1585 if function.name == "vkEnumerateInstanceVersion": 1586 yield " if (m_vk.enumerateInstanceVersion)" 1587 yield " return m_vk.enumerateInstanceVersion(pApiVersion);" 1588 yield "" 1589 yield " *pApiVersion = VK_API_VERSION_1_0;" 1590 yield " return VK_SUCCESS;" 1591 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].type == "VkPhysicalDevice" and len(function.aliasList) > 0 and getInterfaceName(function.name) in getInterfaceName(function.aliasList[0]): 1592 yield " vk::VkPhysicalDeviceProperties props;" 1593 yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);" 1594 yield " if (props.apiVersion >= VK_API_VERSION_1_1)" 1595 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.name), ", ".join(a.name for a in function.arguments)) 1596 yield " else" 1597 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.aliasList[0]), ", ".join(a.name for a in function.arguments)) 1598 else: 1599 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.name), ", ".join(a.name for a in function.arguments)) 1600 yield "}" 1601 1602 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl()) 1603 1604def writeFuncPtrInterfaceSCImpl (api, filename, functionTypes, className): 1605 normFuncs = { 1606 "createGraphicsPipelines" : "\t\treturn createGraphicsPipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);", 1607 "createComputePipelines" : "\t\treturn createComputePipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);", 1608 "createSampler" : "\t\treturn createSamplerHandlerNorm(device, pCreateInfo, pAllocator, pSampler);", 1609 "createSamplerYcbcrConversion" : "\t\treturn createSamplerYcbcrConversionHandlerNorm(device, pCreateInfo, pAllocator, pYcbcrConversion);", 1610 "createDescriptorSetLayout" : "\t\treturn createDescriptorSetLayoutHandlerNorm(device, pCreateInfo, pAllocator, pSetLayout);", 1611 "createPipelineLayout" : "\t\treturn createPipelineLayoutHandlerNorm(device, pCreateInfo, pAllocator, pPipelineLayout);", 1612 "createRenderPass" : "\t\treturn createRenderPassHandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);", 1613 "createRenderPass2" : "\t\treturn createRenderPass2HandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);", 1614 "createCommandPool" : "\t\treturn createCommandPoolHandlerNorm(device, pCreateInfo, pAllocator, pCommandPool);", 1615 "resetCommandPool" : "\t\treturn resetCommandPoolHandlerNorm(device, commandPool, flags);", 1616 "createFramebuffer" : "\t\treturn createFramebufferHandlerNorm(device, pCreateInfo, pAllocator, pFramebuffer);", 1617 } 1618 statFuncs = { 1619 "destroyDevice" : "\t\tdestroyDeviceHandler(device, pAllocator);", 1620 "createDescriptorSetLayout" : "\t\tcreateDescriptorSetLayoutHandlerStat(device, pCreateInfo, pAllocator, pSetLayout);", 1621 "destroyDescriptorSetLayout" : "\t\tdestroyDescriptorSetLayoutHandler(device, descriptorSetLayout, pAllocator);", 1622 "createImageView" : "\t\tcreateImageViewHandler(device, pCreateInfo, pAllocator, pView);", 1623 "destroyImageView" : "\t\tdestroyImageViewHandler(device, imageView, pAllocator);", 1624 "createSemaphore" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(semaphoreRequestCount,1);\n\t\t*pSemaphore = Handle<HANDLE_TYPE_SEMAPHORE>(m_resourceInterface->incResourceCounter());\n\t}", 1625 "destroySemaphore" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(semaphore,semaphoreRequestCount,1);\n\t}", 1626 "createFence" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(fenceRequestCount,1);\n\t\t*pFence = Handle<HANDLE_TYPE_FENCE>(m_resourceInterface->incResourceCounter());\n\t}", 1627 "destroyFence" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(fence,fenceRequestCount,1);\n\t}", 1628 "allocateMemory" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(deviceMemoryRequestCount,1);\n\t\t*pMemory = Handle<HANDLE_TYPE_DEVICE_MEMORY>(m_resourceInterface->incResourceCounter());\n\t}", 1629 "createBuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(bufferRequestCount,1);\n\t\t*pBuffer = Handle<HANDLE_TYPE_BUFFER>(m_resourceInterface->incResourceCounter());\n\t}", 1630 "destroyBuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(buffer,bufferRequestCount,1);\n\t}", 1631 "createImage" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(imageRequestCount,1);\n\t\t*pImage = Handle<HANDLE_TYPE_IMAGE>(m_resourceInterface->incResourceCounter());\n\t}", 1632 "destroyImage" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(image,imageRequestCount,1);\n\t}", 1633 "createEvent" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(eventRequestCount,1);\n\t\t*pEvent = Handle<HANDLE_TYPE_EVENT>(m_resourceInterface->incResourceCounter());\n\t}", 1634 "destroyEvent" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(event,eventRequestCount,1);\n\t}", 1635 "createQueryPool" : "\t\tcreateQueryPoolHandler(device, pCreateInfo, pAllocator, pQueryPool);", 1636 "createBufferView" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(bufferViewRequestCount,1);\n\t\t*pView = Handle<HANDLE_TYPE_BUFFER_VIEW>(m_resourceInterface->incResourceCounter());\n\t}", 1637 "destroyBufferView" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(bufferView,bufferViewRequestCount,1);\n\t}", 1638 "createPipelineLayout" : "\t\tcreatePipelineLayoutHandlerStat(device, pCreateInfo, pAllocator, pPipelineLayout);", 1639 "destroyPipelineLayout" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineLayout,pipelineLayoutRequestCount,1);\n\t}", 1640 "createRenderPass" : "\t\tcreateRenderPassHandlerStat(device, pCreateInfo, pAllocator, pRenderPass);", 1641 "createRenderPass2" : "\t\tcreateRenderPass2HandlerStat(device, pCreateInfo, pAllocator, pRenderPass);", 1642 "destroyRenderPass" : "\t\tdestroyRenderPassHandler(device, renderPass, pAllocator);", 1643 "createGraphicsPipelines" : "\t\tcreateGraphicsPipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);", 1644 "createComputePipelines" : "\t\tcreateComputePipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);", 1645 "destroyPipeline" : "\t\tdestroyPipelineHandler(device, pipeline, pAllocator);", 1646 "createSampler" : "\t\tcreateSamplerHandlerStat(device, pCreateInfo, pAllocator, pSampler);", 1647 "destroySampler" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(sampler,samplerRequestCount,1);\n\t}", 1648 "createDescriptorPool" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(descriptorPoolRequestCount,1);\n\t\t*pDescriptorPool = Handle<HANDLE_TYPE_DESCRIPTOR_POOL>(m_resourceInterface->incResourceCounter());\n\t}", 1649 "resetDescriptorPool" : "\t\tresetDescriptorPoolHandlerStat(device, descriptorPool, flags);", 1650 "allocateDescriptorSets" : "\t\tallocateDescriptorSetsHandlerStat(device, pAllocateInfo, pDescriptorSets);", 1651 "freeDescriptorSets" : "\t\tfreeDescriptorSetsHandlerStat(device, descriptorPool, descriptorSetCount, pDescriptorSets);", 1652 "createFramebuffer" : "\t\tcreateFramebufferHandlerStat(device, pCreateInfo, pAllocator, pFramebuffer);", 1653 "destroyFramebuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(framebuffer,framebufferRequestCount,1);\n\t}", 1654 "createCommandPool" : "\t\tcreateCommandPoolHandlerStat(device, pCreateInfo, pAllocator, pCommandPool);", 1655 "resetCommandPool" : "\t\tresetCommandPoolHandlerStat(device, commandPool, flags);", 1656 "allocateCommandBuffers" : "\t\tallocateCommandBuffersHandler(device, pAllocateInfo, pCommandBuffers);", 1657 "freeCommandBuffers" : "\t\tfreeCommandBuffersHandler(device, commandPool, commandBufferCount, pCommandBuffers);", 1658 "createSamplerYcbcrConversion" : "\t\tcreateSamplerYcbcrConversionHandlerStat(device, pCreateInfo, pAllocator, pYcbcrConversion);", 1659 "destroySamplerYcbcrConversion" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(ycbcrConversion,samplerYcbcrConversionRequestCount,1);\n\t}", 1660 "getDescriptorSetLayoutSupport" : "\t\tgetDescriptorSetLayoutSupportHandler(device, pCreateInfo, pSupport);", 1661# "" : "surfaceRequestCount", 1662# "" : "swapchainRequestCount", 1663# "" : "displayModeRequestCount" 1664 "mapMemory" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tif(m_falseMemory.size() < (static_cast<std::size_t>(offset+size)))\n\t\t\tm_falseMemory.resize(static_cast<std::size_t>(offset+size));\n\t\t*ppData = (void*)m_falseMemory.data();\n\t}", 1665 "getBufferMemoryRequirements" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}", 1666 "getImageMemoryRequirements" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}", 1667 "getBufferMemoryRequirements2" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->memoryRequirements.size = 1048576U;\n\t\tpMemoryRequirements->memoryRequirements.alignment = 1U;\n\t\tpMemoryRequirements->memoryRequirements.memoryTypeBits = ~0U;\n\t}", 1668 "getImageMemoryRequirements2" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->memoryRequirements.size = 1048576U;\n\t\tpMemoryRequirements->memoryRequirements.alignment = 1U;\n\t\tpMemoryRequirements->memoryRequirements.memoryTypeBits = ~0U;\n\t}", 1669 "getImageSubresourceLayout" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpLayout->offset = 0U;\n\t\tpLayout->size = 1048576U;\n\t\tpLayout->rowPitch = 0U;\n\t\tpLayout->arrayPitch = 0U;\n\t\tpLayout->depthPitch = 0U;\n\t}", 1670 "createPipelineCache" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(pipelineCacheRequestCount,1);\n\t\t*pPipelineCache = Handle<HANDLE_TYPE_PIPELINE_CACHE>(m_resourceInterface->incResourceCounter());\n\t}", 1671 "destroyPipelineCache" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineCache,pipelineCacheRequestCount,1);\n\t}", 1672 "cmdUpdateBuffer" : "\t\tincreaseCommandBufferSize(commandBuffer, dataSize);", 1673 "getDeviceQueue" : "\t\tm_vk.getDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);", 1674 } 1675 1676 statReturns = { 1677 "VkResult" : "return VK_SUCCESS;", 1678 "VkDeviceAddress" : "return 0u;", 1679 "uint64_t" : "return 0u;", 1680 } 1681 1682 def makeFuncPtrInterfaceStatisticsImpl (): 1683 for function in api.functions: 1684 if function.getType() in functionTypes: 1685 ifaceName = getInterfaceName(function.name) 1686 yield "" 1687 yield "%s %s::%s (%s) const" % (function.returnType, className, ifaceName, argListToStr(function.arguments)) 1688 yield "{" 1689 # Check for compute only forbidden commands 1690 if ifaceName in computeOnlyForbiddenCommands: 1691 yield "\tif( m_computeOnlyMode ) THROW_NOT_SUPPORTED_COMPUTE_ONLY();" 1692 # Check for compute only restricted commands 1693 if ifaceName in computeOnlyRestrictedCommands: 1694 yield "\tif( m_computeOnlyMode )" 1695 yield "\t{" 1696 yield computeOnlyRestrictedCommands[ifaceName] 1697 yield "\t}" 1698 if ( ifaceName in normFuncs ) or ( ifaceName in statFuncs ): 1699 yield "\tstd::lock_guard<std::mutex> lock(functionMutex);" 1700 if ifaceName != "getDeviceProcAddr" : 1701 yield "\tif (m_normalMode)" 1702 if ifaceName in normFuncs : 1703 yield "%s" % ( normFuncs[ifaceName] ) 1704 else: 1705 yield "\t\t%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", ifaceName, ", ".join(a.name for a in function.arguments)) 1706 if ifaceName in statFuncs : 1707 yield "\telse" 1708 yield "%s" % ( statFuncs[ifaceName] ) 1709 elif ifaceName[:3] == "cmd" : 1710 yield "\telse" 1711 yield "\t\tincreaseCommandBufferSize(commandBuffer, 0u);" 1712 if function.returnType in statReturns: 1713 yield "\t%s" % ( statReturns[function.returnType] ) 1714 yield "}" 1715 1716 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceStatisticsImpl()) 1717 1718def writeStrUtilProto (api, filename): 1719 def makeStrUtilProto (): 1720 for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums if enum.type == "enum"]): 1721 yield line 1722 yield "" 1723 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 e.type == "enum"]): 1724 yield line 1725 yield "" 1726 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 e.type == "enum"]): 1727 yield line 1728 yield "" 1729 for line in indentLines(["tcu::Format::Bitfield<%s>\tget%sStr\t(%s value);" % (("64" if b.type == "VkFlags64" else "32"), b.name[2:], b.name) for b in api.bitmasks]): 1730 yield line 1731 yield "" 1732 for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes]): 1733 yield line 1734 1735 writeInlFile(filename, INL_HEADER, makeStrUtilProto()) 1736 1737def writeStrUtilImpl (api, filename): 1738 def makeStrUtilImpl (): 1739 for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles]): 1740 yield line 1741 1742 yield "" 1743 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE 1744 yield "{" 1745 1746 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): 1747 yield line 1748 1749 yield "}" 1750 1751 savedBitmasks = [] 1752 for enum in api.enums: 1753 if enum.type == "enum": 1754 yield "" 1755 yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name) 1756 yield "{" 1757 yield "\tswitch (value)" 1758 yield "\t{" 1759 enumValues = [] 1760 lastValue = 0x7FFFFFFF 1761 for e in enum.enumeratorList: 1762 enumValues.append(f"\t\tcase {e.name}:\treturn \"{e.name}\";") 1763 enumValues.append("\t\tdefault:\treturn DE_NULL;") 1764 for line in indentLines(enumValues): 1765 yield line 1766 yield "\t}" 1767 yield "}" 1768 elif enum.type == "bitmask": 1769 # find bitfield that uses those bitmasks 1770 foundBitmask = None 1771 for bitmask in api.bitmasks: 1772 if bitmask.requires == enum.name or bitmask.bitvalues == enum.name: 1773 foundBitmask = bitmask 1774 break 1775 if foundBitmask == None: 1776 continue 1777 savedBitmasks.append(foundBitmask.name) 1778 bitSize = "64" if foundBitmask.type == "VkFlags64" else "32" 1779 yield "" 1780 yield f"tcu::Format::Bitfield<{bitSize}> get{bitmask.name[2:]}Str ({bitmask.name} value)" 1781 yield "{" 1782 yield "\tstatic const tcu::Format::BitDesc s_desc[] =" 1783 yield "\t{" 1784 if len(enum.enumeratorList) == 0: 1785 # some bitfields in SC have no items 1786 yield f"\t\ttcu::Format::BitDesc(0, \"0\")" 1787 else: 1788 for line in indentLines([f"\t\ttcu::Format::BitDesc({e.name},\t\"{e.name}\")," for e in enum.enumeratorList]): 1789 yield line 1790 yield "\t};" 1791 yield f"\treturn tcu::Format::Bitfield<{bitSize}>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));" 1792 yield "}" 1793 1794 for bitmask in api.bitmasks: 1795 if bitmask.name not in savedBitmasks: 1796 bitSize = "64" if bitmask.type == "VkFlags64" else "32" 1797 yield "" 1798 yield f"tcu::Format::Bitfield<{bitSize}> get{bitmask.name[2:]}Str ({bitmask.name} value)" 1799 yield "{" 1800 yield f"\treturn tcu::Format::Bitfield<{bitSize}>(value, DE_NULL, DE_NULL);" 1801 yield "}" 1802 1803 bitfieldTypeNames = set([bitmask.name for bitmask in api.bitmasks]) 1804 1805 for type in api.compositeTypes: 1806 yield "" 1807 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name 1808 yield "{" 1809 yield "\ts << \"%s = {\\n\";" % type.name 1810 for member in type.members: 1811 memberName = member.name 1812 valFmt = None 1813 newLine = "" 1814 if member.type in bitfieldTypeNames: 1815 operator = '*' if member.pointer == '*' else '' 1816 valFmt = "get%sStr(%svalue.%s)" % (member.type[2:], operator, member.name) 1817 elif member.type == "char" and member.pointer == '*': 1818 valFmt = "getCharPtrStr(value.%s)" % member.name 1819 elif member.type == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR": 1820 valFmt = "getWStr(value.%s)" % member.name 1821 elif len(member.arraySizeList) == 1: 1822 if member.name in ["extensionName", "deviceName", "layerName", "description"]: 1823 valFmt = "(const char*)value.%s" % member.name 1824 elif member.type == 'char' or member.type == 'uint8_t': 1825 newLine = "'\\n' << " 1826 valFmt = "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.type, member.name, member.type, member.name) 1827 else: 1828 if member.name == "memoryTypes" or member.name == "memoryHeaps": 1829 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1]) 1830 else: 1831 endIter = "DE_ARRAY_END(value.%s)" % member.name 1832 newLine = "'\\n' << " 1833 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter) 1834 memberName = member.name 1835 elif len(member.arraySizeList) > 1: 1836 yield f"\ts << \"\\t{member.name} = \" << '\\n';" 1837 dim = 0 1838 index = '' 1839 dimensionCount = len(member.arraySizeList) 1840 while dim < dimensionCount-1: 1841 yield f"\tfor(uint32_t i{dim} = 0 ; i{dim} < {member.arraySizeList[dim]} ; ++i{dim})" 1842 index += f"[i{dim}]" 1843 dim +=1 1844 yield f"\t\ts << tcu::formatArray(DE_ARRAY_BEGIN(value.{member.name}{index}), DE_ARRAY_END(value.{member.name}{index})) << '\\n';" 1845 # move to next member 1846 continue 1847 else: 1848 valFmt = "value.%s" % member.name 1849 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';" 1850 yield "\ts << '}';" 1851 yield "\treturn s;" 1852 yield "}" 1853 writeInlFile(filename, INL_HEADER, makeStrUtilImpl()) 1854 1855def writeObjTypeImpl (api, filename): 1856 def makeObjTypeImpl (): 1857 1858 yield "namespace vk" 1859 yield "{" 1860 1861 yield "template<typename T> VkObjectType getObjectType (void);" 1862 1863 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]): 1864 yield line 1865 1866 yield "}" 1867 1868 writeInlFile(filename, INL_HEADER, makeObjTypeImpl()) 1869 1870class ConstructorFunction: 1871 def __init__ (self, type, name, objectType, ifaceArgs, arguments): 1872 self.type = type 1873 self.name = name 1874 self.objectType = objectType 1875 self.ifaceArgs = ifaceArgs 1876 self.arguments = arguments 1877 1878def getConstructorFunctions (api): 1879 funcs = [] 1880 1881 ifacesDict = { 1882 Function.TYPE_PLATFORM: [FunctionArgument("vk", "const ", "PlatformInterface&")], 1883 Function.TYPE_INSTANCE: [FunctionArgument("vk", "const ", "InstanceInterface&")], 1884 Function.TYPE_DEVICE: [FunctionArgument("vk", "const ", "DeviceInterface&")]} 1885 1886 for function in api.functions: 1887 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]: 1888 if function.name == "vkCreateDisplayModeKHR": 1889 continue # No way to delete display modes (bug?) 1890 1891 ifaceArgs = [] 1892 if function.name == "vkCreateDevice": 1893 ifaceArgs = [FunctionArgument("vkp", "const ", "PlatformInterface&"), 1894 FunctionArgument("instance", "", "VkInstance")] 1895 ifaceArgs.extend(ifacesDict[function.getType()]) 1896 1897 assert (function.arguments[-2].type == "VkAllocationCallbacks" and \ 1898 "const" in function.arguments[-2].qualifiers and \ 1899 function.arguments[-2].pointer == "*") 1900 1901 objectType = function.arguments[-1].type 1902 arguments = function.arguments[:-1] 1903 funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function.name), objectType, ifaceArgs, arguments)) 1904 return funcs 1905 1906def addVersionDefines(versionSpectrum): 1907 output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()] 1908 return output 1909 1910def writeRefUtilProto (api, filename): 1911 functions = getConstructorFunctions(api) 1912 1913 def makeRefUtilProto (): 1914 unindented = [] 1915 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]): 1916 yield line 1917 1918 writeInlFile(filename, INL_HEADER, makeRefUtilProto()) 1919 1920def writeRefUtilImpl (api, filename): 1921 functions = getConstructorFunctions(api) 1922 1923 def makeRefUtilImpl (): 1924 yield "namespace refdetails" 1925 yield "{" 1926 yield "" 1927 1928 for function in api.functions: 1929 if function.getType() == Function.TYPE_DEVICE \ 1930 and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \ 1931 and not function.name == "vkDestroyDevice": 1932 objectType = function.arguments[-2].type 1933 yield "template<>" 1934 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType) 1935 yield "{" 1936 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function.name)) 1937 yield "}" 1938 yield "" 1939 1940 yield "} // refdetails" 1941 yield "" 1942 1943 dtorDict = { 1944 Function.TYPE_PLATFORM: "object", 1945 Function.TYPE_INSTANCE: "instance", 1946 Function.TYPE_DEVICE: "device" 1947 } 1948 1949 for function in functions: 1950 deleterArgsString = '' 1951 if function.name == "createDevice": 1952 # createDevice requires two additional parameters to setup VkDevice deleter 1953 deleterArgsString = "vkp, instance, object, " + function.arguments[-1].name 1954 else: 1955 deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name) 1956 1957 yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments)) 1958 yield "{" 1959 yield "\t%s object = VK_NULL_HANDLE;" % function.objectType 1960 yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"])) 1961 yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString) 1962 yield "}" 1963 yield "" 1964 1965 writeInlFile(filename, INL_HEADER, makeRefUtilImpl()) 1966 1967def writeStructTraitsImpl (api, filename): 1968 def gen (): 1969 for cType in api.compositeTypes: 1970 if cType.category == "struct" and cType.members[0].name == "sType" and cType.name != "VkBaseOutStructure" and cType.name != "VkBaseInStructure": 1971 yield "template<> VkStructureType getStructureType<%s> (void)" % cType.name 1972 yield "{" 1973 yield "\treturn %s;" % cType.members[0].values 1974 yield "}" 1975 yield "" 1976 1977 writeInlFile(filename, INL_HEADER, gen()) 1978 1979def writeNullDriverImpl (api, filename): 1980 def genNullDriverImpl (): 1981 specialFuncNames = [ 1982 "vkCreateGraphicsPipelines", 1983 "vkCreateComputePipelines", 1984 "vkCreateRayTracingPipelinesNV", 1985 "vkCreateRayTracingPipelinesKHR", 1986 "vkGetInstanceProcAddr", 1987 "vkGetDeviceProcAddr", 1988 "vkEnumeratePhysicalDevices", 1989 "vkEnumerateInstanceExtensionProperties", 1990 "vkEnumerateDeviceExtensionProperties", 1991 "vkGetPhysicalDeviceFeatures", 1992 "vkGetPhysicalDeviceFeatures2KHR", 1993 "vkGetPhysicalDeviceProperties", 1994 "vkGetPhysicalDeviceProperties2KHR", 1995 "vkGetPhysicalDeviceQueueFamilyProperties", 1996 "vkGetPhysicalDeviceMemoryProperties", 1997 "vkGetPhysicalDeviceFormatProperties", 1998 "vkGetPhysicalDeviceImageFormatProperties", 1999 "vkGetDeviceQueue", 2000 "vkGetBufferMemoryRequirements", 2001 "vkGetBufferMemoryRequirements2KHR", 2002 "vkGetImageMemoryRequirements", 2003 "vkGetImageMemoryRequirements2KHR", 2004 "vkAllocateMemory", 2005 "vkMapMemory", 2006 "vkUnmapMemory", 2007 "vkAllocateDescriptorSets", 2008 "vkFreeDescriptorSets", 2009 "vkResetDescriptorPool", 2010 "vkAllocateCommandBuffers", 2011 "vkFreeCommandBuffers", 2012 "vkCreateDisplayModeKHR", 2013 "vkCreateSharedSwapchainsKHR", 2014 "vkGetPhysicalDeviceExternalBufferPropertiesKHR", 2015 "vkGetPhysicalDeviceImageFormatProperties2KHR", 2016 "vkGetMemoryAndroidHardwareBufferANDROID", 2017 "vkCreateShadersEXT", 2018 ] 2019 2020 specialFuncs = [f for f in api.functions if f.name in specialFuncNames] 2021 createFuncs = [f for f in api.functions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs] 2022 destroyFuncs = [f for f in api.functions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs] 2023 dummyFuncs = [f for f in api.functions if f not in specialFuncs + createFuncs + destroyFuncs] 2024 2025 def getHandle (name): 2026 for handle in api.handles: 2027 if handle.name == name: 2028 return handle 2029 raise Exception("No such handle: %s" % name) 2030 2031 for function in createFuncs: 2032 objectType = function.arguments[-1].type 2033 argsStr = ", ".join([a.name for a in function.arguments[:-1]]) 2034 2035 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments)) 2036 yield "{" 2037 yield "\tDE_UNREF(%s);" % function.arguments[-2].name 2038 2039 if function.arguments[-1].len != None: 2040 yield "\tVK_NULL_RETURN((allocateNonDispHandleArray<%s, %s>(%s, %s)));" % (objectType[2:], objectType, argsStr, function.arguments[-1].name) 2041 else: 2042 if getHandle(objectType).type == "VK_DEFINE_NON_DISPATCHABLE_HANDLE": 2043 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr) 2044 else: 2045 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr) 2046 yield "}" 2047 yield "" 2048 2049 for function in destroyFuncs: 2050 objectArg = function.arguments[-2] 2051 2052 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments)) 2053 yield "{" 2054 for arg in function.arguments[:-2]: 2055 yield "\tDE_UNREF(%s);" % arg.name 2056 2057 if getHandle(objectArg.type).type == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE': 2058 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name) 2059 else: 2060 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name) 2061 2062 yield "}" 2063 yield "" 2064 2065 for function in dummyFuncs: 2066 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments)) 2067 yield "{" 2068 for arg in function.arguments: 2069 yield "\tDE_UNREF(%s);" % arg.name 2070 if function.returnType != "void": 2071 yield "\treturn VK_SUCCESS;" 2072 yield "}" 2073 yield "" 2074 2075 def genFuncEntryTable (type, name): 2076 2077 entries = [] 2078 pattern = "\tVK_NULL_FUNC_ENTRY(%s,\t%s)," 2079 for f in api.functions: 2080 if f.getType() != type: 2081 continue 2082 entries.append(pattern % (f.name, getInterfaceName(f.name))) 2083 2084 yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name 2085 yield "{" 2086 2087 for line in indentLines(entries): 2088 yield line 2089 yield "};" 2090 yield "" 2091 2092 # Func tables 2093 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"): 2094 yield line 2095 2096 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"): 2097 yield line 2098 2099 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"): 2100 yield line 2101 2102 writeInlFile(filename, INL_HEADER, genNullDriverImpl()) 2103 2104def writeTypeUtil (api, filename): 2105 # Structs filled by API queries are not often used in test code 2106 QUERY_RESULT_TYPES = set([ 2107 "VkPhysicalDeviceFeatures", 2108 "VkPhysicalDeviceLimits", 2109 "VkFormatProperties", 2110 "VkImageFormatProperties", 2111 "VkPhysicalDeviceSparseProperties", 2112 "VkQueueFamilyProperties", 2113 "VkMemoryType", 2114 "VkMemoryHeap", 2115 "StdVideoH264SpsVuiFlags", 2116 "StdVideoH264SpsFlags", 2117 "StdVideoH264PpsFlags", 2118 "StdVideoDecodeH264PictureInfoFlags", 2119 "StdVideoDecodeH264ReferenceInfoFlags", 2120 "StdVideoEncodeH264SliceHeaderFlags", 2121 "StdVideoEncodeH264PictureInfoFlags", 2122 "StdVideoEncodeH264ReferenceInfoFlags", 2123 "StdVideoEncodeH264ReferenceInfoFlags", 2124 "StdVideoH265HrdFlags", 2125 "StdVideoH265VpsFlags", 2126 "StdVideoH265SpsVuiFlags", 2127 "StdVideoH265SpsFlags", 2128 "StdVideoH265PpsFlags", 2129 "StdVideoDecodeH265PictureInfoFlags", 2130 "StdVideoDecodeH265ReferenceInfoFlags", 2131 "StdVideoEncodeH265PictureInfoFlags", 2132 "StdVideoEncodeH265ReferenceInfoFlags", 2133 "StdVideoEncodeH265SliceSegmentHeaderFlags", 2134 "StdVideoH265ProfileTierLevelFlags", 2135 "StdVideoH265ShortTermRefPicSetFlags", 2136 "StdVideoEncodeH264ReferenceListsInfoFlags", 2137 "StdVideoEncodeH265ReferenceListsInfoFlags", 2138 ]) 2139 2140 def isSimpleStruct (type): 2141 def hasArrayMember (type): 2142 for member in type.members: 2143 if len(member.arraySizeList) > 0: 2144 return True 2145 return False 2146 2147 def hasCompositeMember (type): 2148 for member in type.members: 2149 if member.pointer is not None and '*' not in member.pointer: 2150 match = [c for c in api.compositeTypes if member.type == c.name] 2151 if len(match) > 0: 2152 return True 2153 return False 2154 2155 return type.category == "struct" and \ 2156 type.members[0].type != "VkStructureType" and \ 2157 not type.name in QUERY_RESULT_TYPES and \ 2158 not hasArrayMember(type) and \ 2159 not hasCompositeMember(type) 2160 2161 def gen (): 2162 for type in api.compositeTypes: 2163 if not isSimpleStruct(type): 2164 continue 2165 2166 if "StdVideoAV1" in type.name or "StdVideoDecodeAV1" in type.name: 2167 continue 2168 2169 name = type.name[2:] if type.name[:2].lower() == "vk" else type.name 2170 2171 yield "" 2172 yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members)) 2173 yield "{" 2174 yield "\t%s res;" % type.name 2175 for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]): 2176 yield line 2177 yield "\treturn res;" 2178 yield "}" 2179 2180 writeInlFile(filename, INL_HEADER, gen()) 2181 2182def writeDriverIds(api, filename): 2183 driverIdsString = [] 2184 driverIdsString.append("static const struct\n" 2185 "{\n" 2186 "\tstd::string driver;\n" 2187 "\tuint32_t id;\n" 2188 "} driverIds [] =\n" 2189 "{") 2190 driverItems = dict() 2191 driverIdEnum = [enum for enum in api.enums if enum.name == 'VkDriverId'][0] 2192 for enumerator in driverIdEnum.enumeratorList: 2193 driverIdsString.append(f"\t{{\"{enumerator.name}\", {enumerator.value}}},") 2194 driverItems[enumerator.name] = enumerator.value 2195 for enumerator in driverIdEnum.enumeratorList: 2196 if len(enumerator.aliasList) > 0: 2197 driverIdsString.append(f"\t{{\"{enumerator.aliasList[0]}\", {enumerator.value}}},\t// {enumerator.name}") 2198 driverIdsString.append("\t{\"VK_DRIVER_ID_MAX_ENUM\", 0x7FFFFFFF}") 2199 driverIdsString.append("};") 2200 2201 writeInlFile(filename, INL_HEADER, driverIdsString) 2202 2203def writeSupportedExtensions(api, filename): 2204 2205 def writeExtensionsForVersions(map): 2206 result = [] 2207 for version in map: 2208 result.append(" if (coreVersion >= " + str(version) + ")") 2209 result.append(" {") 2210 for extension in map[version]: 2211 result.append(' dst.push_back("' + extension.name + '");') 2212 result.append(" }") 2213 2214 if not map: 2215 result.append(" DE_UNREF(coreVersion);") 2216 2217 return result 2218 2219 isSC = api.apiName == 'vulkansc' 2220 instanceMap = {} 2221 deviceMap = {} 2222 2223 for ext in api.extensions: 2224 if ext.promotedto is None or "VK_VERSION" not in ext.promotedto: 2225 continue 2226 # skip partialy promoted extensions 2227 if ext.partiallyPromoted is True: 2228 continue 2229 major = int(ext.promotedto[-3]) 2230 minor = int(ext.promotedto[-1]) 2231 currVersion = "VK_API_VERSION_" + ext.promotedto[-3:] 2232 # VulkanSC is based on Vulkan 1.2. Any Vulkan version greater than 1.2 should be excluded 2233 if isSC and major==1 and minor>2: 2234 continue 2235 if ext.type == 'instance': 2236 list = instanceMap.get(currVersion) 2237 instanceMap[currVersion] = list + [ext] if list else [ext] 2238 else: 2239 list = deviceMap.get(currVersion) 2240 deviceMap[currVersion] = list + [ext] if list else [ext] 2241 2242 # add list of extensions missing in Vulkan SC specification 2243 if isSC: 2244 for extensionName, data in api.additionalExtensionData: 2245 # make sure that this extension was registered 2246 if 'register_extension' not in data.keys(): 2247 continue 2248 # save array containing 'device' or 'instance' string followed by the optional vulkan version in which this extension is core; 2249 # note that register_extension section is also required for partialy promoted extensions like VK_EXT_extended_dynamic_state2 2250 # but those extensions should not fill 'core' tag 2251 match = re.match("(\d).(\d).(\d).(\d)", data['register_extension']['core']) 2252 if match == None: 2253 continue 2254 major = int(match.group(2)) 2255 minor = int(match.group(3)) 2256 if major==1 and minor>2: 2257 continue 2258 currVersion = f"VK_API_VERSION_{major}_{minor}" 2259 ext = Extension(extensionName, 0, 0, 0, 0, 0, 0, 0) 2260 if data['register_extension']['type'] == 'instance': 2261 list = instanceMap.get(currVersion) 2262 instanceMap[currVersion] = list + [ext] if list else [ext] 2263 else: 2264 list = deviceMap.get(currVersion) 2265 deviceMap[currVersion] = list + [ext] if list else [ext] 2266 2267 lines = [ 2268 "", 2269 "void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 or isSC else ""), 2270 "{"] + writeExtensionsForVersions(deviceMap) + [ 2271 "}", 2272 "", 2273 "void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 or isSC else ""), 2274 "{"] + writeExtensionsForVersions(instanceMap) + [ 2275 "}", 2276 ""] 2277 writeInlFile(filename, INL_HEADER, lines) 2278 2279 2280def writeExtensionFunctions (api, filename): 2281 2282 def writeExtensionNameArrays (): 2283 instanceExtensionNames = [f"\t\"{ext.name}\"," for ext in api.extensions if ext.type == "instance"] 2284 deviceExtensionNames = [f"\t\"{ext.name}\"," for ext in api.extensions if ext.type == "device"] 2285 yield '::std::string instanceExtensionNames[] =\n{' 2286 for instanceExtName in instanceExtensionNames: 2287 yield instanceExtName 2288 yield '};\n' 2289 yield '::std::string deviceExtensionNames[] =\n{' 2290 for deviceExtName in deviceExtensionNames: 2291 yield deviceExtName 2292 yield '};' 2293 2294 def writeExtensionFunctions (functionType): 2295 isFirstWrite = True 2296 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 2297 if functionType == Function.TYPE_INSTANCE: 2298 yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, const std::vector<std::string> vIEP, const std::vector<std::string> vDEP, const std::string extName, ::std::vector<const char*>& functions)\n{' 2299 yield '\t(void)vIEP;\n(void)vDEP;' 2300 dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"] 2301 elif functionType == Function.TYPE_DEVICE: 2302 yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, const std::vector<std::string> vIEP, const std::vector<std::string> vDEP, const std::string extName, ::std::vector<const char*>& functions)\n{' 2303 yield '\t(void)vIEP;\n(void)vDEP;' 2304 dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"] 2305 for ext in api.extensions: 2306 parsedRequirements = [] 2307 for requirement in ext.requirementsList: 2308 funcNames = [] 2309 for requiredCommand in requirement.newCommands: 2310 commandName = requiredCommand.name 2311 # find function that has specified name 2312 func = None 2313 funcList = [f for f in api.functions if f.name == commandName] 2314 # if name was not found check if this is alias 2315 if len(funcList) == 0: 2316 for f in api.functions: 2317 for aliasName in f.aliasList: 2318 if aliasName == commandName: 2319 func = f 2320 break 2321 if func: 2322 break 2323 else: 2324 func = funcList[0] 2325 if func == None: 2326 if api.apiName == "vulkansc": 2327 continue 2328 # something went wrong, for "vulkan" func should always be found 2329 logging.error("%s in %s not valid" % (commandName, ext.name)) 2330 assert(False) 2331 if func.getType() == functionType: 2332 funcNames.append(commandName) 2333 condition = None 2334 if requirement.depends is not None: 2335 try: 2336 condition = transformDependsToCondition(requirement.depends, api, 'checkVersion(%s, %s, apiVersion)', 'extensionIsSupported(%s, "%s")') 2337 except Exception as e: 2338 if api.apiName != "vulkansc": 2339 raise e 2340 parsedRequirements.append((requirement.depends, condition, funcNames)) 2341 if ext.name: 2342 yield '\tif (extName == "%s")' % ext.name 2343 yield '\t{' 2344 for depends, condition, funcNames in parsedRequirements: 2345 if len(funcNames) == 0: 2346 continue 2347 indent = '\t\t' 2348 if depends is not None: 2349 yield '\t\t// Dependencies: %s' % depends 2350 yield '\t\tif (%s) {' % condition 2351 indent = '\t\t\t' 2352 for funcName in funcNames: 2353 if funcName in dg_list: 2354 yield '%sif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % (indent, funcName) 2355 else: 2356 yield '%sfunctions.push_back("%s");' % (indent, funcName) 2357 if depends is not None: 2358 yield '\t\t}' 2359 if ext.name == "VK_KHR_device_group": 2360 for dg_func in dg_list: 2361 yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func 2362 yield '\t\treturn;' 2363 yield '\t}' 2364 isFirstWrite = False 2365 if not isFirstWrite: 2366 yield '\tDE_FATAL("Extension name not found");' 2367 yield '}' 2368 2369 def genHelperFunctions(): 2370 yield 'bool checkVersion(uint32_t major, uint32_t minor, const uint32_t testedApiVersion)' 2371 yield '{' 2372 yield '\tuint32_t testedMajor = VK_API_VERSION_MAJOR(testedApiVersion);' 2373 yield '\tuint32_t testedMinor = VK_API_VERSION_MINOR(testedApiVersion);' 2374 yield '\t// return true when tested api version is greater' 2375 yield '\t// or equal to version represented by two uints' 2376 yield '\tif (major == testedMajor)' 2377 yield '\t\treturn minor <= testedMinor;' 2378 yield '\treturn major < testedMajor;' 2379 yield '}\n' 2380 yield 'bool extensionIsSupported(const std::vector<std::string> extNames, const std::string& ext)' 2381 yield '{' 2382 yield '\tfor (const std::string& supportedExtension : extNames)' 2383 yield '\t{' 2384 yield '\t\tif (supportedExtension == ext) return true;' 2385 yield '\t}' 2386 yield '\treturn false;' 2387 yield '}\n' 2388 2389 lines = [''] 2390 lines.extend(genHelperFunctions()) 2391 for line in writeExtensionFunctions(Function.TYPE_INSTANCE): 2392 lines += [line] 2393 lines += [''] 2394 for line in writeExtensionFunctions(Function.TYPE_DEVICE): 2395 lines += [line] 2396 lines += [''] 2397 for line in writeExtensionNameArrays(): 2398 lines += [line] 2399 2400 writeInlFile(filename, INL_HEADER, lines) 2401 2402def writeCoreFunctionalities(api, filename): 2403 functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"] 2404 2405 functionNamesPerApiVersionDict = {} 2406 for feature in api.features: 2407 apiVersion = "VK_API_VERSION_" + feature.number.replace('.', '_') 2408 functionNamesPerApiVersionDict[apiVersion] = [] 2409 for r in feature.requirementsList: 2410 functionNamesPerApiVersionDict[apiVersion].extend(r.commandList) 2411 2412 lines = [ 2413 "", 2414 'enum FunctionOrigin', '{'] + [line for line in indentLines([ 2415 '\t' + functionOriginValues[0] + '\t= 0,', 2416 '\t' + functionOriginValues[1] + ',', 2417 '\t' + functionOriginValues[2]])] + [ 2418 "};", 2419 "", 2420 "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;", 2421 "typedef ::std::vector<FunctionInfo> FunctionInfosList;", 2422 "typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;", 2423 "", 2424 "void initApisMap (ApisMap& apis)", 2425 "{", 2426 " apis.clear();"] + [ 2427 " apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + v + ", FunctionInfosList()));" for v in functionNamesPerApiVersionDict] + [ 2428 ""] 2429 2430 apiVersions = [] 2431 functionLines = [] 2432 for apiVersion in functionNamesPerApiVersionDict: 2433 # iterate over names of functions added with api 2434 for functionName in functionNamesPerApiVersionDict[apiVersion]: 2435 # search for data of this function in all functions list 2436 functionData = None 2437 for f in api.functions: 2438 if functionName == f.name or functionName in f.aliasList: 2439 functionData = f 2440 break 2441 if functionData == None: 2442 if api.apiName == "vulkansc": 2443 continue 2444 # something went wrong, for "vulkan" functionData should always be found 2445 assert(False) 2446 # add line coresponding to this function 2447 functionLines.append('\tapis[{0}].push_back(FunctionInfo("' + functionName + '",\t' + functionOriginValues[functionData.getType()] + '));') 2448 # functions for every api version should also include all functions from previous versions 2449 specializedLines = [line.format(apiVersion) for line in functionLines] 2450 # indent all functions of specified api and add them to main list 2451 lines = lines + [line for line in indentLines(specializedLines)] + [""] 2452 2453 lines = lines + ["}"] 2454 writeInlFile(filename, INL_HEADER, lines) 2455 2456def camelToSnake(name): 2457 name = re.sub('([a-z])([23])D([A-Z])', r'\1_\2d\3', name) 2458 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) 2459 return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower() 2460 2461def writeDeviceFeatures2(api, filename): 2462 2463 def structInAPI(compositeObject): 2464 for c in api.compositeTypes: 2465 if c.name == compositeObject.name: 2466 return True 2467 return False 2468 2469 # helper class used to encapsulate all data needed during generation 2470 class StructureDetail: 2471 def __init__ (self, compositeObject): 2472 self.nameList = [compositeObject.name] + compositeObject.aliasList 2473 self.sType = compositeObject.members[0].values 2474 self.instanceName = 'd' + compositeObject.name[11:] 2475 self.flagName = 'is' + compositeObject.name[16:] 2476 self.extension = None 2477 self.api = None 2478 self.major = None 2479 self.minor = None 2480 structureMembers = compositeObject.members[2:] 2481 self.members = [m.name for m in structureMembers] 2482 2483 # helper extension class used in algorith below 2484 class StructureFoundContinueToNextOne(Exception): 2485 pass 2486 2487 # find structures that extend VkPhysicalDeviceFeatures2 2488 structures = [c for c in api.compositeTypes if c.structextends is not None and 'VkPhysicalDeviceFeatures2' in c.structextends] 2489 # remove structures that were added by extensions other than KHR and EXT 2490 testedStructures = [] 2491 for s in structures: 2492 if all([postfix not in s.name for postfix in EXTENSION_POSTFIXES_VENDOR]): 2493 testedStructures.append(s) 2494 2495 existingStructures = list(filter(structInAPI, testedStructures)) # remove features not found in API ( important for Vulkan SC ) 2496 testedStructureDetail = [StructureDetail(struct) for struct in existingStructures] 2497 # iterate over all searched structures and find extensions that enabled them 2498 for structureDetail in testedStructureDetail: 2499 try: 2500 # iterate over all extensions 2501 for extension in api.extensions: 2502 for requirement in extension.requirementsList: 2503 for extensionStructure in requirement.newTypes: 2504 if extensionStructure.name in structureDetail.nameList: 2505 structureDetail.extension = extension.name 2506 if extension.promotedto is not None and extension.partiallyPromoted is False: 2507 # check if extension was promoted to vulkan version or other extension 2508 if 'VK_VERSION' in extension.promotedto: 2509 versionSplit = extension.promotedto.split('_') 2510 structureDetail.api = 0 if api.apiName == "vulkan" else 1 2511 structureDetail.major = versionSplit[-2] 2512 structureDetail.minor = versionSplit[-1] 2513 else: 2514 structureDetail.extension = extension.promotedto 2515 raise StructureFoundContinueToNextOne 2516 except StructureFoundContinueToNextOne: 2517 continue 2518 structureDetailToRemove = [] 2519 for structureDetail in testedStructureDetail: 2520 if structureDetail.major is not None: 2521 continue 2522 # if structure was not added with extension then check if 2523 # it was added directly with one of vulkan versions 2524 structureName = structureDetail.nameList[0] 2525 for feature in api.features: 2526 for requirement in feature.requirementsList: 2527 if structureName in requirement.typeList: 2528 if api.apiName == "vulkansc" and int(feature.number[-1]) > 2: 2529 structureDetailToRemove.append(structureDetail) 2530 else: 2531 versionSplit = feature.name.split('_') 2532 structureDetail.api = 0 if api.apiName == "vulkan" else 1 2533 structureDetail.major = versionSplit[-2] 2534 structureDetail.minor = versionSplit[-1] 2535 break 2536 if structureDetail.major is not None: 2537 break 2538 # remove structures that should not be tested for given api version 2539 for sd in structureDetailToRemove: 2540 testedStructureDetail.remove(sd) 2541 # generate file content 2542 structureDefinitions = [] 2543 featureEnabledFlags = [] 2544 clearStructures = [] 2545 structureChain = [] 2546 logStructures = [] 2547 verifyStructures = [] 2548 for index, structureDetail in enumerate(testedStructureDetail): 2549 structureName = structureDetail.nameList[0] 2550 # create two instances of each structure 2551 nameSpacing = '\t' 2552 structureDefinitions.append(structureName + nameSpacing + structureDetail.instanceName + '[count];') 2553 # create flags that check if proper extension or vulkan version is available 2554 condition = '' 2555 extension = structureDetail.extension 2556 major = structureDetail.major 2557 if extension is not None: 2558 condition = ' checkExtension(properties, "' + extension + '")' 2559 if major is not None: 2560 condition = ' ' if condition == '' else condition + ' || ' 2561 condition += 'context.contextSupports(vk::ApiVersion(' + str(structureDetail.api) + ', ' + str(major) + ', ' + str(structureDetail.minor) + ', 0))' 2562 if condition == '': 2563 condition = ' true' 2564 condition += ';' 2565 nameSpacing = '\t' * int((len(structureName) - 4) / 4) 2566 featureEnabledFlags.append('const bool' + nameSpacing + structureDetail.flagName + ' =' + condition) 2567 # clear memory of each structure 2568 clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx], 0xFF * ndx, sizeof(' + structureName + '));') 2569 # construct structure chain 2570 nextInstanceName = 'DE_NULL'; 2571 if index < len(testedStructureDetail)-1: 2572 nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]' 2573 structureChain.append([ 2574 '\t\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.flagName + ' ? ' + structureDetail.sType + ' : VK_STRUCTURE_TYPE_MAX_ENUM;', 2575 '\t\t' + structureDetail.instanceName + '[ndx].pNext = DE_NULL;']) 2576 # construct log section 2577 logStructures.append([ 2578 '\tif (' + structureDetail.flagName + ')', 2579 '\t\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;' 2580 ]) 2581 #construct verification section 2582 verifyStructure = [] 2583 verifyStructure.append('\tif (' + structureDetail.flagName + ' &&') 2584 for index, m in enumerate(structureDetail.members): 2585 prefix = '\t\t(' if index == 0 else '\t\t ' 2586 postfix = '))' if index == len(structureDetail.members)-1 else ' ||' 2587 verifyStructure.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix) 2588 if len(structureDetail.members) == 0: 2589 verifyStructure.append('\t\tfalse)') 2590 verifyStructure.append('\t{\n\t\tTCU_FAIL("Mismatch between ' + structureName + '");\n\t}') 2591 verifyStructures.append(verifyStructure) 2592 2593 # construct file content 2594 stream = [] 2595 2596 # individual test functions 2597 for n, x in enumerate(testedStructureDetail): 2598 stream.append("tcu::TestStatus testPhysicalDeviceFeature" + x.instanceName[len('device'):]+" (Context& context)") 2599 stream.append("""{ 2600 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 2601 const CustomInstance instance (createCustomInstanceWithExtension(context, "VK_KHR_get_physical_device_properties2")); 2602 const InstanceDriver& vki (instance.getDriver()); 2603 const int count = 2u; 2604 TestLog& log = context.getTestContext().getLog(); 2605 VkPhysicalDeviceFeatures2 extFeatures; 2606 vector<VkExtensionProperties> properties = enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL); 2607""") 2608 stream.append("\t"+structureDefinitions[n]) 2609 stream.append("\t"+featureEnabledFlags[n]) 2610 stream.append('') 2611 stream.append('\tfor (int ndx = 0; ndx < count; ++ndx)\n\t{') 2612 stream.append("\t" + clearStructures[n]) 2613 stream.extend(structureChain[n]) 2614 stream.append('') 2615 stream.append( 2616 '\t\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n' 2617 '\t\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n' 2618 '\t\textFeatures.pNext = &' + testedStructureDetail[n].instanceName + '[ndx];\n\n' 2619 '\t\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);') 2620 stream.append('\t}\n') 2621 stream.extend(logStructures[n]) 2622 stream.append('') 2623 stream.extend(verifyStructures[n]) 2624 stream.append('\treturn tcu::TestStatus::pass("Querying succeeded");') 2625 stream.append("}\n") 2626 2627 allApiVersions = [f.number for f in api.features] 2628 promotedTests = [] 2629 if api.apiName == "vulkan": 2630 for feature in api.features: 2631 major = feature.number[0] 2632 minor = feature.number[-1] 2633 promotedFeatures = [] 2634 if feature.name == 'VK_VERSION_1_0': 2635 continue 2636 for requirement in feature.requirementsList: 2637 for type in requirement.typeList: 2638 matchedStructType = re.search(f'VkPhysicalDevice(\w+)Features', type, re.IGNORECASE) 2639 matchedCoreStructType = re.search(f'VkPhysicalDeviceVulkan(\d+)Features', type, re.IGNORECASE) 2640 if matchedStructType and not matchedCoreStructType: 2641 promotedFeatures.append(type) 2642 if promotedFeatures: 2643 testName = "createDeviceWithPromoted" + feature.number.replace('.', '') + "Structures" 2644 promotedTests.append(testName) 2645 stream.append("tcu::TestStatus " + testName + " (Context& context)") 2646 stream.append("{") 2647 stream.append( 2648 ' if (!context.contextSupports(vk::ApiVersion(0, ' + major + ', ' + minor + ', 0)))\n' 2649 ' TCU_THROW(NotSupportedError, "Vulkan ' + major + '.' + minor + ' is not supported");') 2650 stream.append(""" 2651 const PlatformInterface& platformInterface = context.getPlatformInterface(); 2652 const CustomInstance instance (createCustomInstanceFromContext(context)); 2653 const InstanceDriver& instanceDriver (instance.getDriver()); 2654 const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); 2655 const uint32_t queueFamilyIndex = 0; 2656 const uint32_t queueCount = 1; 2657 const uint32_t queueIndex = 0; 2658 const float queuePriority = 1.0f; 2659 2660 const vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice); 2661 2662 const VkDeviceQueueCreateInfo deviceQueueCreateInfo = 2663 { 2664 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 2665 DE_NULL, 2666 (VkDeviceQueueCreateFlags)0u, 2667 queueFamilyIndex, //queueFamilyIndex; 2668 queueCount, //queueCount; 2669 &queuePriority, //pQueuePriorities; 2670 }; 2671""") 2672 lastFeature = '' 2673 usedFeatures = [] 2674 for feature in promotedFeatures: 2675 for struct in testedStructureDetail: 2676 if (struct.instanceName in usedFeatures): 2677 continue 2678 if feature in struct.nameList: 2679 if lastFeature: 2680 stream.append("\t" + feature + " " + struct.instanceName + " = initVulkanStructure(&" + lastFeature + ");") 2681 else: 2682 stream.append("\t" + feature + " " + struct.instanceName + " = initVulkanStructure();") 2683 lastFeature = struct.instanceName 2684 usedFeatures.append(struct.instanceName) 2685 break 2686 stream.append("\tVkPhysicalDeviceFeatures2 extFeatures = initVulkanStructure(&" + lastFeature + ");") 2687 stream.append(""" 2688 instanceDriver.getPhysicalDeviceFeatures2 (physicalDevice, &extFeatures); 2689 2690 const VkDeviceCreateInfo deviceCreateInfo = 2691 { 2692 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType; 2693 &extFeatures, //pNext; 2694 (VkDeviceCreateFlags)0u, 2695 1, //queueRecordCount; 2696 &deviceQueueCreateInfo, //pRequestedQueues; 2697 0, //layerCount; 2698 DE_NULL, //ppEnabledLayerNames; 2699 0, //extensionCount; 2700 DE_NULL, //ppEnabledExtensionNames; 2701 DE_NULL, //pEnabledFeatures; 2702 }; 2703 2704 const Unique<VkDevice> device (createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); 2705 const DeviceDriver deviceDriver (platformInterface, instance, device.get(), context.getUsedApiVersion(), context.getTestContext().getCommandLine()); 2706 const VkQueue queue = getDeviceQueue(deviceDriver, *device, queueFamilyIndex, queueIndex); 2707 2708 VK_CHECK(deviceDriver.queueWaitIdle(queue)); 2709 2710 return tcu::TestStatus::pass("Pass"); 2711} 2712""") 2713 2714 # function to create tests 2715 stream.append("void addSeparateFeatureTests (tcu::TestCaseGroup* testGroup)\n{") 2716 for x in testedStructureDetail: 2717 stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x.instanceName[len('device'):]) + '", testPhysicalDeviceFeature' + x.instanceName[len('device'):] + ');') 2718 for x in promotedTests: 2719 stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x) + '", ' + x + ');') 2720 stream.append('}\n') 2721 2722 # write out 2723 writeInlFile(filename, INL_HEADER, stream) 2724 2725def generateDeviceFeaturesOrPropertiesDefs(api, FeaturesOrProperties): 2726 assert(FeaturesOrProperties in ['Features', 'Properties']) 2727 defs = [] 2728 foundStructureEnums = [] 2729 structureEnumPattern = f'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_{FeaturesOrProperties.upper()}(\w+)' 2730 structureEnumPatternNotExtension = structureEnumPattern[:-5] + '$' 2731 structureTypePattern = f'VkPhysicalDevice(\w+){FeaturesOrProperties}(\w+)' 2732 structureTypePatternNotExtension = structureTypePattern[:-5] + '$' 2733 structureTypeToSkipPattern = f'VkPhysicalDeviceVulkan\d\d{FeaturesOrProperties}' 2734 structureExtendsPattern = f'VkPhysicalDevice{FeaturesOrProperties}2' 2735 # iterate over all extensions to find extension that adds enum value matching pattern; 2736 # this will always be in first requirement section 2737 for ext in api.extensions: 2738 # skip extensions that were promoted to other extensions (not vk version) 2739 if ext.promotedto is not None and "VK_VERSION" not in ext.promotedto: 2740 continue 2741 allExtendedEnums = ext.requirementsList[0].extendedEnums 2742 for extendedEnum in allExtendedEnums: 2743 matchedStructEnum = re.search(structureEnumPattern, extendedEnum.name, re.IGNORECASE) 2744 if matchedStructEnum: 2745 # find feature/property structure type name 2746 structureTypeName = "" 2747 for stRequirement in ext.requirementsList[0].newTypes: 2748 stName = stRequirement.name 2749 matchedStructType = re.search(structureTypePattern, stName, re.IGNORECASE) 2750 if matchedStructType: 2751 structureTypeName = stName 2752 break 2753 # iterate over all composite types to check if structureTypeName is not alias 2754 # this handles case where extension was promoted and with it feature/property structure 2755 structureType = None 2756 for ct in api.compositeTypes: 2757 if structureTypeName == ct.name: 2758 structureType = ct 2759 break 2760 elif structureTypeName in ct.aliasList: 2761 structureType = ct 2762 structureTypeName = structureType.name 2763 break 2764 # use data in structextends to skip structures that should not be passed to vkGetPhysicalDeviceProperties(/Features)2 function 2765 if structureType is None or structureType.structextends is None or structureExtendsPattern not in structureType.structextends: 2766 continue 2767 # meke sure that structure was not added earlier - this handles special 2768 # cases like VkPhysicalDeviceIDPropertiesKHR added by 3 extensions 2769 if len([d for d in defs if d[3] == structureTypeName]) > 0: 2770 continue 2771 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD 2772 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts 2773 sSuffix = matchedStructEnum.group(2) 2774 sVerSuffix = '' 2775 sExtSuffix = sSuffix 2776 suffixStart = sSuffix.rfind('_') 2777 if suffixStart > 0: 2778 sVerSuffix = sSuffix[:suffixStart] 2779 sExtSuffix = sSuffix[suffixStart:] 2780 foundStructureEnums.append(matchedStructEnum.group(1)) 2781 defs.append( (matchedStructEnum.group(1), sVerSuffix, sExtSuffix, structureTypeName,\ 2782 ext.name, allExtendedEnums[1].name, allExtendedEnums[0].name) ) 2783 # accept single feature/property structure per extension - this also handles cases 2784 # like VK_KHR_variable_pointers which specify feature structure and its alias 2785 break 2786 2787 # iterate over all structures to find Feature/Property structures that were not added with extension 2788 # but with vulkan version; to do that we need to skip extension part from pattern 2789 for ct in api.compositeTypes: 2790 matchedStructType = re.search(structureTypePatternNotExtension, ct.name, re.IGNORECASE) 2791 if matchedStructType: 2792 if ct.members[0].name != "sType": 2793 continue 2794 if ct.structextends is None or structureExtendsPattern not in ct.structextends: 2795 continue 2796 matchedStructEnum = re.search(structureEnumPatternNotExtension, ct.members[0].values, re.IGNORECASE) 2797 if (matchedStructEnum.group(1) not in foundStructureEnums) and (re.match(structureTypeToSkipPattern, ct.name) == None): 2798 defs.append( (matchedStructEnum.group(1), '', '', ct.name, None, None, '0') ) 2799 return defs 2800 2801def writeDeviceFeatures(api, dfDefs, filename): 2802 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs 2803 # and construct dictionary with all of their attributes 2804 blobMembers = {} 2805 blobStructs = {} 2806 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$") 2807 for structureType in api.compositeTypes: 2808 match = blobPattern.match(structureType.name) 2809 if match: 2810 allMembers = [member.name for member in structureType.members] 2811 vkVersion = match.group(1) 2812 blobMembers[vkVersion] = allMembers[2:] 2813 blobStructs[vkVersion] = set() 2814 initFromBlobDefinitions = [] 2815 emptyInitDefinitions = [] 2816 # iterate over all feature structures 2817 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*") 2818 nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$") 2819 for structureType in api.compositeTypes: 2820 # skip structures that are not feature structures 2821 if not allFeaturesPattern.match(structureType.name): 2822 continue 2823 # skip structures that were previously identified as blobs 2824 if blobPattern.match(structureType.name): 2825 continue 2826 # skip sType and pNext and just grab third and next attributes 2827 structureMembers = structureType.members[2:] 2828 notPartOfBlob = True 2829 if nonExtFeaturesPattern.match(structureType.name): 2830 # check if this member is part of any of the blobs 2831 for blobName, blobMemberList in blobMembers.items(): 2832 # if just one member is not part of this blob go to the next blob 2833 # (we asume that all members are part of blob - no need to check all) 2834 if structureMembers[0].name not in blobMemberList: 2835 continue 2836 # add another feature structure name to this blob 2837 blobStructs[blobName].add(structureType) 2838 # add specialization for this feature structure 2839 memberCopying = "" 2840 for member in structureMembers: 2841 memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName) 2842 wholeFunction = \ 2843 "template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \ 2844 "{{\n" \ 2845 "{1}" \ 2846 "}}".format(structureType.name, memberCopying) 2847 initFromBlobDefinitions.append(wholeFunction) 2848 notPartOfBlob = False 2849 # assuming that all members are part of blob, goto next 2850 break 2851 # add empty template definition as on Fedora there are issue with 2852 # linking using just generic template - all specializations are needed 2853 if notPartOfBlob: 2854 emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}" 2855 emptyInitDefinitions.append(emptyFunction.format(structureType.name)) 2856 extensionDefines = [] 2857 makeFeatureDescDefinitions = [] 2858 featureStructWrappers = [] 2859 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extName, extNameDef, specVersionDef) in enumerate(dfDefs): 2860 extensionNameDefinition = extNameDef 2861 if not extensionNameDefinition: 2862 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType) 2863 extensionDefines.append(f'#define {extensionNameDefinition} "core_feature"') 2864 # construct makeFeatureDesc template function definitions 2865 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix) 2866 makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \ 2867 "{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVersionDef, len(dfDefs)-idx)) 2868 # construct CreateFeatureStruct wrapper block 2869 featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVersionDef)) 2870 # construct function that will check for which vk version structure sType is part of blob 2871 blobChecker = "uint32_t getBlobFeaturesVersion (VkStructureType sType)\n{\n" \ 2872 "\tconst std::map<VkStructureType, uint32_t> sTypeBlobMap\n" \ 2873 "\t{\n" 2874 # iterate over blobs with list of structures 2875 for blobName in sorted(blobStructs.keys()): 2876 blobChecker += "\t\t// Vulkan{0}\n".format(blobName) 2877 # iterate over all feature structures in current blob 2878 structuresList = list(blobStructs[blobName]) 2879 structuresList = sorted(structuresList, key=lambda s: s.name) 2880 for structType in structuresList: 2881 # find definition of this structure in dfDefs 2882 structDef = None 2883 allNamesToCheck = [structType.name] 2884 if len(structType.aliasList) > 0: 2885 allNamesToCheck.extend(structType.aliasList) 2886 for structName in allNamesToCheck: 2887 structDefList = [s for s in dfDefs if s[3] == structName] 2888 if len(structDefList) > 0: 2889 structDef = structDefList[0] 2890 break 2891 sType = structDef[0] 2892 sSuffix = structDef[1] + structDef[2] 2893 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix) 2894 tabs = "\t" * int((88 - len(sTypeName)) / 4) 2895 blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1]) 2896 blobChecker += "\t};\n\n" \ 2897 "\tauto it = sTypeBlobMap.find(sType);\n" \ 2898 "\tif(it == sTypeBlobMap.end())\n" \ 2899 "\t\treturn 0;\n" \ 2900 "\treturn it->second;\n" \ 2901 "}\n" 2902 # combine all definition lists 2903 stream = [ 2904 '#include "vkDeviceFeatures.hpp"\n', 2905 'namespace vk\n{'] 2906 stream.extend(extensionDefines) 2907 stream.append('\n') 2908 stream.extend(initFromBlobDefinitions) 2909 stream.append('\n// generic template is not enough for some compilers') 2910 stream.extend(emptyInitDefinitions) 2911 stream.append('\n') 2912 stream.extend(makeFeatureDescDefinitions) 2913 stream.append('\n') 2914 stream.append('static const FeatureStructCreationData featureStructCreationArray[]\n{') 2915 stream.extend(featureStructWrappers) 2916 stream.append('};\n') 2917 stream.append(blobChecker) 2918 stream.append('} // vk\n') 2919 writeInlFile(filename, INL_HEADER, stream) 2920 2921def writeDeviceFeatureTest(api, filename): 2922 2923 coreFeaturesPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$") 2924 featureItems = [] 2925 testFunctions = [] 2926 # iterate over all feature structures 2927 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*") 2928 for structureType in api.compositeTypes: 2929 # skip structures that are not feature structures 2930 if not allFeaturesPattern.match(structureType.name): 2931 continue 2932 # skip sType and pNext and just grab third and next attributes 2933 structureMembers = structureType.members[2:] 2934 2935 items = [] 2936 for member in structureMembers: 2937 items.append(" FEATURE_ITEM ({0}, {1}),".format(structureType.name, member.name)) 2938 2939 testBlock = """ 2940tcu::TestStatus createDeviceWithUnsupportedFeaturesTest{4} (Context& context) 2941{{ 2942 const PlatformInterface& vkp = context.getPlatformInterface(); 2943 tcu::TestLog& log = context.getTestContext().getLog(); 2944 tcu::ResultCollector resultCollector (log); 2945 const CustomInstance instance (createCustomInstanceWithExtensions(context, context.getInstanceExtensions(), DE_NULL, true)); 2946 const InstanceDriver& instanceDriver (instance.getDriver()); 2947 const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); 2948 const uint32_t queueFamilyIndex = 0; 2949 const uint32_t queueCount = 1; 2950 const float queuePriority = 1.0f; 2951 const DeviceFeatures deviceFeaturesAll (context.getInstanceInterface(), context.getUsedApiVersion(), physicalDevice, context.getInstanceExtensions(), context.getDeviceExtensions(), true); 2952 const VkPhysicalDeviceFeatures2 deviceFeatures2 = deviceFeaturesAll.getCoreFeatures2(); 2953 int numErrors = 0; 2954 const tcu::CommandLine& commandLine = context.getTestContext().getCommandLine(); 2955 bool isSubProcess = context.getTestContext().getCommandLine().isSubProcess(); 2956{6} 2957 2958 VkPhysicalDeviceFeatures emptyDeviceFeatures; 2959 deMemset(&emptyDeviceFeatures, 0, sizeof(emptyDeviceFeatures)); 2960 2961 // Only non-core extensions will be used when creating the device. 2962 const auto& extensionNames = context.getDeviceCreationExtensions(); 2963 DE_UNREF(extensionNames); // In some cases this is not used. 2964 2965 if (const void* featuresStruct = findStructureInChain(const_cast<const void*>(deviceFeatures2.pNext), getStructureType<{0}>())) 2966 {{ 2967 static const Feature features[] = 2968 {{ 2969{1} 2970 }}; 2971 auto* supportedFeatures = reinterpret_cast<const {0}*>(featuresStruct); 2972 checkFeatures(vkp, instance, instanceDriver, physicalDevice, {2}, features, supportedFeatures, queueFamilyIndex, queueCount, queuePriority, numErrors, resultCollector, {3}, emptyDeviceFeatures, {5}, context.getUsedApiVersion(), commandLine); 2973 }} 2974 2975 if (numErrors > 0) 2976 return tcu::TestStatus(resultCollector.getResult(), "Enabling unsupported features didn't return VK_ERROR_FEATURE_NOT_PRESENT."); 2977 else 2978 return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage()); 2979}} 2980""" 2981 additionalParams = ( 'memReservationStatMax, isSubProcess' if api.apiName == 'vulkansc' else 'isSubProcess' ) 2982 additionalDefs = ( ' VkDeviceObjectReservationCreateInfo memReservationStatMax = context.getResourceInterface()->getStatMax();' if apiName == 'vulkansc' else '') 2983 featureItems.append(testBlock.format(structureType.name, "\n".join(items), len(items), ("DE_NULL" if coreFeaturesPattern.match(structureType.name) else "&extensionNames"), structureType.name[len('VkPhysicalDevice'):], additionalParams, additionalDefs)) 2984 2985 testFunctions.append("createDeviceWithUnsupportedFeaturesTest" + structureType.name[len('VkPhysicalDevice'):]) 2986 2987 stream = [''] 2988 stream.extend(featureItems) 2989 stream.append(""" 2990void addSeparateUnsupportedFeatureTests (tcu::TestCaseGroup* testGroup) 2991{ 2992""") 2993 for x in testFunctions: 2994 stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x[len('createDeviceWithUnsupportedFeaturesTest'):]) + '", ' + x + ');') 2995 stream.append('}\n') 2996 2997 writeInlFile(filename, INL_HEADER, stream) 2998 2999def writeDeviceProperties(api, dpDefs, filename): 3000 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs 3001 # and construct dictionary with all of their attributes 3002 blobMembers = {} 3003 blobStructs = {} 3004 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$") 3005 for structureType in api.compositeTypes: 3006 match = blobPattern.match(structureType.name) 3007 if match: 3008 allMembers = [member.name for member in structureType.members] 3009 vkVersion = match.group(1) 3010 blobMembers[vkVersion] = allMembers[2:] 3011 blobStructs[vkVersion] = set() 3012 initFromBlobDefinitions = [] 3013 emptyInitDefinitions = [] 3014 # iterate over all property structures 3015 allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*") 3016 nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$") 3017 for structureType in api.compositeTypes: 3018 # skip structures that are not property structures 3019 if not allPropertiesPattern.match(structureType.name): 3020 continue 3021 # skip structures that were previously identified as blobs 3022 if blobPattern.match(structureType.name): 3023 continue 3024 # skip sType and pNext and just grab third and next attributes 3025 structureMembers = structureType.members[2:] 3026 notPartOfBlob = True 3027 if nonExtPropertiesPattern.match(structureType.name): 3028 # check if this member is part of any of the blobs 3029 for blobName, blobMemberList in blobMembers.items(): 3030 # if just one member is not part of this blob go to the next blob 3031 # (we asume that all members are part of blob - no need to check all) 3032 if structureMembers[0].name not in blobMemberList: 3033 continue 3034 # add another property structure name to this blob 3035 blobStructs[blobName].add(structureType) 3036 # add specialization for this property structure 3037 memberCopying = "" 3038 for member in structureMembers: 3039 if len(member.arraySizeList) == 0: 3040 # handle special case 3041 if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name : 3042 blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:] 3043 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName) 3044 # end handling special case 3045 else: 3046 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName) 3047 else: 3048 memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type, member.arraySizeList[0]) 3049 wholeFunction = \ 3050 "template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \ 3051 "{{\n" \ 3052 "{1}" \ 3053 "}}".format(structureType.name, memberCopying) 3054 initFromBlobDefinitions.append(wholeFunction) 3055 notPartOfBlob = False 3056 # assuming that all members are part of blob, goto next 3057 break 3058 # add empty template definition as on Fedora there are issue with 3059 # linking using just generic template - all specializations are needed 3060 if notPartOfBlob: 3061 emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}" 3062 emptyInitDefinitions.append(emptyFunction.format(structureType.name)) 3063 extensionDefines = [] 3064 makePropertyDescDefinitions = [] 3065 propertyStructWrappers = [] 3066 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extName, extNameDef, specVersionDef) in enumerate(dpDefs): 3067 extensionNameDefinition = extNameDef 3068 if not extensionNameDefinition: 3069 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType) 3070 extensionDefines.append(f'#define {extensionNameDefinition} "core_property"') 3071 # construct makePropertyDesc template function definitions 3072 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix) 3073 makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \ 3074 "{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVersionDef, len(dpDefs)-idx)) 3075 # construct CreateProperty struct wrapper block 3076 propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVersionDef)) 3077 # construct method that will check if structure sType is part of blob 3078 blobChecker = "uint32_t getBlobPropertiesVersion (VkStructureType sType)\n{\n" \ 3079 "\tconst std::map<VkStructureType, uint32_t> sTypeBlobMap\n" \ 3080 "\t{\n" 3081 # iterate over blobs with list of structures 3082 for blobName in sorted(blobStructs.keys()): 3083 blobChecker += "\t\t// Vulkan{0}\n".format(blobName) 3084 # iterate over all feature structures in current blob 3085 structuresList = list(blobStructs[blobName]) 3086 structuresList = sorted(structuresList, key=lambda s: s.name) 3087 for structType in structuresList: 3088 # find definition of this structure in dpDefs 3089 structName = structType.name 3090 structDef = None 3091 foundDefs = [s for s in dpDefs if s[3] == structName] 3092 if len(foundDefs) > 0: 3093 structDef = foundDefs[0] 3094 else: 3095 for alias in structType.aliasList: 3096 foundDefs = [s for s in dpDefs if s[3] == alias] 3097 if len(foundDefs) > 0: 3098 structDef = foundDefs[0] 3099 break 3100 sType = structDef[0] 3101 sSuffix = structDef[1] + structDef[2] 3102 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix) 3103 tabs = "\t" * int((80 - len(sTypeName)) / 4) 3104 blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1]) 3105 blobChecker += "\t};\n\n" \ 3106 "\tauto it = sTypeBlobMap.find(sType);\n" \ 3107 "\tif(it == sTypeBlobMap.end())\n" \ 3108 "\t\treturn 0;\n" \ 3109 "\treturn it->second;\n" \ 3110 "}\n" 3111 # combine all definition lists 3112 stream = [ 3113 '#include "vkDeviceProperties.hpp"\n', 3114 'namespace vk\n{'] 3115 stream.extend(extensionDefines) 3116 stream.append('\n') 3117 stream.extend(initFromBlobDefinitions) 3118 stream.append('\n// generic template is not enough for some compilers') 3119 stream.extend(emptyInitDefinitions) 3120 stream.append('\n') 3121 stream.extend(makePropertyDescDefinitions) 3122 stream.append('\n') 3123 stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{') 3124 stream.extend(propertyStructWrappers) 3125 stream.append('};\n') 3126 stream.append(blobChecker) 3127 stream.append('} // vk\n') 3128 writeInlFile(filename, INL_HEADER, stream) 3129 3130UNSUFFIXED_STRUCTURES = [ 3131 "CornerSampledImage", 3132 "ShaderSMBuiltins", 3133 "ShadingRateImage", 3134 "RayTracing", 3135 "RepresentativeFragmentTest", 3136 "ComputeShaderDerivatives", 3137 "MeshShader", 3138 "ShaderImageFootprint", 3139 "ExclusiveScissor", 3140 "DedicatedAllocationImageAliasing", 3141 "CoverageReductionMode", 3142 "DeviceGeneratedCommands", 3143 "InheritedViewportScissor", 3144 "PresentBarrier", 3145 "DiagnosticsConfig", 3146 "FragmentShadingRateEnums", 3147 "RayTracingMotionBlur", 3148 "ExternalMemoryRDMA", 3149 "CopyMemoryIndirect", 3150 "MemoryDecompression", 3151 "LinearColorAttachment", 3152 "OpticalFlow", 3153 "RayTracingInvocationReorder", 3154 "DisplacementMicromap"] 3155 3156def deviceFeaturesOrPropertiesGetter(name): 3157 result = name[16:] # Remove VkPhysicalDevice prefix 3158 if result[-3:] == "KHR": 3159 result = result[0:-3] 3160 elif result[-2:] == "NV": 3161 suffix = result[-2:] 3162 result = result[0:-2] 3163 if result[-8:] == "Features": 3164 infix = result[-8:] 3165 result = result[0:-8] 3166 elif result[-10:] == "Properties": 3167 infix = result[-10:] 3168 result = result[0:-10] 3169 if (result in UNSUFFIXED_STRUCTURES): 3170 suffix = "" 3171 result = result + infix + suffix 3172 return result 3173 3174def genericDeviceFeaturesWriter(dfDefs, pattern, filename): 3175 stream = [] 3176 for _, _, _, extStruct, _, _, _ in dfDefs: 3177 nameSubStr = deviceFeaturesOrPropertiesGetter(extStruct) 3178 stream.append(pattern.format(extStruct, nameSubStr)) 3179 writeInlFile(filename, INL_HEADER, indentLines(stream)) 3180 3181def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename): 3182 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}" 3183 genericDeviceFeaturesWriter(dfDefs, pattern, filename) 3184 3185def writeDeviceFeaturesContextDecl(dfDefs, filename): 3186 pattern = "const vk::{0}&\tget{1}\t(void) const;" 3187 genericDeviceFeaturesWriter(dfDefs, pattern, filename) 3188 3189def writeDeviceFeaturesContextDefs(dfDefs, filename): 3190 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}" 3191 genericDeviceFeaturesWriter(dfDefs, pattern, filename) 3192 3193def genericDevicePropertiesWriter(dfDefs, pattern, filename): 3194 stream = [] 3195 for _, _, _, extStruct, _, _, _ in dfDefs: 3196 nameSubStr = deviceFeaturesOrPropertiesGetter(extStruct) 3197 stream.append(pattern.format(extStruct, nameSubStr)) 3198 writeInlFile(filename, INL_HEADER, indentLines(stream)) 3199 3200def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename): 3201 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}" 3202 genericDevicePropertiesWriter(dfDefs, pattern, filename) 3203 3204def writeDevicePropertiesContextDecl(dfDefs, filename): 3205 pattern = "const vk::{0}&\tget{1}\t(void) const;" 3206 genericDevicePropertiesWriter(dfDefs, pattern, filename) 3207 3208def writeDevicePropertiesContextDefs(dfDefs, filename): 3209 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}" 3210 genericDevicePropertiesWriter(dfDefs, pattern, filename) 3211 3212def writeMandatoryFeatures(api, filename): 3213 3214 def structInAPI(name): 3215 for c in api.compositeTypes: 3216 if c.name == name: 3217 return True 3218 for alias in c.aliasList: 3219 if alias == name: 3220 return True 3221 return False 3222 stream = [] 3223 3224 dictStructs = {} 3225 dictData = [] 3226 extData = [] 3227 usedFeatureStructs = {} 3228 for _, data in api.additionalExtensionData: 3229 if 'mandatory_features' in data.keys(): 3230 # sort to have same results for py2 and py3 3231 listStructFeatures = sorted(data['mandatory_features'].items(), key=lambda tup: tup[0]) 3232 for structure, featuresList in listStructFeatures: 3233 for featureData in featuresList: 3234 # allow for featureless VKSC only extensions 3235 if not 'features' in featureData.keys() or 'requirements' not in featureData.keys(): 3236 continue 3237 requirements = featureData['requirements'] 3238 3239 mandatory_variant = '' 3240 try: 3241 mandatory_variant = featureData['mandatory_variant'] 3242 except KeyError: 3243 mandatory_variant = '' 3244 3245 dictData.append( [ structure, featureData['features'], requirements, mandatory_variant] ) 3246 3247 if structure == 'VkPhysicalDeviceFeatures': 3248 continue 3249 3250 # if structure is not in dict construct name of variable and add is as a first item 3251 if (structure not in dictStructs): 3252 dictStructs[structure] = ([structure[2:3].lower() + structure[3:]], mandatory_variant) 3253 # add first requirement if it is unique 3254 if requirements and (requirements[0] not in dictStructs[structure][0]): 3255 dictStructs[structure][0].append(requirements[0]) 3256 3257 usedFeatureStructs[structure] = [] 3258 3259 if requirements: 3260 for req in requirements: 3261 if '.' in req: 3262 req = req.split('.')[0] 3263 reqStruct = 'Vk' + req[0].upper() + req[1:] 3264 usedFeatureStructs[reqStruct] = [] 3265 3266 if 'mandatory_extensions' in data: 3267 mandatoryExtensions = [] 3268 for mandatoryExt in data['mandatory_extensions']: 3269 if 'extension' in mandatoryExt: 3270 extName = mandatoryExt.pop('extension') 3271 mandatoryExtensions.append((extName, mandatoryExt)) 3272 3273 for extension, extensionData in mandatoryExtensions: 3274 # requirements are actually mandatory. 3275 if 'requirements' not in extensionData: 3276 continue 3277 3278 requirements = extensionData['requirements'] 3279 mandatory_variant = '' if 'mandatory_variant' not in extensionData else extensionData['mandatory_variant'] 3280 extData.append((extension, requirements, mandatory_variant)) 3281 3282 for req in requirements: 3283 if '.' in req: 3284 req = req.split('.')[0] 3285 reqStruct = 'Vk' + req[0].upper() + req[1:] 3286 usedFeatureStructs[reqStruct] = [] 3287 3288 stream.extend(['bool canUseFeaturesStruct (const vector<VkExtensionProperties>& deviceExtensions, uint32_t usedApiVersion, const char* extension)', 3289 '{', 3290 '\treturn (isExtensionStructSupported(deviceExtensions, RequiredExtension(extension))', 3291 '\t\t\t|| isCoreDeviceExtension(usedApiVersion, extension));', 3292 '}', 3293 '', 3294 'bool checkMandatoryFeatures(const vkt::Context& context)\n{', 3295 '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))', 3296 '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");', 3297 '', 3298 '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();', 3299 '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();', 3300 '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);', 3301 '\tconst uint32_t\t\t\t\t\t\tusedApiVersion\t\t= context.getUsedApiVersion();', 3302 '', 3303 '\ttcu::TestLog& log = context.getTestContext().getLog();', 3304 '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;', 3305 '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));', 3306 '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;', 3307 '\tvoid** nextPtr = &coreFeatures.pNext;', 3308 '']) 3309 3310 # Find the extensions that added the required feature structs. 3311 class StructFoundContinue(Exception): 3312 pass 3313 3314 for usedStruct in usedFeatureStructs: 3315 for compType in api.compositeTypes: 3316 nameList = [compType.name] + compType.aliasList 3317 if usedStruct in nameList: 3318 # Found the official name list for the struct. 3319 for extension in api.extensions: 3320 try: 3321 for requirement in extension.requirementsList: 3322 for extensionStructure in requirement.newTypes: 3323 if extensionStructure.name in nameList: 3324 # Found extension for the struct. 3325 usedFeatureStructs[usedStruct].append(extension.name) 3326 raise StructFoundContinue 3327 except StructFoundContinue: 3328 pass 3329 3330 structList = sorted(usedFeatureStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3 3331 apiStructs = list( filter(lambda x : structInAPI(x[0]), structList)) # remove items not defined in current API 3332 varVariants = {} # Some variables are going to be declared only for specific variants. 3333 3334 for structName, extensions in apiStructs: 3335 # The variable name will be the structure name without the Vk prefix and starting in lowercase. 3336 newVar = structName[2].lower() + structName[3:] 3337 3338 metaCondition = '' 3339 if structName in dictStructs: 3340 mandatoryVariantList = dictStructs[structName][1] 3341 if len(mandatoryVariantList) > 0: 3342 mandatoryVariant = mandatoryVariantList[0] 3343 metaCondition = 'defined(CTS_USES_' + mandatoryVariant.upper() + ')' 3344 stream.append('#if ' + metaCondition) 3345 varVariants[newVar] = mandatoryVariant 3346 3347 stream.extend(['\tvk::' + structName + ' ' + newVar + ';', 3348 '\tdeMemset(&' + newVar + ', 0, sizeof(' + newVar + '));', 3349 '']) 3350 3351 if len(extensions) > 0: 3352 canUseCond = '\tif (' 3353 for (i, extName) in enumerate(extensions): 3354 canUseCond += ' ' if i == 0 else ' || ' 3355 canUseCond += 'canUseFeaturesStruct(deviceExtensions, usedApiVersion, "' + extName + '")' 3356 canUseCond += ' )' 3357 stream.append(canUseCond) 3358 elif api.apiName == "vulkan" and structName in dictStructs: 3359 #reqs = v[0][1:] 3360 reqs = dictStructs[structName][0][1:] 3361 cond = 'if ( ' 3362 for i, req in enumerate(reqs): 3363 if i > 0: 3364 cond = cond + ' || ' 3365 if (req.startswith("ApiVersion")): 3366 cond = cond + 'context.contextSupports(vk::' + req + ')' 3367 cond = cond + ' )' 3368 stream.append('\t' + cond) 3369 3370 stream.extend(['\t{', 3371 '\t\t' + newVar + '.sType = getStructureType<' + structName + '>();', 3372 '\t\t*nextPtr = &' + newVar + ';', 3373 '\t\tnextPtr = &' + newVar + '.pNext;', 3374 '\t}']) 3375 3376 if len(metaCondition) > 0: 3377 stream.append('#endif // ' + metaCondition) 3378 3379 stream.append('') 3380 3381 stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);', 3382 '\tbool result = true;', 3383 '']) 3384 3385 for v in dictData: 3386 if not structInAPI(v[0]): # remove items not defined in current API ( important for Vulkan SC ) 3387 continue 3388 structType = v[0] 3389 structName = 'coreFeatures.features' 3390 metaCondition = '' 3391 if len(v) == 4 and v[3] != '': 3392 # for x in v[3].split('_'): 3393 metaCondition = metaCondition + ' || defined(CTS_USES_' + v[3][0].upper() + ')' 3394 stream.extend(['#if ' + metaCondition[4:]]) 3395 if v[0] != 'VkPhysicalDeviceFeatures' : 3396 structName = dictStructs[v[0]][0][0] 3397 if len(v[2]) > 0 : 3398 condition = 'if ( ' 3399 for i, req in enumerate(v[2]) : 3400 if (req.startswith("ApiVersion")): 3401 condition = condition + 'context.contextSupports(vk::' + req + ')' 3402 elif '.' in req: 3403 condition = condition + req 3404 else: 3405 condition = condition + 'isExtensionStructSupported(deviceExtensions, RequiredExtension("' + req + '"))' 3406 if i+1 < len(v[2]) : 3407 condition = condition + ' && ' 3408 condition = condition + ' )' 3409 stream.append('\t' + condition) 3410 stream.append('\t{') 3411 # Don't need to support an AND case since that would just be another line in the .txt 3412 reqMetaCondition = '' 3413 if len(v[1]) == 1: 3414 # If the req struct type has a mandatory variant we need to add an #ifdef block, unless we're already inside one. 3415 if len(metaCondition) == 0 and structName in varVariants: 3416 reqMetaCondition = 'defined(CTS_USES_' + varVariants[structName].upper() + ')' 3417 stream.append('#if ' + reqMetaCondition) 3418 stream.append('\t\tif ( ' + structName + '.' + v[1][0] + ' == VK_FALSE )') 3419 else: 3420 condition = 'if ( ' 3421 for i, feature in enumerate(v[1]): 3422 if i != 0: 3423 condition = condition + ' && ' 3424 condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )' 3425 condition = condition + ' )' 3426 stream.append('\t\t' + condition) 3427 featureSet = " or ".join(v[1]) 3428 stream.extend(['\t\t{', 3429 '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;', 3430 '\t\t\tresult = false;', 3431 '\t\t}']) 3432 if reqMetaCondition != '': 3433 stream.append('#endif // ' + reqMetaCondition) 3434 stream.append('\t}') 3435 if metaCondition != '': 3436 stream.extend(['#endif // ' + metaCondition[4:], 3437 '']) 3438 else: 3439 stream.extend(['']) 3440 3441 for extension, requirements, mandatory_variant in extData: 3442 metaCondition = '' 3443 if mandatory_variant != '': 3444 metaCondition = metaCondition + ' || defined(CTS_USES_' + mandatory_variant[0].upper() + ')' 3445 stream.extend(['#if ' + metaCondition[4:]]) 3446 if len(requirements) > 0 : 3447 condition = 'if ( ' 3448 for i, req in enumerate(requirements) : 3449 if (req.startswith("ApiVersion")): 3450 condition = condition + 'context.contextSupports(vk::' + req + ')' 3451 elif '.' in req: 3452 condition = condition + req 3453 else: 3454 condition = condition + 'isExtensionStructSupported(deviceExtensions, RequiredExtension("' + req + '"))' 3455 if i+1 < len(requirements) : 3456 condition = condition + ' && ' 3457 condition = condition + ' )' 3458 stream.append('\t' + condition) 3459 stream.append('\t{') 3460 stream.extend(['\t\tif (!(isExtensionStructSupported(deviceExtensions, RequiredExtension("' + extension + '")) || isCoreDeviceExtension(usedApiVersion, "' + extension + '")))', 3461 '\t\t{', 3462 '\t\t\tlog << tcu::TestLog::Message << "Mandatory extension ' + extension + ' not supported" << tcu::TestLog::EndMessage;', 3463 '\t\t\tresult = false;', 3464 '\t\t}', 3465 '\t}']) 3466 if metaCondition != '': 3467 stream.extend(['#endif // ' + metaCondition[4:], 3468 '']) 3469 else: 3470 stream.append('') 3471 3472 stream.append('\treturn result;') 3473 stream.append('}\n') 3474 3475 writeInlFile(filename, INL_HEADER, stream) 3476 3477def writeExtensionList(api, filename, extensionType): 3478 extensionList = [] 3479 for extensionName, data in api.additionalExtensionData: 3480 # make sure extension name starts with VK_KHR 3481 if not extensionName.startswith('VK_KHR'): 3482 continue 3483 # make sure that this extension was registered 3484 if 'register_extension' not in data.keys(): 3485 continue 3486 # skip extensions that are not supported in Vulkan SC 3487 if api.apiName == 'vulkansc': 3488 if any(ext.name == extensionName for ext in api.notSupportedExtensions): 3489 continue 3490 # make sure extension is intended for the vulkan variant 3491 is_sc_only = False 3492 3493 if api.apiName != 'vulkansc': 3494 if 'mandatory_features' in data.keys(): 3495 for structure, listStruct in data['mandatory_features'].items(): 3496 for featureData in listStruct: 3497 mandatory_variant = '' 3498 try: 3499 mandatory_variant = featureData['mandatory_variant'] 3500 except KeyError: 3501 mandatory_variant = '' 3502 # VKSC only 3503 if 'vulkansc' in mandatory_variant: 3504 is_sc_only = True 3505 if is_sc_only: 3506 continue 3507 3508 # make sure extension has proper type 3509 if extensionType == data['register_extension']['type']: 3510 extensionList.append(extensionName) 3511 extensionList.sort() 3512 # write list of all found extensions 3513 stream = [] 3514 stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(extensionType.title())) 3515 for n in extensionList: 3516 stream.append('\t"' + n + '",') 3517 stream.append('};\n') 3518 writeInlFile(filename, INL_HEADER, stream) 3519 3520def transformDependsToCondition(depends, api, checkVersionString, checkExtensionString): 3521 depList = re.split(r'(\W+)', depends) 3522 for idx, depPart in enumerate(depList): 3523 if ',' in depPart: 3524 depList[idx] = depList[idx].replace(',', ' || ') 3525 elif '+' in depPart: 3526 depList[idx] = depList[idx].replace('+', ' && ') 3527 elif 'VK_' in depPart: 3528 if 'VK_VERSION' in depPart: 3529 if idx > 0 and ' || ' in depList[idx-1]: 3530 # some vk.xml entries include "promoted to" version preceded by logical OR operator in the extension "depends" attribute 3531 # script don't rely on this optional information and will find "promoted to" versions for all dependencies of all extensions in the below code 3532 # accordingly the one from vk.xml is ignored to avoid redundant isCompatibile() checks 3533 depList[idx-1] = depList[idx-1].replace(' || ', '') 3534 depList[idx] = '' 3535 continue 3536 # when dependency is vulkan version then replace it with proper condition 3537 depList[idx] = checkVersionString % (depPart[-3], depPart[-1]) 3538 else: 3539 # when dependency is extension check if it was promoted 3540 extNotFound = True 3541 for dExt in api.extensions: 3542 if depPart == dExt.name: 3543 depExtVector = 'vDEP' if dExt.type == 'device' else 'vIEP' 3544 isSupportedCheck = checkExtensionString % (depExtVector, depPart) 3545 if dExt.promotedto is not None: 3546 p = dExt.promotedto 3547 # check if dependency was promoted to vulkan version or other extension 3548 if 'VK_VERSION' in p: 3549 depList[idx] = f'({checkVersionString % (p[-3], p[-1])} || {isSupportedCheck})' 3550 else: 3551 depList[idx] = f'({checkExtensionString % (depExtVector, depPart)} || {isSupportedCheck})' 3552 else: 3553 depList[idx] = isSupportedCheck 3554 extNotFound = False 3555 break 3556 # for SC when extension was not found try checking also not supported 3557 # extensions and see if this extension is part of core 3558 if extNotFound and api.apiName == "vulkansc": 3559 for dExt in api.notSupportedExtensions: 3560 if depPart == dExt.name: 3561 p = dExt.promotedto 3562 if p is None: 3563 break 3564 if int(p[-1]) > 2: 3565 break 3566 extNotFound = False 3567 depList[idx] = "true" 3568 if extNotFound: 3569 assert False, f"{depPart} from dependencies ({depends}) not found" 3570 return ''.join(depList) 3571 3572def writeApiExtensionDependencyInfo(api, filename): 3573 3574 def genHelperFunctions(): 3575 yield 'using namespace tcu;' 3576 yield 'using ExtPropVect = std::vector<vk::VkExtensionProperties>;' 3577 yield 'using IsSupportedFun = bool (*)(const tcu::UVec2&, const ExtPropVect&, const ExtPropVect&);' 3578 yield 'using DependencyCheckVect = std::vector<std::pair<const char*, IsSupportedFun> >;\n' 3579 yield 'bool isCompatibile(uint32_t major, uint32_t minor, const tcu::UVec2& testedApiVersion)' 3580 yield '{' 3581 yield '\t// return true when tested api version is greater' 3582 yield '\t// or equal to version represented by two uints' 3583 yield '\tif (major == testedApiVersion.x())' 3584 yield '\t\treturn minor <= testedApiVersion.y();' 3585 yield '\treturn major < testedApiVersion.x();' 3586 yield '}\n' 3587 yield 'bool isSupported(const ExtPropVect& extensions, const char* ext)' 3588 yield '{' 3589 yield '\treturn isExtensionStructSupported(extensions, vk::RequiredExtension(ext));' 3590 yield '}\n' 3591 3592 def genExtDepArray(extType): 3593 extensionList = [] 3594 maxExtLength = 0 3595 extVector = 'vIEP' 3596 othVector = 'vDEP' 3597 if extType == 'device': 3598 extVector, othVector = othVector, extVector # swap 3599 # iterate over all extension that are of specified type and that have requirements 3600 for ext in api.extensions: 3601 if ext.type != extType: 3602 continue 3603 if ext.depends is None: 3604 continue 3605 # memorize extension name and dependencies for future vector generation 3606 extensionList.append(ext.name) 3607 # memorize max extension name and dependency length 3608 maxExtLength = max(maxExtLength, len(ext.name)) 3609 # generate check function for this extension 3610 yield f'bool check_{ext.name}(const tcu::UVec2& v, const ExtPropVect& vIEP, const ExtPropVect& vDEP)' 3611 yield '{' 3612 # check if extension was promoted; for SC we need to check vulkan version as sc10 is based on vk12 3613 if ext.promotedto is not None and 'VK_VERSION' in ext.promotedto: 3614 p = ext.promotedto 3615 yield f'\tif (isCompatibile({p[-3]}, {p[-1]}, v))' 3616 yield '\t\treturn true;\n' 3617 else: 3618 yield '\tDE_UNREF(v);' 3619 # there is a high chance that other vector won't be used 3620 yield f'\tDE_UNREF({othVector});' 3621 # check if extension is supported 3622 yield f'\n\tif (!isSupported({extVector}, "{ext.name}"))' 3623 yield '\t\treturn true;\n' 3624 # replace dependent extensions/versions with proper conditions 3625 finalCondition = transformDependsToCondition(ext.depends, api, 'isCompatibile(%s, %s, v)', 'isSupported(%s, "%s")') 3626 yield f'\t// depends attribute in xml: {ext.depends}' 3627 yield f'\treturn {finalCondition};' 3628 yield '}\n' 3629 # save list of all device/instance extensions 3630 yield 'static const DependencyCheckVect {}ExtensionDependencies'.format(extType) 3631 yield '{' 3632 for ext in extensionList: 3633 extTabCount = (maxExtLength - len(ext)) / 4 3634 eTabs = '\t'*int(round(extTabCount+1.49)) 3635 yield f'\tstd::make_pair("{ext}",{eTabs}&check_{ext}),' 3636 yield '};\n' 3637 3638 def genApiVersions(): 3639 yield 'static const std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>\treleasedApiVersions[]\t=' 3640 yield '{' 3641 for f in reversed(api.features): 3642 apiVariant = '0' if f.api == 'vulkan' else '1' 3643 major, minor = f.number.split('.') 3644 version = (int(apiVariant) << 29) | (int(major) << 22) | (int(minor) << 12) 3645 yield '\tstd::make_tuple({}, {}, {}, {}),'.format(version, apiVariant, major, minor) 3646 yield '};' 3647 3648 def parseExtensionDependencies(extDeps, ext): 3649 major, minor = 1, 0 3650 requiredVerFound = False; 3651 # return in case nothing more left to be processed 3652 if extDeps is None or extDeps == "": 3653 return major, minor, requiredVerFound 3654 ungrpPartLen = 0 3655 versionPattern = "[A-Z]+_VERSION_([0-9]+)_([0-9]+)" 3656 ungroupedPattern = r"^.*?\(+|^.*?$" 3657 # look for non-grouped part, it may include the required vulkan version 3658 ungroupPart = re.search(ungroupedPattern, extDeps) 3659 if ungroupPart is not None and ungroupPart[0].replace(r"(", "") != "": 3660 ungrpPartLen = len(ungroupPart[0].replace(r"(", "")) 3661 # is specific version explicitly requested? 3662 match = re.search(versionPattern, ungroupPart[0]) 3663 if match is not None: 3664 if len(match[0]) != len(extDeps): 3665 # there is more than just a version; check if it's accompanied by AND operator(s) 3666 ext_pattern = ".*\+*"+versionPattern+"\++.*|.*\++"+versionPattern+"\+*.*" 3667 match = re.search(ext_pattern, ungroupPart[0]) 3668 if match is not None: 3669 # specific version is explicitly requested 3670 major, minor = int(match[1]), int(match[2]) 3671 return major, minor, True 3672 # no explicit version is requested, continue parsing the remaining part 3673 extDeps = extDeps[ungrpPartLen:] 3674 groupedPattern = r"(.*)\+|(.*)$" 3675 match = re.search(groupedPattern, extDeps) 3676 if match is not None and match[0] != "": 3677 # groups may include the dependency "promoted to" versions accompanied by OR operator 3678 # but they don't include the extension explicit required version; continue parsing the remaining part 3679 groupLength = len(match[0]) 3680 major, minor, requiredVerFound = parseExtensionDependencies(extDeps[groupLength:], ext) 3681 return major, minor, requiredVerFound 3682 3683 def genRequiredCoreVersions(): 3684 yield 'static const std::tuple<uint32_t, uint32_t, const char*>\textensionRequiredCoreVersion[]\t =' 3685 yield '{' 3686 versionPattern = "[A-Z]+_VERSION_([0-9]+)_([0-9]+)" 3687 for ext in api.extensions: 3688 # skip video extensions 3689 if 'vulkan_video_' in ext.name: 3690 continue 3691 major, minor = 1, 0 3692 if ext.depends is not None: 3693 major, minor, requiredVerFound = parseExtensionDependencies(ext.depends, ext) 3694 if not requiredVerFound: 3695 # find all extensions that are dependencies of this one 3696 matches = re.findall("VK_\w+", ext.depends, re.M) 3697 for m in matches: 3698 for de in api.extensions: 3699 if de.name == m: 3700 if de.depends is not None: 3701 # check if the dependency states explicitly the required vulkan version and pick the higher one 3702 newMajor, newMinor, requiredVerFound = parseExtensionDependencies(de.depends, de) 3703 if requiredVerFound: 3704 if newMajor > major: 3705 major, minor = newMajor, newMinor 3706 elif newMajor == major and newMinor > minor: 3707 minor = newMinor 3708 break 3709 yield '\tstd::make_tuple({}, {}, "{}"),'.format(major, minor, ext.name) 3710 yield '};' 3711 3712 stream = [] 3713 stream.extend(genHelperFunctions()) 3714 stream.extend(genExtDepArray('instance')) 3715 stream.extend(genExtDepArray('device')) 3716 stream.extend(genApiVersions()) 3717 stream.extend(genRequiredCoreVersions()) 3718 3719 writeInlFile(filename, INL_HEADER, stream) 3720 3721def writeEntryPointValidation(api, filename): 3722 # keys are instance extension names and value is list of device-level functions 3723 instExtDeviceFunDict = {} 3724 # iterate over all extensions and find instance extensions 3725 for ext in api.extensions: 3726 if ext.type == "instance": 3727 # iterate over all functions instance extension adds 3728 for requirement in ext.requirementsList: 3729 for extCommand in requirement.newCommands: 3730 # to get a type of command we need to find this command definition in list of all functions 3731 for command in api.functions: 3732 if extCommand.name == command.name or extCommand.name in command.aliasList: 3733 # check if this is device-level entry-point 3734 if command.getType() == Function.TYPE_DEVICE: 3735 if ext.name not in instExtDeviceFunDict: 3736 instExtDeviceFunDict[ext.name] = [] 3737 instExtDeviceFunDict[ext.name].append(extCommand.name) 3738 stream = ['std::map<std::string, std::vector<std::string> > instExtDeviceFun', '{'] 3739 for extName in instExtDeviceFunDict: 3740 stream.append(f'\t{{ "{extName}",\n\t\t{{') 3741 for fun in instExtDeviceFunDict[extName]: 3742 stream.append(f'\t\t\t"{fun}",') 3743 stream.append('\t\t}\n\t},') 3744 stream.append('};') 3745 writeInlFile(filename, INL_HEADER, stream) 3746 3747def writeGetDeviceProcAddr(api, filename): 3748 testBlockStart = '''tcu::TestStatus testGetDeviceProcAddr (Context& context) 3749{ 3750 tcu::TestLog& log (context.getTestContext().getLog()); 3751 const PlatformInterface& platformInterface = context.getPlatformInterface(); 3752 const auto validationEnabled = context.getTestContext().getCommandLine().isValidationEnabled(); 3753 const CustomInstance instance (createCustomInstanceFromContext(context)); 3754 const InstanceDriver& instanceDriver = instance.getDriver(); 3755 const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine()); 3756 const uint32_t queueFamilyIndex = 0; 3757 const uint32_t queueCount = 1; 3758 const float queuePriority = 1.0f; 3759 const std::vector<VkQueueFamilyProperties> queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice); 3760 3761 const VkDeviceQueueCreateInfo deviceQueueCreateInfo = 3762 { 3763 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; 3764 DE_NULL, // const void* pNext; 3765 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags; 3766 queueFamilyIndex, // uint32_t queueFamilyIndex; 3767 queueCount, // uint32_t queueCount; 3768 &queuePriority, // const float* pQueuePriorities; 3769 }; 3770 3771 const VkDeviceCreateInfo deviceCreateInfo = 3772 { 3773 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType; 3774 DE_NULL, // const void* pNext; 3775 (VkDeviceCreateFlags)0u, // VkDeviceCreateFlags flags; 3776 1u, // uint32_t queueCreateInfoCount; 3777 &deviceQueueCreateInfo, // const VkDeviceQueueCreateInfo* pQueueCreateInfos; 3778 0u, // uint32_t enabledLayerCount; 3779 DE_NULL, // const char* const* ppEnabledLayerNames; 3780 0u, // uint32_t enabledExtensionCount; 3781 DE_NULL, // const char* const* ppEnabledExtensionNames; 3782 DE_NULL, // const VkPhysicalDeviceFeatures* pEnabledFeatures; 3783 }; 3784 const Unique<VkDevice> device (createCustomDevice(validationEnabled, platformInterface, instance, instanceDriver, physicalDevice, &deviceCreateInfo)); 3785 const DeviceDriver deviceDriver (platformInterface, instance, device.get(), context.getUsedApiVersion(), context.getTestContext().getCommandLine()); 3786 3787 const std::vector<std::string> functions{''' 3788 testBlockEnd = ''' }; 3789 3790 bool fail = false; 3791 for (const auto& function : functions) 3792 { 3793 if (deviceDriver.getDeviceProcAddr(device.get(), function.c_str()) != DE_NULL) 3794 { 3795 fail = true; 3796 log << tcu::TestLog::Message << "Function " << function << " is not NULL" << tcu::TestLog::EndMessage; 3797 } 3798 } 3799 if (fail) 3800 return tcu::TestStatus::fail("Fail"); 3801 return tcu::TestStatus::pass("All functions are NULL"); 3802} 3803''' 3804 3805 def functions(functionType): 3806 for ext in api.extensions: 3807 for requirement in ext.requirementsList: 3808 for requiredCommand in requirement.newCommands: 3809 yield '\t\t"' + requiredCommand.name + '",' 3810 stream = [] 3811 stream.append('#include "tcuCommandLine.hpp"') 3812 stream.append('#include "vktTestCase.hpp"') 3813 stream.append('#include "vkPlatform.hpp"') 3814 stream.append('#include "vkDeviceUtil.hpp"') 3815 stream.append('#include "vkQueryUtil.hpp"') 3816 stream.append('#include "vktCustomInstancesDevices.hpp"') 3817 stream.append('#include "vktTestCase.hpp"') 3818 stream.append('#include "vktTestCaseUtil.hpp"') 3819 stream.append('\nnamespace vkt\n{\n') 3820 stream.append('using namespace vk;\n') 3821 stream.append(testBlockStart) 3822 stream.extend(functions(api)) 3823 stream.append(testBlockEnd) 3824 3825 # function to create tests 3826 stream.append("void addGetDeviceProcAddrTests (tcu::TestCaseGroup* testGroup)\n{") 3827 stream.append('\taddFunctionCase(testGroup, "non_enabled", testGetDeviceProcAddr);') 3828 stream.append('}\n') 3829 stream.append('}\n') 3830 3831 writeInlFile(filename, INL_HEADER, stream) 3832 3833def writeConformanceVersions(filename): 3834 # get list of all vulkan/vulkansc tags from git 3835 remote_urls = os.popen("git remote -v").read().split('\n') 3836 remote_url = None 3837 for line in remote_urls: 3838 if "gerrit.khronos.org:29418/vk-gl-cts" in line: 3839 remote_url = line.split()[1] 3840 break 3841 listOfTags = os.popen("git ls-remote -t %s" % (remote_url)).read() 3842 vkMatches = re.findall("vulkan-cts-(\d).(\d).(\d).(\d)", listOfTags, re.M) 3843 scMatches = re.findall("vulkansc-cts-(\d).(\d).(\d).(\d)", listOfTags, re.M) 3844 if len(vkMatches) == 0 or len(scMatches) == 0: 3845 return 3846 # read all text files in doc folder and find withdrawn cts versions (branches) 3847 withdrawnVkBranches = set() 3848 withdrawnScBranches = set() 3849 today = datetime.date.today() 3850 for fileName in glob.glob(os.path.join(os.path.dirname(__file__), "..", "doc", "*.txt")): 3851 if "withdrawal" not in fileName: 3852 continue 3853 fileContent = readFile(fileName) 3854 # get date when releases are withdrawn 3855 match = re.search(r"(20\d\d)-(\d\d)-(\d\d).+ withdrawn", fileContent, re.IGNORECASE) 3856 if match is not None: 3857 # check if announcement refers to date in the past 3858 if today > datetime.date(int(match[1]), int(match[2]), int(match[3])): 3859 # get names of withdrawn branches 3860 vkBranchMatches = re.findall("vulkan(\w\w)?-cts-(\d).(\d).(\d).(\d)", fileContent, re.M) 3861 for v in vkBranchMatches: 3862 selectedSet = withdrawnScBranches if v[0] == "sc" else withdrawnVkBranches 3863 selectedSet.add((v[1], v[2], v[3], v[4])) 3864 if len(withdrawnVkBranches) == 0: 3865 print(f"Warning: unable to read content of doc folder, skipping generation of {os.path.basename(filename)}") 3866 return 3867 # define helper function that will be used to add entries for both vk and sc 3868 def appendToStream(stream, versionsToAdd, maxWithdrawnVersion): 3869 addedVersions = set() 3870 for v in reversed(versionsToAdd): 3871 # add only unique versions; ignore duplicates (e.g. with "-rc1", "-rc2" postfix); 3872 # also add versions that are greater then maximal withdrawn version 3873 if v in addedVersions or v <= maxWithdrawnVersion: 3874 continue 3875 addedVersions.add(v) 3876 stream.append(f'\tmakeConformanceVersion({v[0]}, {v[1]}, {v[2]}, {v[3]}),') 3877 # save array with versions 3878 stream = ['static const VkConformanceVersion knownConformanceVersions[]',\ 3879 '{',\ 3880 '#ifndef CTS_USES_VULKANSC'] 3881 appendToStream(stream, vkMatches, max(withdrawnVkBranches)) 3882 stream.append('#else') 3883 appendToStream(stream, scMatches, tuple('0'*4) if len(withdrawnScBranches) == 0 else max(withdrawnScBranches)) 3884 stream.append('#endif // CTS_USES_VULKANSC') 3885 stream.append('};') 3886 writeInlFile(filename, INL_HEADER, stream) 3887 3888def parseCmdLineArgs(): 3889 parser = argparse.ArgumentParser(description = "Generate Vulkan INL files", 3890 formatter_class=argparse.ArgumentDefaultsHelpFormatter) 3891 parser.add_argument("-a", 3892 "--api", 3893 dest="api", 3894 default="", 3895 help="Choose between Vulkan and Vulkan SC") 3896 parser.add_argument("-o", 3897 "--outdir", 3898 dest="outdir", 3899 default="", 3900 help="Choose output directory") 3901 parser.add_argument("-v", "--verbose", 3902 dest="verbose", 3903 action="store_true", 3904 help="Enable verbose logging") 3905 return parser.parse_args() 3906 3907if __name__ == "__main__": 3908 args = parseCmdLineArgs() 3909 3910 # if argument was specified it is interpreted as a path to which .inl files will be written 3911 outputPath = DEFAULT_OUTPUT_DIR[args.api] if args.outdir == '' else args.outdir 3912 3913 vkTree = etree.parse(os.path.join(VULKAN_XML_DIR, "vk.xml")) 3914 apiName = "vulkansc" if args.api == 'SC' else "vulkan" 3915 stripNonmatchingAPIs(vkTree.getroot(), apiName, actuallyDelete = True) 3916 3917 # Read vk.xml and generate vulkan headers from it 3918 api = API(apiName) 3919 api.build(vkTree) 3920 api.postProcess() 3921 3922 # Read video.xml 3923 if args.api != 'SC': 3924 api.build( etree.parse(os.path.join(VULKAN_XML_DIR, "video.xml")) ) 3925 3926 platformFuncs = [Function.TYPE_PLATFORM] 3927 instanceFuncs = [Function.TYPE_INSTANCE] 3928 deviceFuncs = [Function.TYPE_DEVICE] 3929 3930 dfd = generateDeviceFeaturesOrPropertiesDefs(api, 'Features') 3931 writeDeviceFeatures (api, dfd, os.path.join(outputPath, "vkDeviceFeatures.inl")) 3932 writeDeviceFeaturesDefaultDeviceDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForDefaultDeviceDefs.inl")) 3933 writeDeviceFeaturesContextDecl (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDecl.inl")) 3934 writeDeviceFeaturesContextDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDefs.inl")) 3935 writeDeviceFeatureTest (api, os.path.join(outputPath, "vkDeviceFeatureTest.inl")) 3936 3937 dpd = generateDeviceFeaturesOrPropertiesDefs(api, 'Properties') 3938 writeDeviceProperties (api, dpd, os.path.join(outputPath, "vkDeviceProperties.inl")) 3939 writeDevicePropertiesDefaultDeviceDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForDefaultDeviceDefs.inl")) 3940 writeDevicePropertiesContextDecl (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDecl.inl")) 3941 writeDevicePropertiesContextDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDefs.inl")) 3942 3943 writeHandleType (api, os.path.join(outputPath, "vkHandleType.inl")) 3944 writeBasicTypes (api, os.path.join(outputPath, "vkBasicTypes.inl")) 3945 writeCompositeTypes (api, os.path.join(outputPath, "vkStructTypes.inl")) 3946 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualPlatformInterface.inl"), platformFuncs, False) 3947 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualInstanceInterface.inl"), instanceFuncs, False) 3948 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualDeviceInterface.inl"), deviceFuncs, False) 3949 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcretePlatformInterface.inl"), platformFuncs, True) 3950 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteInstanceInterface.inl"), instanceFuncs, True) 3951 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteDeviceInterface.inl"), deviceFuncs, True) 3952 writeFunctionPtrTypes (api, os.path.join(outputPath, "vkFunctionPointerTypes.inl")) 3953 writeFunctionPointers (api, os.path.join(outputPath, "vkPlatformFunctionPointers.inl"), platformFuncs) 3954 writeFunctionPointers (api, os.path.join(outputPath, "vkInstanceFunctionPointers.inl"), instanceFuncs) 3955 writeFunctionPointers (api, os.path.join(outputPath, "vkDeviceFunctionPointers.inl"), deviceFuncs) 3956 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr") 3957 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitInstanceFunctionPointers.inl"), instanceFuncs) 3958 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitDeviceFunctionPointers.inl"), deviceFuncs) 3959 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver") 3960 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver") 3961 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver") 3962 if args.api=='SC': 3963 writeFuncPtrInterfaceSCImpl (api, os.path.join(outputPath, "vkDeviceDriverSCImpl.inl"), deviceFuncs, "DeviceDriverSC") 3964 writeStrUtilProto (api, os.path.join(outputPath, "vkStrUtil.inl")) 3965 writeStrUtilImpl (api, os.path.join(outputPath, "vkStrUtilImpl.inl")) 3966 writeRefUtilProto (api, os.path.join(outputPath, "vkRefUtil.inl")) 3967 writeRefUtilImpl (api, os.path.join(outputPath, "vkRefUtilImpl.inl")) 3968 writeStructTraitsImpl (api, os.path.join(outputPath, "vkGetStructureTypeImpl.inl")) 3969 writeNullDriverImpl (api, os.path.join(outputPath, "vkNullDriverImpl.inl")) 3970 writeTypeUtil (api, os.path.join(outputPath, "vkTypeUtil.inl")) 3971 writeSupportedExtensions (api, os.path.join(outputPath, "vkSupportedExtensions.inl")) 3972 writeCoreFunctionalities (api, os.path.join(outputPath, "vkCoreFunctionalities.inl")) 3973 writeExtensionFunctions (api, os.path.join(outputPath, "vkExtensionFunctions.inl")) 3974 writeDeviceFeatures2 (api, os.path.join(outputPath, "vkDeviceFeatures2.inl")) 3975 writeMandatoryFeatures (api, os.path.join(outputPath, "vkMandatoryFeatures.inl")) 3976 writeExtensionList (api, os.path.join(outputPath, "vkInstanceExtensions.inl"), 'instance') 3977 writeExtensionList (api, os.path.join(outputPath, "vkDeviceExtensions.inl"), 'device') 3978 writeDriverIds (api, os.path.join(outputPath, "vkKnownDriverIds.inl")) 3979 writeObjTypeImpl (api, os.path.join(outputPath, "vkObjTypeImpl.inl")) 3980 writeApiExtensionDependencyInfo (api, os.path.join(outputPath, "vkApiExtensionDependencyInfo.inl")) 3981 writeEntryPointValidation (api, os.path.join(outputPath, "vkEntryPointValidation.inl")) 3982 writeGetDeviceProcAddr (api, os.path.join(outputPath, "vkGetDeviceProcAddr.inl")) 3983 #writeConformanceVersions ( os.path.join(outputPath, "vkKnownConformanceVersions.inl")) 3984 3985 # NOTE: when new files are generated then they should also be added to the 3986 # vk-gl-cts\external\vulkancts\framework\vulkan\CMakeLists.txt outputs list 3987