1 # -*- coding: utf-8 -*-
3 #-------------------------------------------------------------------------
7 # Copyright (c) 2015 Google Inc.
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
13 # http://www.apache.org/licenses/LICENSE-2.0
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.
21 #-------------------------------------------------------------------------
30 from lxml import etree
31 from itertools import chain
32 from collections import OrderedDict
34 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
36 from build.common import DEQP_DIR, execute
37 from khr_util.format import indentLines, writeInlFile
39 VULKAN_XML_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "xml")
40 SCRIPTS_SRC_DIR = os.path.join(os.path.dirname(__file__), "src")
41 DEFAULT_OUTPUT_DIR = { "" : os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkan"),
42 "SC" : os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkansc") }
45 /* WARNING: This is auto-generated file. Do not modify, since changes will
46 * be lost! Modify the generating script instead.
47 * This file was generated by /scripts/gen_framework.py
53 "VK_MAX_PHYSICAL_DEVICE_NAME_SIZE": "size_t",
54 "VK_MAX_EXTENSION_NAME_SIZE": "size_t",
55 "VK_MAX_DRIVER_NAME_SIZE": "size_t",
56 "VK_MAX_DRIVER_INFO_SIZE": "size_t",
57 "VK_UUID_SIZE": "size_t",
58 "VK_LUID_SIZE": "size_t",
59 "VK_MAX_MEMORY_TYPES": "size_t",
60 "VK_MAX_MEMORY_HEAPS": "size_t",
61 "VK_MAX_DESCRIPTION_SIZE": "size_t",
62 "VK_MAX_DEVICE_GROUP_SIZE": "size_t",
63 "VK_ATTACHMENT_UNUSED": "uint32_t",
64 "VK_SUBPASS_EXTERNAL": "uint32_t",
65 "VK_QUEUE_FAMILY_IGNORED": "uint32_t",
66 "VK_QUEUE_FAMILY_EXTERNAL": "uint32_t",
67 "VK_REMAINING_MIP_LEVELS": "uint32_t",
68 "VK_REMAINING_ARRAY_LAYERS": "uint32_t",
69 "VK_WHOLE_SIZE": "vk::VkDeviceSize",
70 "VK_TRUE": "vk::VkBool32",
71 "VK_FALSE": "vk::VkBool32",
76 (["Display","*"], ["XlibDisplayPtr"], "void*"),
77 (["Window"], ["XlibWindow"], "uintptr_t",),
78 (["VisualID"], ["XlibVisualID"], "uint32_t"),
81 (["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"),
82 (["xcb_window_t"], ["XcbWindow"], "uintptr_t"),
83 (["xcb_visualid_t"], ["XcbVisualid"], "uint32_t"),
85 # VK_KHR_wayland_surface
86 (["struct", "wl_display","*"], ["WaylandDisplayPtr"], "void*"),
87 (["struct", "wl_surface", "*"], ["WaylandSurfacePtr"], "void*"),
90 (["MirConnection", "*"], ["MirConnectionPtr"], "void*"),
91 (["MirSurface", "*"], ["MirSurfacePtr"], "void*"),
93 # VK_KHR_android_surface
94 (["ANativeWindow", "*"], ["AndroidNativeWindowPtr"], "void*"),
96 # VK_KHR_win32_surface
97 (["HINSTANCE"], ["Win32InstanceHandle"], "void*"),
98 (["HWND"], ["Win32WindowHandle"], "void*"),
99 (["HANDLE"], ["Win32Handle"], "void*"),
100 (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"),
101 (["AHardwareBuffer", "*"], ["AndroidHardwareBufferPtr"], "void*"),
102 (["HMONITOR"], ["Win32MonitorHandle"], "void*"),
103 (["LPCWSTR"], ["Win32LPCWSTR"], "const void*"),
105 # VK_EXT_acquire_xlib_display
106 (["RROutput"], ["RROutput"], "void*"),
108 (["zx_handle_t"], ["zx_handle_t"], "uint32_t"),
109 (["GgpFrameToken"], ["GgpFrameToken"], "int32_t"),
110 (["GgpStreamDescriptor"], ["GgpStreamDescriptor"], "int32_t"),
111 (["CAMetalLayer"], ["CAMetalLayer"], "void*"),
112 (["struct", "_screen_context", "*"], ["QNXScreenContextPtr"], "void*"),
113 (["struct", "_screen_window", "*"], ["QNXScreenWindowPtr"], "void*"),
115 # VK_EXT_metal_objects
116 (["MTLDevice_id"], ["MTLDevice_id"], "void*"),
117 (["MTLCommandQueue_id"], ["MTLCommandQueue_id"], "void*"),
118 (["MTLBuffer_id"], ["MTLBuffer_id"], "void*"),
119 (["MTLTexture_id"], ["MTLTexture_id"], "void*"),
120 (["IOSurfaceRef"], ["IOSurfaceRef"], "void*"),
121 (["MTLSharedEvent_id"], ["MTLSharedEvent_id"], "void*"),
124 PLATFORM_TYPE_NAMESPACE = "pt"
126 TYPE_SUBSTITUTIONS = [
128 ("DWORD", "uint32_t"),
129 ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
132 EXTENSION_POSTFIXES_STANDARD = ["KHR", "EXT"]
133 EXTENSION_POSTFIXES_VENDOR = ["AMD", "ARM", "NV", 'INTEL', "NVX", "KHX", "NN", "MVK", "FUCHSIA", 'QCOM', "GGP", "QNX", "ANDROID", 'VALVE', 'HUAWEI']
134 EXTENSION_POSTFIXES = EXTENSION_POSTFIXES_STANDARD + EXTENSION_POSTFIXES_VENDOR
136 def substituteType(object): # both CompositeMember and FunctionArgument can be passed to this function
137 for src, dst in TYPE_SUBSTITUTIONS:
138 object.type = object.type.replace(src, dst)
139 for platformType, substitute, _ in PLATFORM_TYPES:
140 platformTypeName = platformType[0]
141 platformTypeName = platformType[-2] if "*" in platformType else platformType[0]
142 if object.type == platformTypeName:
143 object.type = PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]
144 object.qualifiers = None if 'struct' in platformType else object.qualifiers
145 object.qualifiers = None if 'const' in platformType else object.qualifiers
146 if "*" in platformType:
147 object.pointer = "*" if object.pointer == "**" else None
150 def __init__ (self, name, aType, alias, value):
157 def __init__ (self, name, aType, alias, parent, objtypeenum):
162 self.objtypeenum = objtypeenum
165 def __init__ (self, name, aType, requires, bitvalues):
168 self.alias = None # initialy None but may be filled while parsing next tag
169 self.requires = requires
170 self.bitvalues = bitvalues
173 def __init__ (self, name, value, bitpos):
175 self.aliasList = [] # list of strings
176 self.value = value # some enums specify value and some bitpos
178 self.extension = None # name of extension that added this enumerator
181 def __init__ (self, name):
183 self.alias = None # name of enum alias or None
184 self.type = None # enum or bitmask
186 self.enumeratorList = [] # list of Enumerator objects
188 def areValuesLinear (self):
189 if self.type == 'bitmask':
192 for enumerator in self.enumeratorList:
193 intValue = parseInt(enumerator.value)
194 if intValue != curIndex:
199 class CompositeMember:
200 def __init__ (self, name, aType, pointer, qualifiers, arraySizeList, optional, limittype, values, fieldWidth):
202 self.type = aType # member type
203 self.pointer = pointer # None, '*' or '**'
204 self.qualifiers = qualifiers # 'const' or 'struct' or None
205 self.arraySizeList = arraySizeList # can contain digits or enums
206 self.optional = optional
207 self.limittype = limittype
208 self.values = values # allowed member values
209 self.fieldWidth = fieldWidth # ':' followed by number of bits
211 # check if type should be swaped
215 def __init__ (self, name, category, allowduplicate, structextends, returnedonly, members):
217 self.category = category # is it struct or union
218 self.aliasList = [] # most composite types have single alias but there are cases like VkPhysicalDeviceVariablePointersFeatures that have 3
219 self.allowduplicate = allowduplicate
220 self.structextends = structextends
221 self.returnedonly = returnedonly
222 self.members = members # list of CompositeMember objects
224 class FunctionArgument:
225 def __init__ (self, name, qualifiers, aType, pointer = None, secondPointerIsConst = False, arraySize = None):
227 self.qualifiers = qualifiers
229 self.pointer = pointer # None, '*' or '**'
230 self.secondPointerIsConst = secondPointerIsConst
231 self.arraySize = arraySize
233 # check if type should be swaped
237 TYPE_PLATFORM = 0 # Not bound to anything
238 TYPE_INSTANCE = 1 # Bound to VkInstance
239 TYPE_DEVICE = 2 # Bound to VkDevice
241 def __init__ (self, name, returnType = None, arguments = None):
244 self.returnType = returnType
245 self.arguments = arguments # list of FunctionArgument objects
246 self.functionType = Function.TYPE_PLATFORM
248 # Determine function type based on first argument but use TYPE_PLATFORM for vkGetInstanceProcAddr
249 if self.name == "vkGetInstanceProcAddr":
251 assert len(self.arguments) > 0
252 firstArgType = self.arguments[0].type
253 if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
254 self.functionType = Function.TYPE_INSTANCE
255 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
256 self.functionType = Function.TYPE_DEVICE
259 return self.functionType
261 class FeatureRequirement:
262 def __init__ (self, comment, enumList, typeList, commandList):
263 self.comment = comment
264 self.enumList = enumList
265 self.typeList = typeList
266 self.commandList = commandList # list of strings, each representing required function
269 def __init__ (self, api, name, number, requirementsList):
273 self.requirementsList = requirementsList # list of FeatureRequirement objects
275 class ExtensionEnumerator:
276 def __init__ (self, name, extends, alias, value, extnumber, offset, comment):
278 self.extends = extends
281 self.extnumber = extnumber
283 self.comment = comment # note: comment is used to mark not promoted features for partially promoted extensions
285 class ExtensionCommand:
286 def __init__ (self, name, comment):
288 self.comment = comment
291 def __init__ (self, name, comment):
293 self.comment = comment
295 class ExtensionRequirements:
296 def __init__ (self, extensionName, extendedEnums, newCommands, newTypes):
297 self.extensionName = extensionName # None when requirements apply to all implementations of extension;
298 # string with extension name when requirements apply to implementations that also support given extension
299 self.extendedEnums = extendedEnums # list of ExtensionEnumerator objects
300 self.newCommands = newCommands # list of ExtensionCommand objects
301 self.newTypes = newTypes # list of ExtensionType objects
304 def __init__ (self, name, number, type, requiresCore, requiredExtensions, platform, promotedto, partiallyPromoted, requirementsList):
305 self.name = name # extension name
306 self.number = number # extension version
307 self.type = type # extension type - "device" or "instance"
308 self.requiresCore = requiresCore # required core vulkan version e.g. "1.1"
309 self.requiredExtensions = requiredExtensions # list of extensions names that also need to be available on implementation or None
310 self.platform = platform # None, "win32", "ios", "android" etc.
311 self.promotedto = promotedto # vulkan version, other extension or None
312 self.partiallyPromoted = partiallyPromoted # when True then some of requirements were not promoted
313 self.requirementsList = requirementsList # list of ExtensionRequirements objects
318 self.basetypes = {} # dictionary, e.g. one of keys is VkFlags and its value is uint32_t
321 self.bitmasks = [] # list of Bitmask objects
322 self.enums = [] # list of Enum objects - each contains individual enum definition (including extension enums)
323 self.compositeTypes = [] # list of Composite objects - each contains individual structure/union definition (including extension structures)
324 self.functions = [] # list of Function objects - each contains individual command definition (including extension functions)
325 self.features = [] # list of Feature objects
326 self.extensions = [] # list of Extension objects - each contains individual extension definition
327 self.basicCTypes = [] # list of basic C types e.g. 'void', 'int8_t'
328 self.tempAliasesList = [] # list of touples used to handle aliases for enumerators that will be defined later
330 # read all files from extensions directory
331 additionalExtensionData = {}
332 for fileName in glob.glob(os.path.join(SCRIPTS_SRC_DIR, "extensions", "*.json")):
333 if "schema.json" in fileName:
335 extensionName = os.path.basename(fileName)[:-5]
336 fileContent = readFile(fileName)
338 additionalExtensionData[extensionName] = json.loads(fileContent)
339 except ValueError as err:
340 print("Error in %s: %s" % (os.path.basename(fileName), str(err)))
342 self.additionalExtensionData = sorted(additionalExtensionData.items(), key=lambda e: e[0])
344 def addOrUpdateEnumerator (self, enumeratorNode, enumDefinition, extensionNumber = None):
345 name = enumeratorNode.get("name")
346 alias = enumeratorNode.get("alias")
347 # if enumerator node has alias atribute then update existing enumerator
348 if alias is not None:
349 for e in reversed(enumDefinition.enumeratorList):
350 if alias == e.name or alias in e.aliasList:
351 # make sure same alias is not already on the list; this handles special case like
352 # VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR alais which is defined in three places
353 if name not in e.aliasList:
354 e.aliasList.append(name)
356 # there are cases where alias is specified for enumerator that wasn't yet defined,
357 # we need to remember those aliases and assign them after we parse whole xml
358 self.tempAliasesList.append((enumDefinition, name, alias))
360 # calculate enumerator value if offset attribute is present
361 value = enumeratorNode.get("value")
363 value = enumeratorNode.get("offset")
364 if value is not None:
365 # check if extensionNumber should be overridden
366 extnumber = enumeratorNode.get("extnumber")
367 if extnumber is not None:
368 extensionNumber = extnumber
369 value = 1000000000 + (int(extensionNumber)-1) * 1000 + int(value)
370 # check if value should be negative
371 dir = enumeratorNode.get("dir")
374 # convert to string so that type matches the type in which values
375 # are stored for enums that were read from enums xml section
378 enumDefinition.enumeratorList.append(Enumerator(
381 enumeratorNode.get("bitpos")
384 def readEnum (self, enumsNode):
385 enumName = enumsNode.get("name")
386 # special case for vulkan hardcoded constants that are specified as enum in vk.xml
387 if enumName == "API Constants":
388 for enumItem in enumsNode:
389 self.defines.append(Define(
390 enumItem.get("name"),
391 enumItem.get("type"),
392 enumItem.get("alias"),
393 enumItem.get("value")
396 # initial enum definition is read while processing types section;
397 # we need to find this enum definition and add data to it
398 enumDefinition = [enumDef for enumDef in self.enums if enumName == enumDef.name][0]
399 # add type and bitwidth to enum definition
400 enumDefinition.type = enumsNode.get("type")
401 enumDefinition.bitwidth = enumsNode.get("bitwidth")
402 if enumDefinition.bitwidth is None:
403 enumDefinition.bitwidth = "32"
404 # add components to enum definition
405 for enumeratorItem in enumsNode:
407 if enumeratorItem.tag != "enum":
409 self.addOrUpdateEnumerator(enumeratorItem, enumDefinition)
411 def readCommand (self, commandNode):
412 protoNode = None # proto is a first child of every command node
413 # check if this is alias
414 alias = commandNode.get("alias")
415 # if node is alias then use the fact that alias definition follows aliased structure
416 if alias is not None:
417 # aliased command has usually been added recently, so we iterate in reverse order
419 for f in reversed(self.functions):
420 found = (f.name == alias)
422 f.aliasList.append(commandNode.get("name"))
427 # memorize all parameters
429 for paramNode in commandNode:
430 # memorize prototype node
431 if paramNode.tag == "proto":
432 protoNode = paramNode
434 # skip implicitexternsyncparams
435 if paramNode.tag != "param":
437 nameNode = paramNode.find("name")
438 typeNode = paramNode.find("type")
439 starCount = typeNode.tail.count('*')
440 functionParams.append(FunctionArgument(
443 paramNode.find("type").text,
444 '*' * starCount if starCount > 0 else None,
445 'const' in typeNode.tail,
448 # memorize whole function
449 self.functions.append(Function(
450 protoNode.find("name").text,
451 protoNode.find("type").text,
455 def readExtension (self, extensionNode):
456 # skip disabled extensions
457 if extensionNode.get("supported") == "disabled":
459 extensionName = extensionNode.get("name")
460 extensionNumber = extensionNode.get("number")
461 partiallyPromoted = False
462 # before reading extension data first read extension
463 # requirements by iterating over all require tags
464 requirementsList = []
465 for requireItem in extensionNode:
469 # iterate over all children in current require tag
470 # and add them to proper list
471 for individualRequirement in requireItem:
472 requirementName = individualRequirement.get("name")
473 requirementComment = individualRequirement.get("comment")
474 # check if this requirement was not promoted and mark
475 # this extension as not fully promoted
476 if requirementComment is not None and "Not promoted to" in requirementComment:
477 partiallyPromoted = True
478 # check if this requirement describes enum, command or type
479 if individualRequirement.tag == "enum":
480 extendedEnumName = individualRequirement.get("extends")
481 extendedEnums.append(ExtensionEnumerator(
484 individualRequirement.get("alias"),
485 individualRequirement.get("value"),
486 individualRequirement.get("extnumber"),
487 individualRequirement.get("offset"),
489 # add enumerator to proper enum from api.enums
490 if extendedEnumName is not None:
491 newEnumerator = individualRequirement.get("name")
492 # find extendedEnumName in self.enums
493 matchedEnum = [enum for enum in self.enums if enum.name == extendedEnumName][0]
494 # add enumerator only when it is not already in enum
495 if len([e for e in matchedEnum.enumeratorList if e.name == newEnumerator]) == 0:
496 self.addOrUpdateEnumerator(individualRequirement, matchedEnum, extensionNumber)
497 elif individualRequirement.tag == "command":
498 newCommands.append(ExtensionCommand(requirementName, requirementComment))
499 elif individualRequirement.tag == "type":
500 newTypes.append(ExtensionType(requirementName, requirementComment))
501 elif individualRequirement.tag == "comment" and "not promoted to" in individualRequirement.text:
502 # partial promotion of VK_EXT_ycbcr_2plane_444_formats and VK_EXT_4444_formats
503 # is marked with comment tag in first require section
504 partiallyPromoted = True
505 # construct requirement object and add it to the list
506 requirementsList.append(ExtensionRequirements(
507 requireItem.get("extension"), # extensionName
508 extendedEnums, # extendedEnums
509 newCommands, # newCommands
512 # read extensions that need to be supported when current extension is suported;
513 # in xml this is single comma separated string, we split it to list of strings
514 requiredExtensions = extensionNode.get("requires")
515 if requiredExtensions is not None:
516 requiredExtensions = requiredExtensions.split(',')
517 # add extension definition to api object
518 self.extensions.append(Extension(
519 extensionName, # name
520 extensionNumber, # number
521 extensionNode.get("type"), # type
522 extensionNode.get("requiresCore"), # requiresCore
523 requiredExtensions, # requiredExtensions
524 extensionNode.get("platform"), # platform
525 extensionNode.get("promotedto"), # promotedto
526 partiallyPromoted, # partiallyPromoted
527 requirementsList # requirementsList
530 def readFeature (self, featureNode):
531 requirementsList = []
532 for requirementGroup in featureNode:
536 for requirement in requirementGroup:
537 requirementName = requirement.get("name")
538 if requirement.tag == "enum":
539 enumList.append(requirementName)
540 extendedEnumName = requirement.get("extends")
541 if extendedEnumName is not None:
542 # find extended enum in api.enums list
544 if extendedEnumName == e.name:
545 # read enumerator and add it to enum
546 self.addOrUpdateEnumerator(requirement, e)
548 elif requirement.tag == "type":
549 typeList.append(requirementName)
550 elif requirement.tag == "command":
551 commandList.append(requirementName)
552 requirementsList.append(FeatureRequirement(
553 requirementGroup.get("comment"),
558 self.features.append(Feature(
559 featureNode.get("api"),
560 featureNode.get("name"),
561 featureNode.get("number"),
565 def readType (self, typeNode):
566 name = typeNode.get("name")
567 alias = typeNode.get("alias")
568 category = typeNode.get("category")
569 if category == "enum":
571 self.enums.append(Enum(name))
573 for e in reversed(self.enums):
577 elif category == "handle":
580 name = typeNode.find("name").text
581 type = typeNode.find("type").text
582 self.handles.append(Handle(
586 typeNode.get("parent"),
587 typeNode.get("objtypeenum"),
590 for h in reversed(self.handles):
594 elif category == "basetype":
595 # processing only those basetypes that have type child
596 type = typeNode.find("type")
598 self.basetypes[typeNode.find("name").text] = type.text
599 elif category == "bitmask":
600 # if node is alias then use the fact that alias definition follows aliased bitmasks;
601 # in majoriti of cases it follows directly aliased bitmasks but in some cases there
602 # is a unrelated bitmasks definition in between - to handle this traverse in reverse order
603 if alias is not None:
604 for bm in reversed(self.bitmasks):
609 self.bitmasks.append(Bitmask(
610 typeNode.find("name").text,
611 typeNode.find("type").text,
612 typeNode.get("requires"),
613 typeNode.get("bitvalues")
615 elif category in ["struct", "union"]:
616 # if node is alias then use the fact that alias definition follows aliased structure;
617 # in majoriti of cases it follows directly aliased structure but in some cases there
618 # is a unrelated structure definition in between - to handle this traverse in reverse order
619 if alias is not None:
620 for ct in reversed(self.compositeTypes):
622 ct.aliasList.append(name)
626 # read structure members
628 for memberNode in typeNode:
629 if memberNode.tag != "member":
631 # handle enum nodes that can be used for arrays
633 for node in memberNode:
634 if node.tag == "enum":
635 arraySizeList.append(node.text)
636 # handle additional text after name tag; it can represent array
637 # size like in VkPipelineFragmentShadingRateEnumStateCreateInfoNV
638 # or number of bits like in VkAccelerationStructureInstanceKHR
639 nameNode = memberNode.find("name")
640 nameTail = nameNode.tail
644 fieldWidth = nameTail.replace(':', '').replace(' ', '')
645 elif '[' in nameTail and ']' in nameTail:
646 nameTail = nameTail.replace(']', ' ').replace('[', ' ')
647 arraySizeList = nameTail.split()
648 # handle additional text after type tag; it can represent pointers like *pNext
649 memberTypeNode = memberNode.find("type")
650 pointer = memberTypeNode.tail.strip() if memberTypeNode.tail is not None else None
651 structMembers.append(CompositeMember(
652 nameNode.text, # name
653 memberTypeNode.text, # type
655 memberNode.text, # qualifiers
656 arraySizeList, # arraySizeList
657 memberNode.get("optional"), # optional
658 memberNode.get("limittype"), # limittype
659 memberNode.get("values"), # values
660 fieldWidth # fieldWidth
662 # create structure definition
663 self.compositeTypes.append(Composite(
666 typeNode.get("allowduplicate"),
667 typeNode.get("structextends"),
668 typeNode.get("returnedonly"),
671 elif category == "define":
672 if typeNode.get("requires") == "VK_MAKE_API_VERSION":
673 value = typeNode.find("type").tail
674 value = 'VK_MAKE_API_VERSION' + value[:value.find(')')+1]
675 self.defines.append(Define(
676 typeNode.find("name").text,
682 requires = typeNode.get("requires")
683 if requires == 'vk_platform':
684 self.basicCTypes.append(name)
686 def build (self, rawVkXml):
687 # iterate over all *.xml root children
688 for rootChild in rawVkXml.getroot():
690 # each enum is defined in separate enums node directly under root node
691 if rootChild.tag == "enums":
692 self.readEnum(rootChild)
694 # read function definitions
695 if rootChild.tag == "commands":
696 commandsNode = rootChild
697 for commandItem in commandsNode:
698 self.readCommand(commandItem)
700 # read vulkan versions
701 if rootChild.tag == "feature":
702 self.readFeature(rootChild)
705 if rootChild.tag == "extensions":
706 extensionsNode = rootChild
707 for extensionItem in extensionsNode:
708 self.readExtension(extensionItem)
710 # "types" is a first child of root so it's optimal to check for it
711 # last and don't repeat this check for all other iterations
712 if rootChild.tag == "types":
713 typesNode = rootChild
714 for typeItem in typesNode:
715 self.readType(typeItem)
717 def postProcess (self):
718 def removeExtensionFromApi(extName, structureNameList, commandNameList):
719 extObjectList = [e for e in api.extensions if e.name == extName]
720 if len(extObjectList) > 0:
721 api.extensions.remove(extObjectList[0])
722 structObjectList = [ct for ct in api.compositeTypes if ct.name in structureNameList]
723 for s in structObjectList:
724 api.compositeTypes.remove(s)
725 commandObjectList = [f for f in api.functions if f.name in commandNameList]
726 for f in commandObjectList:
727 api.functions.remove(f)
729 # remove structures and commands added by VK_EXT_directfb_surface extension
730 removeExtensionFromApi("VK_EXT_directfb_surface",
731 ["VkDirectFBSurfaceCreateFlagsEXT", "VkDirectFBSurfaceCreateInfoEXT"],
732 ["vkCreateDirectFBSurfaceEXT", "vkGetPhysicalDeviceDirectFBPresentationSupportEXT"])
734 # remove structures and commands added by disabled VK_ANDROID_native_buffer extension;
735 # disabled extensions aren't read but their structures and commands will be in types and commands sections in vk.xml
736 removeExtensionFromApi("VK_ANDROID_native_buffer",
737 ["VkNativeBufferANDROID", "VkSwapchainImageCreateInfoANDROID",
738 "VkPhysicalDevicePresentationPropertiesANDROID", "VkNativeBufferUsage2ANDROID",
739 "VkSwapchainImageUsageFlagBitsANDROID", "VkSwapchainImageUsageFlagsANDROID"],
740 ["vkGetSwapchainGrallocUsageANDROID", "vkAcquireImageANDROID",
741 "vkQueueSignalReleaseImageANDROID", "vkGetSwapchainGrallocUsage2ANDROID"])
743 # remove empty enums e.g. VkQueryPoolCreateFlagBits, VkDeviceCreateFlagBits
744 enumsToRemove = [enum for enum in self.enums if len(enum.enumeratorList) == 0]
745 for er in enumsToRemove:
746 self.enums.remove(er)
748 # add aliases to enumerators that were defined after alias (there are ~10 cases like that in vk.xml)
749 for tmpAliasTouple in self.tempAliasesList:
750 (enum, name, alias) = tmpAliasTouple
751 for e in enum.enumeratorList:
753 e.aliasList.append(name)
755 self.tempAliasesList = None
757 # add alias for VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR (in vk.xml for this struct alias is defined before struct
758 # where in all other cases it is defined after structure definition)
759 barycentricFeaturesStruct = [c for c in api.compositeTypes if c.name == 'VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR'][0]
760 barycentricFeaturesStruct.aliasList.append('VkPhysicalDeviceFragmentShaderBarycentricFeaturesNV')
762 # sort enumerators in enums
763 sortLambda = lambda enumerator: int(enumerator.bitpos) if enumerator.value is None else int(enumerator.value, 16 if 'x' in enumerator.value else 10)
764 for enum in self.enums:
765 # skip enums that have no items in enumeratorList (e.g. VkQueryPoolCreateFlagBits) or just one item
766 if len(enum.enumeratorList) < 2:
768 # construct list of enumerators in which value and bitpos are not None
769 enumeratorsToSort = [e for e in enum.enumeratorList if e.value != e.bitpos]
770 # construct list of enumerators in which value and bitpos are equal to None
771 remainingEnumerators = [e for e in enum.enumeratorList if e.value == e.bitpos]
772 # construct sorted enumerator list with aliases at the end
773 enum.enumeratorList = sorted(enumeratorsToSort, key=sortLambda)
774 enum.enumeratorList.extend(remainingEnumerators)
776 def prefixName (prefix, name):
777 name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
778 name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
782 def parseInt (value):
783 return int(value, 16 if (value[:2] == "0x") else 10)
785 def getApiVariantIndexByName(variantName):
791 return apiVariant[variantName]
793 def getApiVariantNameByIndex(variantIndex):
799 return apiVariant[variantIndex]
801 def readFile (filename):
802 with open(filename, 'rt') as f:
805 def getInterfaceName (functionName):
806 assert functionName[:2] == "vk"
807 return functionName[2].lower() + functionName[3:]
809 def getFunctionTypeName (functionName):
810 assert functionName[:2] == "vk"
811 return functionName[2:] + "Func"
813 def endsWith (str, postfix):
814 return str[-len(postfix):] == postfix
816 def writeHandleType (api, filename):
818 def getHandleName (name):
819 return prefixName("HANDLE_TYPE_", name)
822 yield "\t%s\t= 0," % getHandleName(api.handles[0].name)
823 for h in api.handles[1:]:
824 yield "\t%s," % getHandleName(h.name)
825 for h in api.handles:
826 if h.alias is not None:
827 yield "\t%s\t= %s," % (getHandleName(h.alias), getHandleName(h.name))
828 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (getHandleName(api.handles[-1].name))
830 def genHandlesBlock ():
831 yield "enum HandleType"
834 for line in indentLines(genHandles()):
840 writeInlFile(filename, INL_HEADER, genHandlesBlock())
842 def getEnumValuePrefixAndPostfix (enum):
843 prefix = enum.name[0]
844 for i in range(1, len(enum.name)):
845 if enum.name[i].isupper() and not enum.name[i-1].isupper():
847 prefix += enum.name[i].upper()
848 for p in EXTENSION_POSTFIXES:
849 if prefix.endswith(p):
850 return prefix[:-len(p)-1], '_'+p
853 def genEnumSrc (enum):
854 yield "enum %s" % enum.name
857 for ed in enum.enumeratorList:
858 if ed.value is not None:
859 lines.append(f"\t{ed.name}\t= {ed.value},")
860 for ed in enum.enumeratorList:
861 for alias in ed.aliasList:
862 lines.append(f"\t{alias}\t= {ed.name},")
864 # add *_LAST item when enum is linear
865 prefix, postfix = getEnumValuePrefixAndPostfix(enum)
866 if enum.areValuesLinear():
867 lines.append(f"\t{prefix}{postfix}_LAST,")
869 # add _MAX_ENUM item with the ext postifix at the end
870 lines.append(f"\t{prefix}_MAX_ENUM{postfix}\t= 0x7FFFFFFF")
872 for line in indentLines(lines):
877 def genBitfieldSrc (bitfield):
879 for ev in bitfield.enumeratorList:
880 # bitfields may use mix of bitpos and values
881 if ev.bitpos is not None:
882 value = pow(2, int(ev.bitpos))
883 lines.append(f"\t{ev.name}\t= {value:#010x},")
884 if ev.value is not None:
885 lines.append(f"\t{ev.name}\t= {ev.value},")
886 for ev in bitfield.enumeratorList:
887 for alias in ev.aliasList:
888 lines.append(f"\t{alias}\t= {ev.name},")
890 prefix, postfix = getEnumValuePrefixAndPostfix(bitfield)
891 lines.append(f"\t{prefix}_MAX_ENUM{postfix}\t= 0x7FFFFFFF")
892 yield f"enum {bitfield.name}"
894 for line in indentLines(lines):
898 def genBitfield64Src (bitfield64):
899 def generateEntry(lines, bitfieldName, entryName, bitpos, value):
900 if entryName is None:
902 # bitfields may use mix of bitpos and values
903 if ev.bitpos is not None:
904 v = pow(2, int(bitpos))
905 lines.append(f"static const {bitfieldName} {entryName}\t= {v:#010x}ULL;")
906 if value is not None:
907 lines.append(f"static const {bitfieldName} {entryName}\t= {value}ULL;")
909 yield f"typedef uint64_t {bitfield64.name};"
911 for ev in bitfield64.enumeratorList:
912 generateEntry(lines, bitfield64.name, ev.name, ev.bitpos, ev.value)
913 for alias in ev.aliasList:
914 generateEntry(lines, bitfield64.name, alias, ev.bitpos, ev.value)
915 # write indented lines
916 for line in indentLines(lines):
920 def genDefinesSrc (apiName, defines):
921 def genLines (defines):
923 if d.alias is not None:
925 defineType = DEFINITIONS.get(d.name, d.type)
926 yield f"#define {d.name}\t(static_cast<{defineType}>\t({d.value}))"
927 for line in indentLines(genLines(defines)):
929 # add VK_API_MAX_FRAMEWORK_VERSION
930 major, minor = api.features[-1].number.split('.')
931 yield f"#define VK_API_MAX_FRAMEWORK_VERSION\tVK{apiName}_API_VERSION_{major}_{minor}"
933 def genHandlesSrc (handles):
934 def genLines (handles):
937 handleObjtype = h.objtypeenum
938 if h.alias is not None:
939 # search for aliased handle
940 for searchedHandle in handles:
941 if h.alias == searchedHandle.name:
942 handleType = searchedHandle.type
943 handleObjtype = searchedHandle.objtypeenum
945 yield f"{handleType}\t({h.name},\tHANDLE{handleObjtype[9:]});"
946 for line in indentLines(genLines(handles)):
949 def genHandlesSrc (handles):
950 def genLines (handles):
953 handleObjtype = h.objtypeenum
954 line = f"{handleType}\t({{}},\tHANDLE{handleObjtype[9:]});"
955 yield line.format(h.name)
956 if h.alias is not None:
957 yield line.format(h.alias)
959 for line in indentLines(genLines(handles)):
962 def writeBasicTypes (apiName, api, filename):
966 for line in genDefinesSrc(apiName, api.defines):
970 for line in genHandlesSrc(api.handles):
974 for enum in api.enums:
975 if len(enum.enumeratorList) == 0:
977 if enum.type == "bitmask":
978 if enum.bitwidth == "32":
979 for line in genBitfieldSrc(enum):
982 for line in genBitfield64Src(enum):
985 for line in genEnumSrc(enum):
987 if enum.alias is not None:
988 yield f"typedef {enum.name} {enum.alias};"
991 for bitmask in api.bitmasks:
992 plainType = api.basetypes[bitmask.type]
993 yield f"typedef {plainType} {bitmask.name};\n"
995 yield f"typedef {bitmask.name} {bitmask.alias};\n"
998 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s)" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
1002 for ext in api.extensions:
1003 firstRequirementEnums = ext.requirementsList[0].extendedEnums
1004 for e in firstRequirementEnums:
1005 if e.extends is None and e.value is not None:
1006 yield "#define " + e.name + " " + e.value
1008 writeInlFile(filename, INL_HEADER, gen())
1010 def writeCompositeTypes (api, filename):
1011 # function that returns definition of structure member
1012 def memberAsString (member):
1014 if member.qualifiers:
1015 result += member.qualifiers
1016 result += member.type
1018 result += member.pointer
1019 result += '\t' + member.name
1020 for size in member.arraySizeList:
1021 result += f"[{size}]"
1022 if member.fieldWidth:
1023 result += f":{member.fieldWidth}"
1026 # function that prints single structure definition
1027 def genCompositeTypeSrc (type):
1028 structLines = "%s %s\n{\n" % (type.category, type.name)
1029 for line in indentLines(['\t'+memberAsString(m)+';' for m in type.members]):
1030 structLines += line + '\n'
1031 return structLines + "};\n"
1033 # function that prints all structure definitions and alias typedefs
1035 # structures in xml are not ordered in a correct way for C++
1036 # we need to save structures that are used in other structures first
1037 allStructureNamesList = [s.name for s in api.compositeTypes]
1038 commonTypesList = api.basicCTypes + ['VkStructureType']
1039 savedStructureNamesList = []
1040 delayedStructureObjectsList = []
1042 # helper function that checks if all structure members were already saved
1043 def canStructBeSaved(compositeObject):
1044 for m in compositeObject.members:
1045 # check first commonTypesList to speed up the algorithm
1046 if m.type in commonTypesList:
1048 # make sure that member is not of same type as compositeObject
1049 # (this hadles cases like VkBaseOutStructure)
1050 if m.type == compositeObject.name:
1052 # if member is of compositeType that was not saved we cant save it now
1053 if m.type in allStructureNamesList and m.type not in savedStructureNamesList:
1057 # iterate over all composite types
1058 lastDelayedComposite = None
1059 for ct in api.compositeTypes:
1060 # check if one of delayed structures can be saved
1061 delayedButSaved = []
1062 for dct in delayedStructureObjectsList:
1063 if lastDelayedComposite != dct and canStructBeSaved(dct):
1064 yield genCompositeTypeSrc(dct)
1065 delayedButSaved.append(dct)
1066 lastDelayedComposite = None
1067 for dsct in delayedButSaved:
1068 savedStructureNamesList.append(dsct.name)
1069 delayedStructureObjectsList.remove(dsct)
1070 # check if current structure can be saved
1071 if canStructBeSaved(ct):
1072 yield genCompositeTypeSrc(ct)
1073 savedStructureNamesList.append(ct.name)
1075 delayedStructureObjectsList.append(ct)
1076 # memorize structure that was delayed in last iteration to
1077 # avoid calling for it canStructBeSaved in next iteration
1078 lastDelayedComposite = ct
1079 # save remaining delayed composite types (~4 video related structures)
1080 while len(delayedStructureObjectsList) > 0:
1081 for dct in delayedStructureObjectsList:
1082 if canStructBeSaved(dct):
1083 yield genCompositeTypeSrc(dct)
1084 savedStructureNamesList.append(dct.name)
1085 delayedStructureObjectsList.remove(dct)
1087 # write all alias typedefs
1088 for ct in api.compositeTypes:
1089 for alias in ct.aliasList:
1090 yield "typedef %s %s;" % (ct.name, alias)
1093 writeInlFile(filename, INL_HEADER, gen())
1095 def argListToStr (args):
1096 def argumentToString(arg):
1097 # args can be instance of FunctionArgument or CompositeMember
1098 # but CompositeMember has no arraySize atrribute nor secondPointerIsConst
1099 workingOnFunctionArgument = True if hasattr(arg, 'arraySize') else False
1102 result += arg.qualifiers
1105 if workingOnFunctionArgument and arg.secondPointerIsConst:
1106 result += '* const*'
1108 result += arg.pointer
1109 result += ' ' + arg.name
1110 if workingOnFunctionArgument:
1112 result += arg.arraySize
1114 return ", ".join(argumentToString(arg) for arg in args)
1116 def writeInterfaceDecl (api, filename, functionTypes, concrete):
1118 postfix = "" if concrete else " = 0"
1119 for function in api.functions:
1120 if not function.getType() in functionTypes:
1122 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments), postfix)
1124 writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1126 def writeFunctionPtrTypes (api, filename):
1128 pattern = "typedef VKAPI_ATTR {}\t(VKAPI_CALL* {})\t({});"
1129 for function in api.functions:
1130 argList = argListToStr(function.arguments)
1131 yield pattern.format(function.returnType, getFunctionTypeName(function.name), argList)
1132 for alias in function.aliasList:
1133 yield pattern.format(function.returnType, getFunctionTypeName(alias), argList)
1135 writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1137 def writeFunctionPointers (api, filename, functionTypes):
1138 def FunctionsYielder ():
1139 for function in api.functions:
1140 if function.getType() in functionTypes:
1141 interfaceName = getInterfaceName(function.name)
1142 functionTypeName = getFunctionTypeName(function.name)
1143 yield f"{functionTypeName}\t{interfaceName};"
1144 if function.getType() == Function.TYPE_INSTANCE:
1145 for alias in function.aliasList:
1146 interfaceName = getInterfaceName(alias)
1147 functionTypeName = getFunctionTypeName(alias)
1148 yield f"{functionTypeName}\t{interfaceName};"
1150 writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1152 def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1153 def makeInitFunctionPointers ():
1154 for function in api.functions:
1155 if function.getType() in functionTypes and (cond == None or cond(function)):
1156 interfaceName = getInterfaceName(function.name)
1157 functionTypeName = getFunctionTypeName(function.name)
1158 yield f"m_vk.{interfaceName}\t= ({functionTypeName})\tGET_PROC_ADDR(\"{function.name}\");"
1159 for alias in function.aliasList:
1160 yield f"if (!m_vk.{interfaceName})"
1161 yield f" m_vk.{interfaceName}\t= ({functionTypeName})\tGET_PROC_ADDR(\"{alias}\");"
1162 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].type == "VkPhysicalDevice":
1163 interfaceName = getInterfaceName(alias)
1164 functionTypeName = getFunctionTypeName(alias)
1165 yield f"m_vk.{interfaceName}\t= ({functionTypeName})\tGET_PROC_ADDR(\"{alias}\");"
1167 lines = [line.replace(' ', '\t') for line in indentLines(makeInitFunctionPointers())]
1168 writeInlFile(filename, INL_HEADER, lines)
1170 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1171 def makeFuncPtrInterfaceImpl ():
1172 for function in api.functions:
1173 if function.getType() in functionTypes:
1175 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function.name), argListToStr(function.arguments))
1177 if function.name == "vkEnumerateInstanceVersion":
1178 yield " if (m_vk.enumerateInstanceVersion)"
1179 yield " return m_vk.enumerateInstanceVersion(pApiVersion);"
1181 yield " *pApiVersion = VK_API_VERSION_1_0;"
1182 yield " return VK_SUCCESS;"
1183 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].type == "VkPhysicalDevice" and len(function.aliasList) > 0:
1184 yield " vk::VkPhysicalDeviceProperties props;"
1185 yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1186 yield " if (props.apiVersion >= VK_API_VERSION_1_1)"
1187 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.name), ", ".join(a.name for a in function.arguments))
1189 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.aliasList[0]), ", ".join(a.name for a in function.arguments))
1191 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.name), ", ".join(a.name for a in function.arguments))
1194 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1196 def writeFuncPtrInterfaceSCImpl (api, filename, functionTypes, className):
1198 "createGraphicsPipelines" : "\t\treturn createGraphicsPipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1199 "createComputePipelines" : "\t\treturn createComputePipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1200 "createSampler" : "\t\treturn createSamplerHandlerNorm(device, pCreateInfo, pAllocator, pSampler);",
1201 "createSamplerYcbcrConversion" : "\t\treturn createSamplerYcbcrConversionHandlerNorm(device, pCreateInfo, pAllocator, pYcbcrConversion);",
1202 "createDescriptorSetLayout" : "\t\treturn createDescriptorSetLayoutHandlerNorm(device, pCreateInfo, pAllocator, pSetLayout);",
1203 "createPipelineLayout" : "\t\treturn createPipelineLayoutHandlerNorm(device, pCreateInfo, pAllocator, pPipelineLayout);",
1204 "createRenderPass" : "\t\treturn createRenderPassHandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);",
1205 "createRenderPass2" : "\t\treturn createRenderPass2HandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);",
1206 "createCommandPool" : "\t\treturn createCommandPoolHandlerNorm(device, pCreateInfo, pAllocator, pCommandPool);",
1207 "resetCommandPool" : "\t\treturn resetCommandPoolHandlerNorm(device, commandPool, flags);",
1208 "createFramebuffer" : "\t\treturn createFramebufferHandlerNorm(device, pCreateInfo, pAllocator, pFramebuffer);",
1211 "destroyDevice" : "\t\tdestroyDeviceHandler(device, pAllocator);",
1212 "createDescriptorSetLayout" : "\t\tcreateDescriptorSetLayoutHandlerStat(device, pCreateInfo, pAllocator, pSetLayout);",
1213 "destroyDescriptorSetLayout" : "\t\tdestroyDescriptorSetLayoutHandler(device, descriptorSetLayout, pAllocator);",
1214 "createImageView" : "\t\tcreateImageViewHandler(device, pCreateInfo, pAllocator, pView);",
1215 "destroyImageView" : "\t\tdestroyImageViewHandler(device, imageView, pAllocator);",
1216 "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}",
1217 "destroySemaphore" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(semaphore,semaphoreRequestCount,1);\n\t}",
1218 "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}",
1219 "destroyFence" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(fence,fenceRequestCount,1);\n\t}",
1220 "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}",
1221 "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}",
1222 "destroyBuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(buffer,bufferRequestCount,1);\n\t}",
1223 "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}",
1224 "destroyImage" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(image,imageRequestCount,1);\n\t}",
1225 "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}",
1226 "destroyEvent" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(event,eventRequestCount,1);\n\t}",
1227 "createQueryPool" : "\t\tcreateQueryPoolHandler(device, pCreateInfo, pAllocator, pQueryPool);",
1228 "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}",
1229 "destroyBufferView" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(bufferView,bufferViewRequestCount,1);\n\t}",
1230 "createPipelineLayout" : "\t\tcreatePipelineLayoutHandlerStat(device, pCreateInfo, pAllocator, pPipelineLayout);",
1231 "destroyPipelineLayout" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineLayout,pipelineLayoutRequestCount,1);\n\t}",
1232 "createRenderPass" : "\t\tcreateRenderPassHandlerStat(device, pCreateInfo, pAllocator, pRenderPass);",
1233 "createRenderPass2" : "\t\tcreateRenderPass2HandlerStat(device, pCreateInfo, pAllocator, pRenderPass);",
1234 "destroyRenderPass" : "\t\tdestroyRenderPassHandler(device, renderPass, pAllocator);",
1235 "createGraphicsPipelines" : "\t\tcreateGraphicsPipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1236 "createComputePipelines" : "\t\tcreateComputePipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
1237 "destroyPipeline" : "\t\tdestroyPipelineHandler(device, pipeline, pAllocator);",
1238 "createSampler" : "\t\tcreateSamplerHandlerStat(device, pCreateInfo, pAllocator, pSampler);",
1239 "destroySampler" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(sampler,samplerRequestCount,1);\n\t}",
1240 "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}",
1241 "resetDescriptorPool" : "\t\tresetDescriptorPoolHandlerStat(device, descriptorPool, flags);",
1242 "allocateDescriptorSets" : "\t\tallocateDescriptorSetsHandlerStat(device, pAllocateInfo, pDescriptorSets);",
1243 "freeDescriptorSets" : "\t\tfreeDescriptorSetsHandlerStat(device, descriptorPool, descriptorSetCount, pDescriptorSets);",
1244 "createFramebuffer" : "\t\tcreateFramebufferHandlerStat(device, pCreateInfo, pAllocator, pFramebuffer);",
1245 "destroyFramebuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(framebuffer,framebufferRequestCount,1);\n\t}",
1246 "createCommandPool" : "\t\tcreateCommandPoolHandlerStat(device, pCreateInfo, pAllocator, pCommandPool);",
1247 "resetCommandPool" : "\t\tresetCommandPoolHandlerStat(device, commandPool, flags);",
1248 "allocateCommandBuffers" : "\t\tallocateCommandBuffersHandler(device, pAllocateInfo, pCommandBuffers);",
1249 "freeCommandBuffers" : "\t\tfreeCommandBuffersHandler(device, commandPool, commandBufferCount, pCommandBuffers);",
1250 "createSamplerYcbcrConversion" : "\t\tcreateSamplerYcbcrConversionHandlerStat(device, pCreateInfo, pAllocator, pYcbcrConversion);",
1251 "destroySamplerYcbcrConversion" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(ycbcrConversion,samplerYcbcrConversionRequestCount,1);\n\t}",
1252 "getDescriptorSetLayoutSupport" : "\t\tgetDescriptorSetLayoutSupportHandler(device, pCreateInfo, pSupport);",
1253 # "" : "surfaceRequestCount",
1254 # "" : "swapchainRequestCount",
1255 # "" : "displayModeRequestCount"
1256 "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}",
1257 "getBufferMemoryRequirements" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}",
1258 "getImageMemoryRequirements" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}",
1259 "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}",
1260 "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}",
1261 "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}",
1262 "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}",
1263 "destroyPipelineCache" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineCache,pipelineCacheRequestCount,1);\n\t}",
1264 "cmdUpdateBuffer" : "\t\tincreaseCommandBufferSize(commandBuffer, dataSize);",
1265 "getDeviceQueue" : "\t\tm_vk.getDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);",
1269 "VkResult" : "return VK_SUCCESS;",
1270 "VkDeviceAddress" : "return 0u;",
1271 "uint64_t" : "return 0u;",
1273 def makeFuncPtrInterfaceStatisticsImpl ():
1274 for function in api.functions:
1275 if function.getType() in functionTypes and not function.isAlias:
1277 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
1279 if ( getInterfaceName(function) in normFuncs ) or ( getInterfaceName(function) in statFuncs ):
1280 yield "\tstd::lock_guard<std::mutex> lock(functionMutex);"
1281 if getInterfaceName(function) != "getDeviceProcAddr" :
1282 yield "\tif (m_normalMode)"
1283 if getInterfaceName(function) in normFuncs :
1284 yield "%s" % ( normFuncs[getInterfaceName(function)] )
1286 yield "\t\t%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1287 if getInterfaceName(function) in statFuncs :
1289 yield "%s" % ( statFuncs[getInterfaceName(function)] )
1290 elif getInterfaceName(function)[:3] == "cmd" :
1292 yield "\t\tincreaseCommandBufferSize(commandBuffer, 0u);"
1293 if function.returnType in statReturns:
1294 yield "\t%s" % ( statReturns[function.returnType] )
1297 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceStatisticsImpl())
1299 def writeStrUtilProto (api, filename):
1300 def makeStrUtilProto ():
1301 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"]):
1304 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"]):
1307 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"]):
1310 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]):
1313 for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes]):
1316 writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1318 def writeStrUtilImpl (api, filename):
1319 def makeStrUtilImpl ():
1320 for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles]):
1324 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1327 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):
1333 for enum in api.enums:
1334 if enum.type == "enum":
1336 yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1338 yield "\tswitch (value)"
1341 lastValue = 0x7FFFFFFF
1342 for e in enum.enumeratorList:
1343 enumValues.append(f"\t\tcase {e.name}:\treturn \"{e.name}\";")
1344 enumValues.append("\t\tdefault:\treturn DE_NULL;")
1345 for line in indentLines(enumValues):
1349 elif enum.type == "bitmask":
1350 # find bitfield that uses those bitmasks
1352 for bitmask in api.bitmasks:
1353 if bitmask.requires == enum.name or bitmask.bitvalues == enum.name:
1354 foundBitmask = bitmask
1356 savedBitmasks.append(foundBitmask.name)
1357 bitSize = "64" if foundBitmask.type == "VkFlags64" else "32"
1359 yield f"tcu::Format::Bitfield<{bitSize}> get{bitmask.name[2:]}Str ({bitmask.name} value)"
1361 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1363 for line in indentLines([f"\t\ttcu::Format::BitDesc({e.name},\t\"{e.name}\")," for e in enum.enumeratorList]):
1366 yield f"\treturn tcu::Format::Bitfield<{bitSize}>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1369 for bitmask in api.bitmasks:
1370 if bitmask.name not in savedBitmasks:
1371 bitSize = "64" if bitmask.type == "VkFlags64" else "32"
1373 yield f"tcu::Format::Bitfield<{bitSize}> get{bitmask.name[2:]}Str ({bitmask.name} value)"
1375 yield f"\treturn tcu::Format::Bitfield<{bitSize}>(value, DE_NULL, DE_NULL);"
1378 bitfieldTypeNames = set([bitmask.name for bitmask in api.bitmasks])
1380 for type in api.compositeTypes:
1382 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1384 yield "\ts << \"%s = {\\n\";" % type.name
1385 for member in type.members:
1386 memberName = member.name
1389 if member.type in bitfieldTypeNames:
1390 operator = '*' if member.pointer == '*' else ''
1391 valFmt = "get%sStr(%svalue.%s)" % (member.type[2:], operator, member.name)
1392 elif member.type == "char" and member.pointer == '*':
1393 valFmt = "getCharPtrStr(value.%s)" % member.name
1394 elif member.type == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1395 valFmt = "getWStr(value.%s)" % member.name
1396 elif len(member.arraySizeList) > 0:
1397 singleDimensional = len(member.arraySizeList) == 1
1398 if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1399 valFmt = "(const char*)value.%s" % member.name
1400 elif singleDimensional and (member.type == 'char' or member.type == 'uint8_t'):
1401 newLine = "'\\n' << "
1402 valFmt = "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.type, member.name, member.type, member.name)
1404 if member.name == "memoryTypes" or member.name == "memoryHeaps":
1405 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1407 endIter = "DE_ARRAY_END(value.%s)" % member.name
1408 newLine = "'\\n' << "
1409 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1410 memberName = member.name
1412 valFmt = "value.%s" % member.name
1413 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1417 writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1419 def writeObjTypeImpl (api, filename):
1420 def makeObjTypeImpl ():
1422 yield "namespace vk"
1425 yield "template<typename T> VkObjectType getObjectType (void);"
1427 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]):
1432 writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1434 class ConstructorFunction:
1435 def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1438 self.objectType = objectType
1439 self.ifaceArgs = ifaceArgs
1440 self.arguments = arguments
1442 def getConstructorFunctions (api):
1446 Function.TYPE_PLATFORM: [FunctionArgument("vk", "const ", "PlatformInterface&")],
1447 Function.TYPE_INSTANCE: [FunctionArgument("vk", "const ", "InstanceInterface&")],
1448 Function.TYPE_DEVICE: [FunctionArgument("vk", "const ", "DeviceInterface&")]}
1450 for function in api.functions:
1451 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1452 if function.name == "vkCreateDisplayModeKHR":
1453 continue # No way to delete display modes (bug?)
1456 if function.name == "vkCreateDevice":
1457 ifaceArgs = [FunctionArgument("vkp", "const ", "PlatformInterface&"),
1458 FunctionArgument("instance", "", "VkInstance")]
1459 ifaceArgs.extend(ifacesDict[function.getType()])
1461 assert (function.arguments[-2].type == "VkAllocationCallbacks" and \
1462 "const" in function.arguments[-2].qualifiers and \
1463 function.arguments[-2].pointer == "*")
1465 objectType = function.arguments[-1].type
1466 arguments = function.arguments[:-1]
1467 funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function.name), objectType, ifaceArgs, arguments))
1470 def addVersionDefines(versionSpectrum):
1471 output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1474 def writeRefUtilProto (api, filename):
1475 functions = getConstructorFunctions(api)
1477 def makeRefUtilProto ():
1479 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]):
1482 writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1484 def writeRefUtilImpl (api, filename):
1485 functions = getConstructorFunctions(api)
1487 def makeRefUtilImpl ():
1488 yield "namespace refdetails"
1492 for function in api.functions:
1493 if function.getType() == Function.TYPE_DEVICE \
1494 and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1495 and not function.name == "vkDestroyDevice":
1496 objectType = function.arguments[-2].type
1498 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1500 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function.name))
1504 yield "} // refdetails"
1508 Function.TYPE_PLATFORM: "object",
1509 Function.TYPE_INSTANCE: "instance",
1510 Function.TYPE_DEVICE: "device"
1513 for function in functions:
1514 deleterArgsString = ''
1515 if function.name == "createDevice":
1516 # createDevice requires two additional parameters to setup VkDevice deleter
1517 deleterArgsString = "vkp, instance, object, " + function.arguments[-1].name
1519 deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1521 yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1523 yield "\t%s object = 0;" % function.objectType
1524 yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1525 yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1529 writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1531 def writeStructTraitsImpl (api, filename):
1533 for cType in api.compositeTypes:
1534 if cType.category == "struct" and cType.members[0].name == "sType" and cType.name != "VkBaseOutStructure" and cType.name != "VkBaseInStructure":
1535 yield "template<> VkStructureType getStructureType<%s> (void)" % cType.name
1537 yield "\treturn %s;" % cType.members[0].values
1541 writeInlFile(filename, INL_HEADER, gen())
1543 def writeNullDriverImpl (api, filename):
1544 def genNullDriverImpl ():
1545 specialFuncNames = [
1546 "vkCreateGraphicsPipelines",
1547 "vkCreateComputePipelines",
1548 "vkCreateRayTracingPipelinesNV",
1549 "vkCreateRayTracingPipelinesKHR",
1550 "vkGetInstanceProcAddr",
1551 "vkGetDeviceProcAddr",
1552 "vkEnumeratePhysicalDevices",
1553 "vkEnumerateInstanceExtensionProperties",
1554 "vkEnumerateDeviceExtensionProperties",
1555 "vkGetPhysicalDeviceFeatures",
1556 "vkGetPhysicalDeviceFeatures2KHR",
1557 "vkGetPhysicalDeviceProperties",
1558 "vkGetPhysicalDeviceProperties2KHR",
1559 "vkGetPhysicalDeviceQueueFamilyProperties",
1560 "vkGetPhysicalDeviceMemoryProperties",
1561 "vkGetPhysicalDeviceFormatProperties",
1562 "vkGetPhysicalDeviceImageFormatProperties",
1564 "vkGetBufferMemoryRequirements",
1565 "vkGetBufferMemoryRequirements2KHR",
1566 "vkGetImageMemoryRequirements",
1567 "vkGetImageMemoryRequirements2KHR",
1571 "vkAllocateDescriptorSets",
1572 "vkFreeDescriptorSets",
1573 "vkResetDescriptorPool",
1574 "vkAllocateCommandBuffers",
1575 "vkFreeCommandBuffers",
1576 "vkCreateDisplayModeKHR",
1577 "vkCreateSharedSwapchainsKHR",
1578 "vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1579 "vkGetPhysicalDeviceImageFormatProperties2KHR",
1580 "vkGetMemoryAndroidHardwareBufferANDROID",
1583 specialFuncs = [f for f in api.functions if f.name in specialFuncNames]
1584 createFuncs = [f for f in api.functions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1585 destroyFuncs = [f for f in api.functions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1586 dummyFuncs = [f for f in api.functions if f not in specialFuncs + createFuncs + destroyFuncs]
1588 def getHandle (name):
1589 for handle in api.handles:
1590 if handle.name == name:
1592 raise Exception("No such handle: %s" % name)
1594 for function in createFuncs:
1595 objectType = function.arguments[-1].type
1596 argsStr = ", ".join([a.name for a in function.arguments[:-1]])
1598 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments))
1600 yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1602 if getHandle(objectType).type == "VK_DEFINE_NON_DISPATCHABLE_HANDLE":
1603 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
1605 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
1609 for function in destroyFuncs:
1610 objectArg = function.arguments[-2]
1612 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments))
1614 for arg in function.arguments[:-2]:
1615 yield "\tDE_UNREF(%s);" % arg.name
1617 if getHandle(objectArg.type).type == 'VK_DEFINE_NON_DISPATCHABLE_HANDLE':
1618 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
1620 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
1625 for function in dummyFuncs:
1626 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function.name), argListToStr(function.arguments))
1628 for arg in function.arguments:
1629 yield "\tDE_UNREF(%s);" % arg.name
1630 if function.returnType != "void":
1631 yield "\treturn VK_SUCCESS;"
1635 def genFuncEntryTable (type, name):
1638 pattern = "\tVK_NULL_FUNC_ENTRY(%s,\t%s),"
1639 for f in api.functions:
1640 if f.getType() != type:
1642 entries.append(pattern % (f.name, getInterfaceName(f.name)))
1644 yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1647 for line in indentLines(entries):
1653 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1656 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1659 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1662 writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1664 def writeTypeUtil (api, filename):
1665 # Structs filled by API queries are not often used in test code
1666 QUERY_RESULT_TYPES = set([
1667 "VkPhysicalDeviceFeatures",
1668 "VkPhysicalDeviceLimits",
1669 "VkFormatProperties",
1670 "VkImageFormatProperties",
1671 "VkPhysicalDeviceSparseProperties",
1672 "VkQueueFamilyProperties",
1675 "StdVideoH264SpsVuiFlags",
1676 "StdVideoH264SpsFlags",
1677 "StdVideoH264PpsFlags",
1678 "StdVideoDecodeH264PictureInfoFlags",
1679 "StdVideoDecodeH264ReferenceInfoFlags",
1680 "StdVideoDecodeH264MvcElementFlags",
1681 "StdVideoEncodeH264SliceHeaderFlags",
1682 "StdVideoEncodeH264PictureInfoFlags",
1683 "StdVideoEncodeH264RefMgmtFlags",
1684 "StdVideoEncodeH264ReferenceInfoFlags",
1685 "StdVideoH265HrdFlags",
1686 "StdVideoH265VpsFlags",
1687 "StdVideoH265SpsVuiFlags",
1688 "StdVideoH265SpsFlags",
1689 "StdVideoH265PpsFlags",
1690 "StdVideoDecodeH265PictureInfoFlags",
1691 "StdVideoDecodeH265ReferenceInfoFlags",
1692 "StdVideoEncodeH265PictureInfoFlags",
1693 "StdVideoEncodeH265SliceSegmentHeaderFlags",
1694 "StdVideoEncodeH265ReferenceModificationFlags",
1695 "StdVideoEncodeH265ReferenceInfoFlags",
1696 "StdVideoH265ProfileTierLevelFlags",
1697 "StdVideoH265ShortTermRefPicSetFlags"
1700 def isSimpleStruct (type):
1701 def hasArrayMember (type):
1702 for member in type.members:
1703 if len(member.arraySizeList) > 0:
1707 def hasCompositeMember (type):
1708 for member in type.members:
1709 if member.pointer is not None and '*' not in member.pointer:
1710 match = [c for c in api.compositeTypes if member.type == c.name]
1715 return type.category == "struct" and \
1716 type.members[0].type != "VkStructureType" and \
1717 not type.name in QUERY_RESULT_TYPES and \
1718 not hasArrayMember(type) and \
1719 not hasCompositeMember(type)
1722 for type in api.compositeTypes:
1723 if not isSimpleStruct(type):
1726 name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
1729 yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
1731 yield "\t%s res;" % type.name
1732 for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1734 yield "\treturn res;"
1737 writeInlFile(filename, INL_HEADER, gen())
1739 def writeDriverIds(api, filename):
1740 driverIdsString = []
1741 driverIdsString.append("static const struct\n"
1743 "\tstd::string driver;\n"
1745 "} driverIds [] =\n"
1747 driverItems = dict()
1748 driverIdEnum = [enum for enum in api.enums if enum.name == 'VkDriverId'][0]
1749 for enumerator in driverIdEnum.enumeratorList:
1750 driverIdsString.append(f"\t{{\"{enumerator.name}\", {enumerator.value}}},")
1751 driverItems[enumerator.name] = enumerator.value
1752 for enumerator in driverIdEnum.enumeratorList:
1753 if len(enumerator.aliasList) > 0:
1754 driverIdsString.append(f"\t{{\"{enumerator.aliasList[0]}\", {enumerator.value}}},\t// {enumerator.name}")
1755 driverIdsString.append("\t{\"VK_DRIVER_ID_MAX_ENUM\", 0x7FFFFFFF}")
1756 driverIdsString.append("};")
1758 writeInlFile(filename, INL_HEADER, driverIdsString)
1760 def writeSupportedExtensions(apiName, api, filename):
1762 def writeExtensionsForVersions(map):
1765 result.append(" if (coreVersion >= " + str(version) + ")")
1767 for extension in map[version]:
1768 result.append(' dst.push_back("' + extension.name + '");')
1772 result.append(" DE_UNREF(coreVersion);")
1779 for ext in api.extensions:
1780 if ext.promotedto is None or "VK_VERSION" not in ext.promotedto:
1782 # skip partialy promoted extensions
1783 if ext.partiallyPromoted is True:
1785 major = int(ext.promotedto[-3])
1786 minor = int(ext.promotedto[-1])
1787 currVersion = "VK_API_VERSION_" + ext.promotedto[-3:]
1788 # VulkanSC is based on Vulkan 1.2. Any Vulkan version greater than 1.2 should be excluded
1789 if apiName=='SC' and major==1 and minor>2:
1791 if ext.type == 'instance':
1792 list = instanceMap.get(currVersion)
1793 instanceMap[currVersion] = list + [ext] if list else [ext]
1795 list = deviceMap.get(currVersion)
1796 deviceMap[currVersion] = list + [ext] if list else [ext]
1798 # add list of extensions missing in Vulkan SC specification
1800 for extensionName, data in api.additionalExtensionData:
1801 # make sure that this extension was registered
1802 if 'register_extension' not in data.keys():
1804 # save array containing 'device' or 'instance' string followed by the optional vulkan version in which this extension is core;
1805 # note that register_extension section is also required for partialy promoted extensions like VK_EXT_extended_dynamic_state2
1806 # but those extensions should not fill 'core' tag
1807 match = re.match("(\d).(\d).(\d).(\d)", data['register_extension']['core'])
1809 currVersion = Version([int(match.group(1)), int(match.group(2)), int(match.group(3)), int(match.group(4))])
1810 ext = Extension(extensionName, 0, 0, 0, 0, 0, 0, 0, 0, 0)
1811 if currVersion.api==0 and currVersion.major==1 and currVersion.minor>2:
1813 if data['register_extension']['type'] == 'instance':
1814 list = instanceMap.get(currVersion)
1815 instanceMap[currVersion] = list + [ext] if list else [ext]
1817 list = deviceMap.get(currVersion)
1818 deviceMap[currVersion] = list + [ext] if list else [ext]
1822 "void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 or apiName == 'SC' else ""),
1823 "{"] + writeExtensionsForVersions(deviceMap) + [
1826 "void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 or apiName == 'SC' else ""),
1827 "{"] + writeExtensionsForVersions(instanceMap) + [
1830 writeInlFile(filename, INL_HEADER, lines)
1833 def writeExtensionFunctions (api, filename):
1835 def writeExtensionNameArrays ():
1836 instanceExtensionNames = [f"\t\"{ext.name}\"," for ext in api.extensions if ext.type == "instance"]
1837 deviceExtensionNames = [f"\t\"{ext.name}\"," for ext in api.extensions if ext.type == "device"]
1838 yield '::std::string instanceExtensionNames[] =\n{'
1839 for instanceExtName in instanceExtensionNames:
1840 yield instanceExtName
1842 yield '::std::string deviceExtensionNames[] =\n{'
1843 for deviceExtName in deviceExtensionNames:
1847 def writeExtensionFunctions (functionType):
1849 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
1850 if functionType == Function.TYPE_INSTANCE:
1851 yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1852 dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
1853 elif functionType == Function.TYPE_DEVICE:
1854 yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1855 dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
1856 for ext in api.extensions:
1858 for requirement in ext.requirementsList:
1859 for requiredCommand in requirement.newCommands:
1860 commandName = requiredCommand.name
1861 # find function that has specified name
1863 funcList = [f for f in api.functions if f.name == commandName]
1864 # if name was not found check if this is alias
1865 if len(funcList) == 0:
1866 for f in api.functions:
1867 for aliasName in f.aliasList:
1868 if aliasName == commandName:
1873 if func.getType() == functionType:
1874 # only add functions with same vendor as extension
1875 # this is a workaroudn for entrypoints requiring more
1876 # than one excetions and lack of the dependency in vk.xml
1877 vendor = ext.name.split('_')[1]
1878 if func.name.endswith(vendor):
1879 funcNames.append(func.name)
1881 yield '\tif (extName == "%s")' % ext.name
1883 for funcName in funcNames:
1884 if funcName in dg_list:
1885 yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
1887 yield '\t\tfunctions.push_back("%s");' % funcName
1888 if ext.name == "VK_KHR_device_group":
1889 for dg_func in dg_list:
1890 yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
1893 isFirstWrite = False
1894 if not isFirstWrite:
1895 yield '\tDE_FATAL("Extension name not found");'
1899 for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
1902 for line in writeExtensionFunctions(Function.TYPE_DEVICE):
1905 for line in writeExtensionNameArrays():
1908 writeInlFile(filename, INL_HEADER, lines)
1910 def writeCoreFunctionalities(api, filename):
1911 functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1913 functionNamesPerApiVersionDict = {}
1914 for feature in api.features:
1915 apiVersion = "VK_API_VERSION_" + feature.number.replace('.', '_')
1916 functionNamesPerApiVersionDict[apiVersion] = []
1917 for r in feature.requirementsList:
1918 functionNamesPerApiVersionDict[apiVersion].extend(r.commandList)
1922 'enum FunctionOrigin', '{'] + [line for line in indentLines([
1923 '\t' + functionOriginValues[0] + '\t= 0,',
1924 '\t' + functionOriginValues[1] + ',',
1925 '\t' + functionOriginValues[2]])] + [
1928 "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1929 "typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1930 "typedef ::std::map<uint32_t, FunctionInfosList> ApisMap;",
1932 "void initApisMap (ApisMap& apis)",
1934 " apis.clear();"] + [
1935 " apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + v + ", FunctionInfosList()));" for v in functionNamesPerApiVersionDict] + [
1940 for apiVersion in functionNamesPerApiVersionDict:
1941 # iterate over names of functions added with api
1942 for functionName in functionNamesPerApiVersionDict[apiVersion]:
1943 # search for data of this function in all functions list
1945 for f in api.functions:
1946 if functionName == f.name:
1949 assert(functionData != None)
1950 # add line coresponding to this function
1951 functionLines.append('\tapis[{0}].push_back(FunctionInfo("' + functionName + '",\t' + functionOriginValues[functionData.getType()] + '));')
1952 # functions for every api version should also include all functions from previous versions
1953 specializedLines = [line.format(apiVersion) for line in functionLines]
1954 # indent all functions of specified api and add them to main list
1955 lines = lines + [line for line in indentLines(specializedLines)] + [""]
1957 lines = lines + ["}"]
1958 writeInlFile(filename, INL_HEADER, lines)
1960 def camelToSnake(name):
1961 name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
1962 return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
1964 def writeDeviceFeatures2(api, filename):
1966 def structInAPI(compositeObject):
1967 for c in api.compositeTypes:
1968 if c.name == compositeObject.name:
1972 # helper class used to encapsulate all data needed during generation
1973 class StructureDetail:
1974 def __init__ (self, compositeObject):
1975 self.nameList = [compositeObject.name] + compositeObject.aliasList
1976 self.sType = compositeObject.members[0].values
1977 self.instanceName = 'd' + compositeObject.name[11:]
1978 self.flagName = 'is' + compositeObject.name[16:]
1979 self.extension = None
1983 structureMembers = compositeObject.members[2:]
1984 self.members = [m.name for m in structureMembers]
1986 # helper extension class used in algorith below
1987 class StructureFoundContinueToNextOne(Exception):
1990 # find structures that extend VkPhysicalDeviceFeatures2
1991 structures = [c for c in api.compositeTypes if c.structextends is not None and 'VkPhysicalDeviceFeatures2' in c.structextends]
1992 # remove structures that were added by extensions other than KHR and EXT
1993 testedStructures = []
1994 for s in structures:
1995 if all([postfix not in s.name for postfix in EXTENSION_POSTFIXES_VENDOR]):
1996 testedStructures.append(s)
1998 existingStructures = list(filter(structInAPI, testedStructures)) # remove features not found in API ( important for Vulkan SC )
1999 testedStructureDetail = [StructureDetail(struct) for struct in existingStructures]
2000 # iterate over all searched structures and find extensions that enabled them
2001 for structureDetail in testedStructureDetail:
2003 # iterate over all extensions
2004 for extension in api.extensions:
2005 for requirement in extension.requirementsList:
2006 for extensionStructure in requirement.newTypes:
2007 if extensionStructure.name in structureDetail.nameList:
2008 structureDetail.extension = extension.name
2009 if extension.promotedto is not None and extension.partiallyPromoted is False:
2010 # check if extension was promoted to vulkan version or other extension
2011 if 'VK_VERSION' in extension.promotedto:
2012 versionSplit = extension.promotedto.split('_')
2013 structureDetail.api = 0 # TODO handle this for Vulkan SC
2014 structureDetail.major = versionSplit[-2]
2015 structureDetail.minor = versionSplit[-1]
2017 structureDetail.extension = extension.promotedto
2018 raise StructureFoundContinueToNextOne
2019 except StructureFoundContinueToNextOne:
2021 for structureDetail in testedStructureDetail:
2022 if structureDetail.major is not None:
2024 # if structure was not added with extension then check if
2025 # it was added directly with one of vulkan versions
2026 structureName = structureDetail.nameList[0]
2027 for feature in api.features:
2028 for requirement in feature.requirementsList:
2029 if structureName in requirement.typeList:
2030 versionSplit = feature.name.split('_')
2031 structureDetail.api = 0 # TODO handle this for Vulkan SC
2032 structureDetail.major = versionSplit[-2]
2033 structureDetail.minor = versionSplit[-1]
2035 if structureDetail.major is not None:
2037 # generate file content
2038 structureDefinitions = []
2039 featureEnabledFlags = []
2040 clearStructures = []
2043 verifyStructures = []
2044 for index, structureDetail in enumerate(testedStructureDetail):
2045 structureName = structureDetail.nameList[0]
2046 # create two instances of each structure
2048 structureDefinitions.append(structureName + nameSpacing + structureDetail.instanceName + '[count];')
2049 # create flags that check if proper extension or vulkan version is available
2051 extension = structureDetail.extension
2052 major = structureDetail.major
2053 if extension is not None:
2054 condition = ' checkExtension(properties, "' + extension + '")'
2055 if major is not None:
2056 condition = ' ' if condition == '' else condition + ' || '
2057 condition += 'context.contextSupports(vk::ApiVersion(' + str(structureDetail.api) + ', ' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
2061 nameSpacing = '\t' * int((len(structureName) - 4) / 4)
2062 featureEnabledFlags.append('const bool' + nameSpacing + structureDetail.flagName + ' =' + condition)
2063 # clear memory of each structure
2064 clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx], 0xFF * ndx, sizeof(' + structureName + '));')
2065 # construct structure chain
2066 nextInstanceName = 'DE_NULL';
2067 if index < len(testedStructureDetail)-1:
2068 nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
2069 structureChain.append([
2070 '\t\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.flagName + ' ? ' + structureDetail.sType + ' : VK_STRUCTURE_TYPE_MAX_ENUM;',
2071 '\t\t' + structureDetail.instanceName + '[ndx].pNext = DE_NULL;'])
2072 # construct log section
2073 logStructures.append([
2074 '\tif (' + structureDetail.flagName + ')',
2075 '\t\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;'
2077 #construct verification section
2078 verifyStructure = []
2079 verifyStructure.append('\tif (' + structureDetail.flagName + ' &&')
2080 for index, m in enumerate(structureDetail.members):
2081 prefix = '\t\t(' if index == 0 else '\t\t '
2082 postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
2083 verifyStructure.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
2084 if len(structureDetail.members) == 0:
2085 verifyStructure.append('\t\tfalse)')
2086 verifyStructure.append('\t{\n\t\tTCU_FAIL("Mismatch between ' + structureName + '");\n\t}')
2087 verifyStructures.append(verifyStructure)
2089 # construct file content
2092 # individual test functions
2093 for n, x in enumerate(testedStructureDetail):
2094 stream.append("tcu::TestStatus testPhysicalDeviceFeature" + x.instanceName[len('device'):]+" (Context& context)")
2096 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
2097 const CustomInstance instance (createCustomInstanceWithExtension(context, "VK_KHR_get_physical_device_properties2"));
2098 const InstanceDriver& vki (instance.getDriver());
2099 const int count = 2u;
2100 TestLog& log = context.getTestContext().getLog();
2101 VkPhysicalDeviceFeatures2 extFeatures;
2102 vector<VkExtensionProperties> properties = enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
2104 stream.append("\t"+structureDefinitions[n])
2105 stream.append("\t"+featureEnabledFlags[n])
2107 stream.append('\tfor (int ndx = 0; ndx < count; ++ndx)\n\t{')
2108 stream.append("\t" + clearStructures[n])
2109 stream.extend(structureChain[n])
2112 '\t\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
2113 '\t\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
2114 '\t\textFeatures.pNext = &' + testedStructureDetail[n].instanceName + '[ndx];\n\n'
2115 '\t\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);')
2116 stream.append('\t}\n')
2117 stream.extend(logStructures[n])
2119 stream.extend(verifyStructures[n])
2120 stream.append('\treturn tcu::TestStatus::pass("Querying succeeded");')
2121 stream.append("}\n")
2123 # function to create tests
2124 stream.append("void addSeparateFeatureTests (tcu::TestCaseGroup* testGroup)\n{")
2125 for x in testedStructureDetail:
2126 stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x.instanceName[len('device'):]) + '", "' + x.nameList[0] + '", testPhysicalDeviceFeature' + x.instanceName[len('device'):] + ');')
2127 stream.append('}\n')
2130 writeInlFile(filename, INL_HEADER, stream)
2132 def generateDeviceFeaturesOrPropertiesDefs(api, FeaturesOrProperties):
2133 assert(FeaturesOrProperties in ['Features', 'Properties'])
2135 foundStructureEnums = []
2136 structureEnumPattern = f'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_{FeaturesOrProperties.upper()}(\w+)'
2137 structureEnumPatternNotExtension = structureEnumPattern[:-5] + '$'
2138 structureTypePattern = f'VkPhysicalDevice(\w+){FeaturesOrProperties}(\w+)'
2139 structureTypePatternNotExtension = structureTypePattern[:-5] + '$'
2140 structureTypeToSkipPattern = f'VkPhysicalDeviceVulkan\d\d{FeaturesOrProperties}'
2141 structureExtendsPattern = f'VkPhysicalDevice{FeaturesOrProperties}2'
2142 # iterate over all extensions to find extension that adds enum value matching pattern;
2143 # this will always be in first requirement section
2144 for ext in api.extensions:
2145 # skip extensions that were promoted to other extensions (not vk version)
2146 if ext.promotedto is not None and "VK_VERSION" not in ext.promotedto:
2148 allExtendedEnums = ext.requirementsList[0].extendedEnums
2149 for extendedEnum in allExtendedEnums:
2150 matchedStructEnum = re.search(structureEnumPattern, extendedEnum.name, re.IGNORECASE)
2151 if matchedStructEnum:
2152 # find feature/property structure type name
2153 structureTypeName = ""
2154 for stRequirement in ext.requirementsList[0].newTypes:
2155 stName = stRequirement.name
2156 matchedStructType = re.search(structureTypePattern, stName, re.IGNORECASE)
2157 if matchedStructType:
2158 structureTypeName = stName
2160 # iterate over all composite types to check if structureTypeName is not alias
2161 # this handles case where extension was promoted and with it feature/property structure
2162 structureType = None
2163 for ct in api.compositeTypes:
2164 if structureTypeName == ct.name:
2167 elif structureTypeName in ct.aliasList:
2169 structureTypeName = structureType.name
2171 # use data in structextends to skip structures that should not be passed to vkGetPhysicalDeviceProperties(/Features)2 function
2172 if structureType.structextends is None or structureExtendsPattern not in structureType.structextends:
2174 # meke sure that structure was not added earlier - this handles special
2175 # cases like VkPhysicalDeviceIDPropertiesKHR added by 3 extensions
2176 if len([d for d in defs if d[3] == structureTypeName]) > 0:
2178 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
2179 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
2180 sSuffix = matchedStructEnum.group(2)
2182 sExtSuffix = sSuffix
2183 suffixStart = sSuffix.rfind('_')
2185 sVerSuffix = sSuffix[:suffixStart]
2186 sExtSuffix = sSuffix[suffixStart:]
2187 foundStructureEnums.append(matchedStructEnum.group(1))
2188 defs.append( (matchedStructEnum.group(1), sVerSuffix, sExtSuffix, structureTypeName,\
2189 ext.name, allExtendedEnums[1].name, allExtendedEnums[0].name) )
2190 # accept single feature/property structure per extension - this also handles cases
2191 # like VK_KHR_variable_pointers which specify feature structure and its alias
2194 # iterate over all structures to find Feature/Property structures that were not added with extension
2195 # but with vulkan version; to do that we need to skip extension part from pattern
2196 for ct in api.compositeTypes:
2197 matchedStructType = re.search(structureTypePatternNotExtension, ct.name, re.IGNORECASE)
2198 if matchedStructType:
2199 if ct.members[0].name != "sType":
2201 if ct.structextends is None or structureExtendsPattern not in ct.structextends:
2203 matchedStructEnum = re.search(structureEnumPatternNotExtension, ct.members[0].values, re.IGNORECASE)
2204 if (matchedStructEnum.group(1) not in foundStructureEnums) and (re.match(structureTypeToSkipPattern, ct.name) == None):
2205 defs.append( (matchedStructEnum.group(1), '', '', ct.name, None, None, '0') )
2208 def generateDevicePropertiesDefs(apiName, src):
2209 # look for definitions
2210 ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
2211 matches = re.findall(ptrnSType, src, re.M)
2212 matches = sorted(matches, key=lambda m: m[0])
2213 # hardcoded list of core extensions having properties and missing from Vulkan SC
2214 missingVulkanSCExt = \
2215 '#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME \"VK_KHR_depth_stencil_resolve\"\n' \
2216 '#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME \"VK_EXT_descriptor_indexing\"\n' \
2217 '#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME \"VK_KHR_driver_properties\"\n' \
2218 '#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME \"VK_KHR_shader_float_controls\"\n' \
2219 '#define VK_KHR_MAINTENANCE3_EXTENSION_NAME \"VK_KHR_maintenance3\"\n' \
2220 '#define VK_KHR_MULTIVIEW_EXTENSION_NAME \"VK_KHR_multiview\"\n' \
2221 '#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME \"VK_EXT_sampler_filter_minmax\"\n' \
2222 '#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME \"VK_KHR_timeline_semaphore\"\n'
2223 # construct final list
2225 for sType, sSuffix in matches:
2226 # handle special cases
2227 if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'VULKAN_1_3', 'VULKAN_SC_1_0', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
2229 # there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
2230 # where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
2232 sExtSuffix = sSuffix
2233 suffixStart = sSuffix.rfind('_')
2235 sVerSuffix = sSuffix[:suffixStart]
2236 sExtSuffix = sSuffix[suffixStart:]
2237 # handle special case
2241 structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
2242 ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
2243 matchStructName = re.search(ptrnStructName, src, re.M)
2247 if extType == "MAINTENANCE_3":
2248 extType = "MAINTENANCE3"
2249 elif extType == "MAINTENANCE_4":
2250 extType = "MAINTENANCE4"
2251 elif extType == "POINT_CLIPPING":
2252 extType = "MAINTENANCE2"
2253 # end handling special cases
2254 ptrnExtensionName = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
2255 matchExtensionName = re.search(ptrnExtensionName, src, re.M)
2256 if matchExtensionName is None and apiName=='SC':
2257 matchExtensionName = re.search(ptrnExtensionName, missingVulkanSCExt, re.M)
2258 ptrnSpecVersion = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
2259 matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
2260 defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
2261 matchExtensionName.group(0) if matchExtensionName else None,
2262 matchExtensionName.group(1) if matchExtensionName else None,
2263 matchSpecVersion.group (1) if matchSpecVersion else '0') )
2266 def writeDeviceFeatures(api, dfDefs, filename):
2267 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2268 # and construct dictionary with all of their attributes
2271 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
2272 for structureType in api.compositeTypes:
2273 match = blobPattern.match(structureType.name)
2275 allMembers = [member.name for member in structureType.members]
2276 vkVersion = match.group(1)
2277 blobMembers[vkVersion] = allMembers[2:]
2278 blobStructs[vkVersion] = set()
2279 initFromBlobDefinitions = []
2280 emptyInitDefinitions = []
2281 # iterate over all feature structures
2282 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
2283 nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
2284 for structureType in api.compositeTypes:
2285 # skip structures that are not feature structures
2286 if not allFeaturesPattern.match(structureType.name):
2288 # skip structures that were previously identified as blobs
2289 if blobPattern.match(structureType.name):
2291 # skip sType and pNext and just grab third and next attributes
2292 structureMembers = structureType.members[2:]
2293 notPartOfBlob = True
2294 if nonExtFeaturesPattern.match(structureType.name):
2295 # check if this member is part of any of the blobs
2296 for blobName, blobMemberList in blobMembers.items():
2297 # if just one member is not part of this blob go to the next blob
2298 # (we asume that all members are part of blob - no need to check all)
2299 if structureMembers[0].name not in blobMemberList:
2301 # add another feature structure name to this blob
2302 blobStructs[blobName].add(structureType)
2303 # add specialization for this feature structure
2305 for member in structureMembers:
2306 memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2308 "template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
2311 "}}".format(structureType.name, memberCopying)
2312 initFromBlobDefinitions.append(wholeFunction)
2313 notPartOfBlob = False
2314 # assuming that all members are part of blob, goto next
2316 # add empty template definition as on Fedora there are issue with
2317 # linking using just generic template - all specializations are needed
2319 emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2320 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2321 extensionDefines = []
2322 makeFeatureDescDefinitions = []
2323 featureStructWrappers = []
2324 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extName, extNameDef, specVersionDef) in enumerate(dfDefs):
2325 extensionNameDefinition = extNameDef
2326 if not extensionNameDefinition:
2327 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2328 extensionDefines.append(f'#define {extensionNameDefinition} "not_existent_feature"')
2329 # construct makeFeatureDesc template function definitions
2330 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2331 makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2332 "{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVersionDef, len(dfDefs)-idx))
2333 # construct CreateFeatureStruct wrapper block
2334 featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVersionDef))
2335 # construct function that will check for which vk version structure sType is part of blob
2336 blobChecker = "deUint32 getBlobFeaturesVersion (VkStructureType sType)\n{\n" \
2337 "\tconst std::map<VkStructureType, deUint32> sTypeBlobMap\n" \
2339 # iterate over blobs with list of structures
2340 for blobName in sorted(blobStructs.keys()):
2341 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2342 # iterate over all feature structures in current blob
2343 structuresList = list(blobStructs[blobName])
2344 structuresList = sorted(structuresList, key=lambda s: s.name)
2345 for structType in structuresList:
2346 # find definition of this structure in dfDefs
2348 allNamesToCheck = [structType.name]
2349 if len(structType.aliasList) > 0:
2350 allNamesToCheck.extend(structType.aliasList)
2351 for structName in allNamesToCheck:
2352 structDefList = [s for s in dfDefs if s[3] == structName]
2353 if len(structDefList) > 0:
2354 structDef = structDefList[0]
2356 sType = structDef[0]
2357 sSuffix = structDef[1] + structDef[2]
2358 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2359 tabs = "\t" * int((88 - len(sTypeName)) / 4)
2360 blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1])
2361 blobChecker += "\t};\n\n" \
2362 "\tauto it = sTypeBlobMap.find(sType);\n" \
2363 "\tif(it == sTypeBlobMap.end())\n" \
2365 "\treturn it->second;\n" \
2367 # combine all definition lists
2369 '#include "vkDeviceFeatures.hpp"\n',
2371 stream.extend(extensionDefines)
2373 stream.extend(initFromBlobDefinitions)
2374 stream.append('\n// generic template is not enough for some compilers')
2375 stream.extend(emptyInitDefinitions)
2377 stream.extend(makeFeatureDescDefinitions)
2379 stream.append('static const FeatureStructCreationData featureStructCreationArray[]\n{')
2380 stream.extend(featureStructWrappers)
2381 stream.append('};\n')
2382 stream.append(blobChecker)
2383 stream.append('} // vk\n')
2384 writeInlFile(filename, INL_HEADER, stream)
2386 def writeDeviceFeatureTest(apiName, api, filename):
2388 coreFeaturesPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
2391 # iterate over all feature structures
2392 allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
2393 for structureType in api.compositeTypes:
2394 # skip structures that are not feature structures
2395 if not allFeaturesPattern.match(structureType.name):
2397 # skip sType and pNext and just grab third and next attributes
2398 structureMembers = structureType.members[2:]
2401 for member in structureMembers:
2402 items.append(" FEATURE_ITEM ({0}, {1}),".format(structureType.name, member.name))
2405 tcu::TestStatus createDeviceWithUnsupportedFeaturesTest{4} (Context& context)
2407 const PlatformInterface& vkp = context.getPlatformInterface();
2408 tcu::TestLog& log = context.getTestContext().getLog();
2409 tcu::ResultCollector resultCollector (log);
2410 const CustomInstance instance (createCustomInstanceWithExtensions(context, context.getInstanceExtensions(), DE_NULL, true));
2411 const InstanceDriver& instanceDriver (instance.getDriver());
2412 const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
2413 const deUint32 queueFamilyIndex = 0;
2414 const deUint32 queueCount = 1;
2415 const float queuePriority = 1.0f;
2416 const DeviceFeatures deviceFeaturesAll (context.getInstanceInterface(), context.getUsedApiVersion(), physicalDevice, context.getInstanceExtensions(), context.getDeviceExtensions(), DE_TRUE);
2417 const VkPhysicalDeviceFeatures2 deviceFeatures2 = deviceFeaturesAll.getCoreFeatures2();
2419 bool isSubProcess = context.getTestContext().getCommandLine().isSubProcess();
2422 VkPhysicalDeviceFeatures emptyDeviceFeatures;
2423 deMemset(&emptyDeviceFeatures, 0, sizeof(emptyDeviceFeatures));
2425 // Only non-core extensions will be used when creating the device.
2426 vector<const char*> coreExtensions;
2427 getCoreDeviceExtensions(context.getUsedApiVersion(), coreExtensions);
2428 vector<string> nonCoreExtensions(removeExtensions(context.getDeviceExtensions(), coreExtensions));
2430 vector<const char*> extensionNames;
2431 extensionNames.reserve(nonCoreExtensions.size());
2432 for (const string& extension : nonCoreExtensions)
2433 extensionNames.push_back(extension.c_str());
2435 if (const void* featuresStruct = findStructureInChain(const_cast<const void*>(deviceFeatures2.pNext), getStructureType<{0}>()))
2437 static const Feature features[] =
2441 auto* supportedFeatures = reinterpret_cast<const {0}*>(featuresStruct);
2442 checkFeatures(vkp, instance, instanceDriver, physicalDevice, {2}, features, supportedFeatures, queueFamilyIndex, queueCount, queuePriority, numErrors, resultCollector, {3}, emptyDeviceFeatures, {5});
2446 return tcu::TestStatus(resultCollector.getResult(), "Enabling unsupported features didn't return VK_ERROR_FEATURE_NOT_PRESENT.");
2448 return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
2451 additionalParams = ( 'memReservationStatMax, isSubProcess' if apiName == 'SC' else 'isSubProcess' )
2452 additionalDefs = ( ' VkDeviceObjectReservationCreateInfo memReservationStatMax = context.getResourceInterface()->getStatMax();' if apiName == 'SC' else '')
2453 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))
2455 testFunctions.append("createDeviceWithUnsupportedFeaturesTest" + structureType.name[len('VkPhysicalDevice'):])
2458 stream.extend(featureItems)
2460 void addSeparateUnsupportedFeatureTests (tcu::TestCaseGroup* testGroup)
2463 for x in testFunctions:
2464 stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x[len('createDeviceWithUnsupportedFeaturesTest'):]) + '", "' + x + '", ' + x + ');')
2465 stream.append('}\n')
2467 writeInlFile(filename, INL_HEADER, stream)
2469 def writeDeviceProperties(api, dpDefs, filename):
2470 # find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2471 # and construct dictionary with all of their attributes
2474 blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2475 for structureType in api.compositeTypes:
2476 match = blobPattern.match(structureType.name)
2478 allMembers = [member.name for member in structureType.members]
2479 vkVersion = match.group(1)
2480 blobMembers[vkVersion] = allMembers[2:]
2481 blobStructs[vkVersion] = set()
2482 initFromBlobDefinitions = []
2483 emptyInitDefinitions = []
2484 # iterate over all property structures
2485 allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2486 nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2487 for structureType in api.compositeTypes:
2488 # skip structures that are not property structures
2489 if not allPropertiesPattern.match(structureType.name):
2491 # skip structures that were previously identified as blobs
2492 if blobPattern.match(structureType.name):
2494 # skip sType and pNext and just grab third and next attributes
2495 structureMembers = structureType.members[2:]
2496 notPartOfBlob = True
2497 if nonExtPropertiesPattern.match(structureType.name):
2498 # check if this member is part of any of the blobs
2499 for blobName, blobMemberList in blobMembers.items():
2500 # if just one member is not part of this blob go to the next blob
2501 # (we asume that all members are part of blob - no need to check all)
2502 if structureMembers[0].name not in blobMemberList:
2504 # add another property structure name to this blob
2505 blobStructs[blobName].add(structureType)
2506 # add specialization for this property structure
2508 for member in structureMembers:
2509 if len(member.arraySizeList) == 0:
2510 # handle special case
2511 if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2512 blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2513 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2514 # end handling special case
2516 memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2518 memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type, member.arraySizeList[0])
2520 "template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2523 "}}".format(structureType.name, memberCopying)
2524 initFromBlobDefinitions.append(wholeFunction)
2525 notPartOfBlob = False
2526 # assuming that all members are part of blob, goto next
2528 # add empty template definition as on Fedora there are issue with
2529 # linking using just generic template - all specializations are needed
2531 emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2532 emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2533 extensionDefines = []
2534 makePropertyDescDefinitions = []
2535 propertyStructWrappers = []
2536 for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extName, extNameDef, specVersionDef) in enumerate(dpDefs):
2537 extensionNameDefinition = extNameDef
2538 if not extensionNameDefinition:
2539 extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2540 extensionDefines.append(f'#define {extensionNameDefinition} "core_property"')
2541 # construct makePropertyDesc template function definitions
2542 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2543 makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2544 "{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVersionDef, len(dpDefs)-idx))
2545 # construct CreateProperty struct wrapper block
2546 propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVersionDef))
2547 # construct method that will check if structure sType is part of blob
2548 blobChecker = "deUint32 getBlobPropertiesVersion (VkStructureType sType)\n{\n" \
2549 "\tconst std::map<VkStructureType, deUint32> sTypeBlobMap\n" \
2551 # iterate over blobs with list of structures
2552 for blobName in sorted(blobStructs.keys()):
2553 blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2554 # iterate over all feature structures in current blob
2555 structuresList = list(blobStructs[blobName])
2556 structuresList = sorted(structuresList, key=lambda s: s.name)
2557 for structType in structuresList:
2558 # find definition of this structure in dpDefs
2559 structName = structType.name
2561 foundDefs = [s for s in dpDefs if s[3] == structName]
2562 if len(foundDefs) > 0:
2563 structDef = foundDefs[0]
2565 for alias in structType.aliasList:
2566 foundDefs = [s for s in dpDefs if s[3] == alias]
2567 if len(foundDefs) > 0:
2568 structDef = foundDefs[0]
2570 sType = structDef[0]
2571 sSuffix = structDef[1] + structDef[2]
2572 sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2573 tabs = "\t" * int((80 - len(sTypeName)) / 4)
2574 blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1])
2575 blobChecker += "\t};\n\n" \
2576 "\tauto it = sTypeBlobMap.find(sType);\n" \
2577 "\tif(it == sTypeBlobMap.end())\n" \
2579 "\treturn it->second;\n" \
2581 # combine all definition lists
2583 '#include "vkDeviceProperties.hpp"\n',
2585 stream.extend(extensionDefines)
2587 stream.extend(initFromBlobDefinitions)
2588 stream.append('\n// generic template is not enough for some compilers')
2589 stream.extend(emptyInitDefinitions)
2591 stream.extend(makePropertyDescDefinitions)
2593 stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2594 stream.extend(propertyStructWrappers)
2595 stream.append('};\n')
2596 stream.append(blobChecker)
2597 stream.append('} // vk\n')
2598 writeInlFile(filename, INL_HEADER, stream)
2600 def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
2602 for _, _, _, extStruct, _, _, _ in dfDefs:
2603 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2604 stream.append(pattern.format(extStruct, nameSubStr))
2605 writeInlFile(filename, INL_HEADER, indentLines(stream))
2607 def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
2608 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
2609 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2611 def writeDeviceFeaturesContextDecl(dfDefs, filename):
2612 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2613 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2615 def writeDeviceFeaturesContextDefs(dfDefs, filename):
2616 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2617 genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2619 def genericDevicePropertiesWriter(dfDefs, pattern, filename):
2621 for _, _, _, extStruct, _, _, _ in dfDefs:
2622 nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2623 if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
2625 stream.append(pattern.format(extStruct, nameSubStr))
2626 writeInlFile(filename, INL_HEADER, indentLines(stream))
2628 def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
2629 pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
2630 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2632 def writeDevicePropertiesContextDecl(dfDefs, filename):
2633 pattern = "const vk::{0}&\tget{1}\t(void) const;"
2634 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2636 def writeDevicePropertiesContextDefs(dfDefs, filename):
2637 pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2638 genericDevicePropertiesWriter(dfDefs, pattern, filename)
2640 def writeMandatoryFeatures(api, filename):
2642 def structInAPI(name):
2643 for c in api.compositeTypes:
2646 for alias in c.aliasList:
2654 for _, data in api.additionalExtensionData:
2655 if 'mandatory_features' not in data.keys():
2657 # sort to have same results for py2 and py3
2658 listStructFeatures = sorted(data['mandatory_features'].items(), key=lambda tup: tup[0])
2659 for structure, featuresList in listStructFeatures:
2660 for featureData in featuresList:
2661 # allow for featureless VKSC only extensions
2662 if not 'features' in featureData.keys() or 'requirements' not in featureData.keys():
2664 requirements = featureData['requirements']
2666 mandatory_variant = ''
2668 mandatory_variant = featureData['mandatory_variant']
2670 mandatory_variant = ''
2672 dictData.append( [ structure, featureData['features'], requirements, mandatory_variant] )
2674 if structure == 'VkPhysicalDeviceFeatures':
2676 # if structure is not in dict construct name of variable and add is as a first item
2677 if (structure not in dictStructs):
2678 dictStructs[structure] = ([structure[2:3].lower() + structure[3:]], mandatory_variant)
2679 # add first requirement if it is unique
2680 if requirements and (requirements[0] not in dictStructs[structure][0]):
2681 dictStructs[structure][0].append(requirements[0])
2684 stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
2685 '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
2686 '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
2688 '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
2689 '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
2690 '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
2692 '\ttcu::TestLog& log = context.getTestContext().getLog();',
2693 '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
2694 '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
2695 '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
2696 '\tvoid** nextPtr = &coreFeatures.pNext;',
2699 listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
2700 apiStruct = list( filter(lambda x : structInAPI(x[0]), listStruct)) # remove items not defined in current A
2702 for k, v in apiStruct:
2705 metaCondition = metaCondition + ' || defined(CTS_USES_' + v[1][0].upper() + ')'
2706 stream.extend(['#if ' + metaCondition[4:]])
2707 if (v[0][1].startswith("ApiVersion")):
2708 cond = '\tif (context.contextSupports(vk::' + v[0][1] + '))'
2710 cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[0][1] + '"))'
2711 stream.extend(['\tvk::' + k + ' ' + v[0][0]+ ';',
2712 '\tdeMemset(&' + v[0][0] + ', 0, sizeof(' + v[0][0] + '));',
2717 for i, req in enumerate(reqs) :
2718 if (req.startswith("ApiVersion")):
2719 cond = cond + 'context.contextSupports(vk::' + req + ')'
2721 cond = cond + 'isExtensionStructSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2722 if i+1 < len(reqs) :
2723 cond = cond + ' || '
2725 stream.append('\t' + cond)
2726 stream.extend(['\t{',
2727 '\t\t' + v[0][0] + '.sType = getStructureType<' + k + '>();',
2728 '\t\t*nextPtr = &' + v[0][0] + ';',
2729 '\t\tnextPtr = &' + v[0][0] + '.pNext;',
2731 if metaCondition != '':
2732 stream.extend(['#endif // ' + metaCondition[4:],
2736 stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
2737 '\tbool result = true;',
2741 if not structInAPI(v[0]): # remove items not defined in current API ( important for Vulkan SC )
2744 structName = 'coreFeatures.features';
2746 if len(v) == 4 and v[3] != '':
2747 # for x in v[3].split('_'):
2748 metaCondition = metaCondition + ' || defined(CTS_USES_' + v[3][0].upper() + ')'
2749 stream.extend(['#if ' + metaCondition[4:]])
2750 if v[0] != 'VkPhysicalDeviceFeatures' :
2751 structName = dictStructs[v[0]][0][0]
2754 for i, req in enumerate(v[2]) :
2755 if (req.startswith("ApiVersion")):
2756 condition = condition + 'context.contextSupports(vk::' + req + ')'
2758 condition = condition + req
2760 condition = condition + 'isExtensionStructSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2761 if i+1 < len(v[2]) :
2762 condition = condition + ' && '
2763 condition = condition + ' )'
2764 stream.append('\t' + condition)
2765 stream.append('\t{')
2766 # Don't need to support an AND case since that would just be another line in the .txt
2768 stream.append('\t\tif ( ' + structName + '.' + v[1][0] + ' == VK_FALSE )')
2771 for i, feature in enumerate(v[1]):
2773 condition = condition + ' && '
2774 condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
2775 condition = condition + ' )'
2776 stream.append('\t\t' + condition)
2777 featureSet = " or ".join(v[1])
2778 stream.extend(['\t\t{',
2779 '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
2780 '\t\t\tresult = false;',
2783 if metaCondition != '':
2784 stream.extend(['#endif // ' + metaCondition[4:],
2789 stream.append('\treturn result;')
2790 stream.append('}\n')
2791 writeInlFile(filename, INL_HEADER, stream)
2793 def writeExtensionList(apiName, api, filename, extensionType):
2795 for extensionName, data in api.additionalExtensionData:
2796 # make sure extension name starts with VK_KHR
2797 if not extensionName.startswith('VK_KHR'):
2799 # make sure that this extension was registered
2800 if 'register_extension' not in data.keys():
2802 # make sure extension is intended for the vulkan variant
2806 if 'mandatory_features' in data.keys():
2807 for structure, listStruct in data['mandatory_features'].items():
2808 for featureData in listStruct:
2809 mandatory_variant = ''
2811 mandatory_variant = featureData['mandatory_variant']
2813 mandatory_variant = ''
2815 if 'vulkansc' in mandatory_variant:
2820 # make sure extension has proper type
2821 if extensionType == data['register_extension']['type']:
2822 extensionList.append(extensionName)
2823 extensionList.sort()
2824 # write list of all found extensions
2826 stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(extensionType.title()))
2827 for n in extensionList:
2828 stream.append('\t"' + n + '",')
2829 stream.append('};\n')
2830 writeInlFile(filename, INL_HEADER, stream)
2832 def writeApiExtensionDependencyInfo(api, filename):
2834 def isExtensionInCore(ext, apiMajor, apiMinor):
2835 if ext.promotedto is None:
2837 if 'VK_VERSION' not in ext.promotedto:
2839 extMajor = ext.promotedto[-3]
2840 extMinor = ext.promotedto[-1]
2841 if apiMajor > extMajor:
2843 if apiMajor == extMajor and apiMinor >= extMinor:
2847 def genExtDepArray(extType):
2848 yield 'static const std::tuple<deUint32, deUint32, deUint32, const char*, const char*>\t{}ExtensionDependencies[]\t='.format(extType)
2850 allApiVersions = [f.number for f in api.features]
2851 # iterate over all extension that are of specified type and that have requirements
2852 for ext in api.extensions:
2853 if ext.type != extType:
2855 if ext.requiredExtensions is None:
2858 # iterate over all api versions
2859 for apiVersion in allApiVersions:
2860 major, minor = apiVersion.split('.')
2861 if ext.requiresCore is not None:
2862 requiresCoreMajor, requiresCoreMinor = ext.requiresCore.split('.')
2863 if major < requiresCoreMajor or minor < requiresCoreMinor:
2865 if isExtensionInCore(ext, major, minor):
2867 # iterate over all requirements and add to the list those that are
2868 # applicable for currently processed api version
2869 for r in ext.requiredExtensions:
2870 # find required extension and make sure it is not part of core for this or previous api version
2871 requiredExtensionList = [re for re in api.extensions if re.name == r]
2872 if len(requiredExtensionList) > 0:
2873 requiredExtension = requiredExtensionList[0]
2874 if isExtensionInCore(requiredExtension, major, minor):
2876 yield '\tstd::make_tuple({}, {}, {}, "{}", "{}"),'.format(apiVariant, major, minor, ext.name, r)
2879 def genApiVersions():
2880 yield 'static const std::tuple<deUint32, deUint32, deUint32, deUint32>\treleasedApiVersions[]\t='
2882 for f in reversed(api.features):
2883 apiVariant = '0' if f.api == 'vulkan' else '1'
2884 major, minor = f.number.split('.')
2885 version = (int(apiVariant) << 29) | (int(major) << 22) | (int(minor) << 12)
2886 yield '\tstd::make_tuple({}, {}, {}, {}),'.format(version, apiVariant, major, minor)
2889 def genRequiredCoreVersions():
2890 yield 'static const std::tuple<deUint32, deUint32, const char*>\textensionRequiredCoreVersion[]\t ='
2892 for ext in api.extensions:
2893 # skip video extensions
2894 if 'vulkan_video_' in ext.name:
2896 major, minor = '1', '0'
2897 if ext.requiresCore is not None:
2898 major, minor = ext.requiresCore.split('.')
2899 yield '\tstd::make_tuple({}, {}, "{}"),'.format(major, minor, ext.name)
2903 stream.extend(genExtDepArray('instance'))
2904 stream.extend(genExtDepArray('device'))
2905 stream.extend(genApiVersions())
2906 stream.extend(genRequiredCoreVersions())
2908 writeInlFile(filename, INL_HEADER, stream)
2910 def parseCmdLineArgs():
2911 parser = argparse.ArgumentParser(description = "Generate Vulkan INL files",
2912 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
2913 parser.add_argument("-a",
2917 help="Choose between Vulkan and Vulkan SC")
2918 parser.add_argument("-o",
2922 help="Choose output directory")
2923 return parser.parse_args()
2925 if __name__ == "__main__":
2926 args = parseCmdLineArgs()
2928 # if argument was specified it is interpreted as a path to which .inl files will be written
2929 outputPath = DEFAULT_OUTPUT_DIR[args.api] if args.outdir == '' else args.outdir
2931 currentDir = os.getcwd()
2936 # Read vk.xml and generate vulkan headers from it
2937 os.chdir(VULKAN_XML_DIR)
2938 api.build( etree.parse("vk.xml") )
2939 api.build( etree.parse("video.xml") )
2942 elif args.api=='SC':
2943 # At the moment structure of vk.xml for Vulkan SC is not final.
2944 # For time being we will use old version of gen_framework script that
2945 # was saved as gen_framework_sc (it still parses vulkan_sc_core.h)
2946 os.chdir(os.path.dirname(__file__))
2947 pythonExecutable = sys.executable or "python"
2948 execute([pythonExecutable, "gen_framework_sc.py", "--api", "SC"])
2951 os.chdir(currentDir)
2953 platformFuncs = [Function.TYPE_PLATFORM]
2954 instanceFuncs = [Function.TYPE_INSTANCE]
2955 deviceFuncs = [Function.TYPE_DEVICE]
2957 dfd = generateDeviceFeaturesOrPropertiesDefs(api, 'Features')
2958 writeDeviceFeatures (api, dfd, os.path.join(outputPath, "vkDeviceFeatures.inl"))
2959 writeDeviceFeaturesDefaultDeviceDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
2960 writeDeviceFeaturesContextDecl (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDecl.inl"))
2961 writeDeviceFeaturesContextDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDefs.inl"))
2962 writeDeviceFeatureTest (args.api, api, os.path.join(outputPath, "vkDeviceFeatureTest.inl"))
2964 dpd = generateDeviceFeaturesOrPropertiesDefs(api, 'Properties')
2965 writeDeviceProperties (api, dpd, os.path.join(outputPath, "vkDeviceProperties.inl"))
2966 writeDevicePropertiesDefaultDeviceDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
2967 writeDevicePropertiesContextDecl (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDecl.inl"))
2968 writeDevicePropertiesContextDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDefs.inl"))
2970 writeHandleType (api, os.path.join(outputPath, "vkHandleType.inl"))
2971 writeBasicTypes (args.api, api, os.path.join(outputPath, "vkBasicTypes.inl"))
2972 writeCompositeTypes (api, os.path.join(outputPath, "vkStructTypes.inl"))
2973 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualPlatformInterface.inl"), platformFuncs, False)
2974 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualInstanceInterface.inl"), instanceFuncs, False)
2975 writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualDeviceInterface.inl"), deviceFuncs, False)
2976 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcretePlatformInterface.inl"), platformFuncs, True)
2977 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteInstanceInterface.inl"), instanceFuncs, True)
2978 writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteDeviceInterface.inl"), deviceFuncs, True)
2979 writeFunctionPtrTypes (api, os.path.join(outputPath, "vkFunctionPointerTypes.inl"))
2980 writeFunctionPointers (api, os.path.join(outputPath, "vkPlatformFunctionPointers.inl"), platformFuncs)
2981 writeFunctionPointers (api, os.path.join(outputPath, "vkInstanceFunctionPointers.inl"), instanceFuncs)
2982 writeFunctionPointers (api, os.path.join(outputPath, "vkDeviceFunctionPointers.inl"), deviceFuncs)
2983 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr")
2984 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitInstanceFunctionPointers.inl"), instanceFuncs)
2985 writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitDeviceFunctionPointers.inl"), deviceFuncs)
2986 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver")
2987 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver")
2988 writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver")
2990 writeFuncPtrInterfaceSCImpl (api, os.path.join(outputPath, "vkDeviceDriverSCImpl.inl"), deviceFuncs, "DeviceDriverSC")
2991 writeStrUtilProto (api, os.path.join(outputPath, "vkStrUtil.inl"))
2992 writeStrUtilImpl (api, os.path.join(outputPath, "vkStrUtilImpl.inl"))
2993 writeRefUtilProto (api, os.path.join(outputPath, "vkRefUtil.inl"))
2994 writeRefUtilImpl (api, os.path.join(outputPath, "vkRefUtilImpl.inl"))
2995 writeStructTraitsImpl (api, os.path.join(outputPath, "vkGetStructureTypeImpl.inl"))
2996 writeNullDriverImpl (api, os.path.join(outputPath, "vkNullDriverImpl.inl"))
2997 writeTypeUtil (api, os.path.join(outputPath, "vkTypeUtil.inl"))
2998 writeSupportedExtensions (args.api, api, os.path.join(outputPath, "vkSupportedExtensions.inl"))
2999 writeCoreFunctionalities (api, os.path.join(outputPath, "vkCoreFunctionalities.inl"))
3000 writeExtensionFunctions (api, os.path.join(outputPath, "vkExtensionFunctions.inl"))
3001 writeDeviceFeatures2 (api, os.path.join(outputPath, "vkDeviceFeatures2.inl"))
3002 writeMandatoryFeatures (api, os.path.join(outputPath, "vkMandatoryFeatures.inl"))
3003 writeExtensionList (args.api, api, os.path.join(outputPath, "vkInstanceExtensions.inl"), 'instance')
3004 writeExtensionList (args.api, api, os.path.join(outputPath, "vkDeviceExtensions.inl"), 'device')
3005 writeDriverIds (api, os.path.join(outputPath, "vkKnownDriverIds.inl"))
3006 writeObjTypeImpl (api, os.path.join(outputPath, "vkObjTypeImpl.inl"))
3007 writeApiExtensionDependencyInfo (api, os.path.join(outputPath, "vkApiExtensionDependencyInfo.inl"))
3009 # NOTE: when new files are generated then they should also be added to the
3010 # vk-gl-cts\external\vulkancts\framework\vulkan\CMakeLists.txt outputs list