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