diff --git a/scripts/generate_source.py b/scripts/generate_source.py index 01cf652..b7216b9 100755 --- a/scripts/generate_source.py +++ b/scripts/generate_source.py @@ -33,7 +33,7 @@ def RunGenerators(api: str, registry: str, targetFilter: str) -> None: print("Inside Vulkan-Headers there is a registry/reg.py file that is used.") sys.exit(1) # Return without call stack so easy to spot error - from generators.base_generator import BaseGeneratorOptions + from base_generator import BaseGeneratorOptions from generators.dispatch_table_generator import DispatchTableOutputGenerator from generators.enum_string_helper_generator import EnumStringHelperOutputGenerator from generators.format_utils_generator import FormatUtilsOutputGenerator @@ -42,7 +42,7 @@ def RunGenerators(api: str, registry: str, targetFilter: str) -> None: # These set fields that are needed by both OutputGenerator and BaseGenerator, # but are uniform and don't need to be set at a per-generated file level - from generators.base_generator import (SetTargetApiName, SetMergedApiNames) + from base_generator import (SetTargetApiName, SetMergedApiNames) SetTargetApiName(api) # Build up a list of all generators and custom options diff --git a/scripts/generators/base_generator.py b/scripts/generators/base_generator.py deleted file mode 100644 index 8d4ee06..0000000 --- a/scripts/generators/base_generator.py +++ /dev/null @@ -1,782 +0,0 @@ -#!/usr/bin/python3 -i -# -# Copyright (c) 2023-2025 Valve Corporation -# Copyright (c) 2023-2025 LunarG, Inc. -# Copyright (c) 2023-2025 RasterGrid Kft. -# -# SPDX-License-Identifier: Apache-2.0 - -import pickle -import os -import tempfile -from generators.vulkan_object import (VulkanObject, - Extension, Version, Handle, Param, Queues, CommandScope, Command, - EnumField, Enum, Flag, Bitmask, Member, Struct, - FormatComponent, FormatPlane, Format, - SyncSupport, SyncEquivalent, SyncStage, SyncAccess, SyncPipelineStage, SyncPipeline, - SpirvEnables, Spirv) - -# These live in the Vulkan-Docs repo, but are pulled in via the -# Vulkan-Headers/registry folder -from generator import OutputGenerator, GeneratorOptions, write -from vkconventions import VulkanConventions - -# An API style convention object -vulkanConventions = VulkanConventions() - -# Helpers to keep things cleaner -def splitIfGet(elem, name): - return elem.get(name).split(',') if elem.get(name) is not None and elem.get(name) != '' else None - -def textIfFind(elem, name): - return elem.find(name).text if elem.find(name) is not None else None - -def intIfGet(elem, name): - return None if elem.get(name) is None else int(elem.get(name), 0) - -def boolGet(elem, name) -> bool: - return elem.get(name) is not None and elem.get(name) == "true" - -def getQueues(elem) -> Queues: - queues = 0 - queues_list = splitIfGet(elem, 'queues') - if queues_list is not None: - queues |= Queues.TRANSFER if 'transfer' in queues_list else 0 - queues |= Queues.GRAPHICS if 'graphics' in queues_list else 0 - queues |= Queues.COMPUTE if 'compute' in queues_list else 0 - queues |= Queues.PROTECTED if 'protected' in queues_list else 0 - queues |= Queues.SPARSE_BINDING if 'sparse_binding' in queues_list else 0 - queues |= Queues.OPTICAL_FLOW if 'opticalflow' in queues_list else 0 - queues |= Queues.DECODE if 'decode' in queues_list else 0 - queues |= Queues.ENCODE if 'encode' in queues_list else 0 - return queues - -# Shared object used by Sync elements that don't have ones -maxSyncSupport = SyncSupport(None, None, True) -maxSyncEquivalent = SyncEquivalent(None, None, True) - -# Helpers to set GeneratorOptions options globally -def SetOutputFileName(fileName: str) -> None: - global globalFileName - globalFileName = fileName - -def SetOutputDirectory(directory: str) -> None: - global globalDirectory - globalDirectory = directory - -def SetTargetApiName(apiname: str) -> None: - global globalApiName - globalApiName = apiname - -def SetMergedApiNames(names: str) -> None: - global mergedApiNames - mergedApiNames = names - -cachingEnabled = False -def EnableCaching() -> None: - global cachingEnabled - cachingEnabled = True - -# This class is a container for any source code, data, or other behavior that is necessary to -# customize the generator script for a specific target API variant (e.g. Vulkan SC). As such, -# all of these API-specific interfaces and their use in the generator script are part of the -# contract between this repository and its downstream users. Changing or removing any of these -# interfaces or their use in the generator script will have downstream effects and thus -# should be avoided unless absolutely necessary. -class APISpecific: - # Version object factory method - @staticmethod - def createApiVersion(targetApiName: str, name: str) -> Version: - match targetApiName: - - # Vulkan specific API version creation - case 'vulkan': - nameApi = name.replace('VK_', 'VK_API_') - nameString = f'"{name}"' - return Version(name, nameString, nameApi) - - -# This Generator Option is used across all generators. -# After years of use, it has shown that most the options are unified across each generator (file) -# as it is easier to modifiy things per-file that need the difference -class BaseGeneratorOptions(GeneratorOptions): - def __init__(self, - customFileName = None, - customDirectory = None, - customApiName = None): - GeneratorOptions.__init__(self, - conventions = vulkanConventions, - filename = customFileName if customFileName else globalFileName, - directory = customDirectory if customDirectory else globalDirectory, - apiname = customApiName if customApiName else globalApiName, - mergeApiNames = mergedApiNames, - defaultExtensions = customApiName if customApiName else globalApiName, - emitExtensions = '.*', - emitSpirv = '.*', - emitFormats = '.*') - # These are used by the generator.py script - self.apicall = 'VKAPI_ATTR ' - self.apientry = 'VKAPI_CALL ' - self.apientryp = 'VKAPI_PTR *' - self.alignFuncParam = 48 - -# -# This object handles all the parsing from reg.py generator scripts in the Vulkan-Headers -# It will grab all the data and form it into a single object the rest of the generators will use -class BaseGenerator(OutputGenerator): - def __init__(self): - OutputGenerator.__init__(self, None, None, None) - self.vk = VulkanObject() - self.targetApiName = globalApiName - - # reg.py has a `self.featureName` but this is nicer because - # it will be either the Version or Extension object - self.currentExtension = None - self.currentVersion = None - - # Will map alias to promoted name - # ex. ['VK_FILTER_CUBIC_IMG' : 'VK_FILTER_CUBIC_EXT'] - # When generating any code, there is no reason so use the old name - self.enumAliasMap = dict() - self.enumFieldAliasMap = dict() - self.bitmaskAliasMap = dict() - self.flagAliasMap = dict() - self.structAliasMap = dict() - - def write(self, data): - # Prevents having to check before writting - if data is not None and data != "": - write(data, file=self.outFile) - - - def beginFile(self, genOpts): - OutputGenerator.beginFile(self, genOpts) - self.filename = genOpts.filename - - # No gen*() command to get these, so do it manually - for platform in self.registry.tree.findall('platforms/platform'): - self.vk.platforms[platform.get('name')] = platform.get('protect') - - for tags in self.registry.tree.findall('tags'): - for tag in tags.findall('tag'): - self.vk.vendorTags.append(tag.get('name')) - - # No way known to get this from the XML - self.vk.queueBits[Queues.TRANSFER] = 'VK_QUEUE_TRANSFER_BIT' - self.vk.queueBits[Queues.GRAPHICS] = 'VK_QUEUE_GRAPHICS_BIT' - self.vk.queueBits[Queues.COMPUTE] = 'VK_QUEUE_COMPUTE_BIT' - self.vk.queueBits[Queues.PROTECTED] = 'VK_QUEUE_PROTECTED_BIT' - self.vk.queueBits[Queues.SPARSE_BINDING] = 'VK_QUEUE_SPARSE_BINDING_BIT' - self.vk.queueBits[Queues.OPTICAL_FLOW] = 'VK_QUEUE_OPTICAL_FLOW_BIT_NV' - self.vk.queueBits[Queues.DECODE] = 'VK_QUEUE_VIDEO_DECODE_BIT_KHR' - self.vk.queueBits[Queues.ENCODE] = 'VK_QUEUE_VIDEO_ENCODE_BIT_KHR' - - # This function should be overloaded - def generate(self): - print("WARNING: This should not be called from the child class") - return - - # This function is dense, it does all the magic to set the right extensions dependencies! - # - # The issue is if 2 extension expose a command, genCmd() will only - # show one of the extension, at endFile() we can finally go through - # and update which things depend on which extensions - # - # self.featureDictionary is built for use in the reg.py framework - # Details found in Vulkan-Docs/scripts/scriptgenerator.py - def applyExtensionDependency(self): - for extension in self.vk.extensions.values(): - # dict.key() can be None, so need to double loop - dict = self.featureDictionary[extension.name]['command'] - - # "required" == None - # or - # an additional feature dependency, which is a boolean expression of - # one or more extension and/or core version names - for required in dict: - for commandName in dict[required]: - # Skip commands removed in the target API - # This check is needed because parts of the base generator code bypass the - # dependency resolution logic in the registry tooling and thus the generator - # may attempt to generate code for commands which are not supported in the - # target API variant, thus this check needs to happen even if any specific - # target API variant may not specifically need it - if not commandName in self.vk.commands: - continue - - command = self.vk.commands[commandName] - # Make sure list is unique - command.extensions.extend([extension] if extension not in command.extensions else []) - extension.commands.extend([command] if command not in extension.commands else []) - - # While genGroup() will call twice with aliased value, it doesn't provide all the information we need - dict = self.featureDictionary[extension.name]['enumconstant'] - for required in dict: - # group can be a Enum or Bitmask - for group in dict[required]: - if group in self.vk.enums: - if group not in extension.enumFields: - extension.enumFields[group] = [] # Dict needs init - enum = self.vk.enums[group] - # Need to convert all alias so they match what is in EnumField - enumList = list(map(lambda x: x if x not in self.enumFieldAliasMap else self.enumFieldAliasMap[x], dict[required][group])) - - for enumField in [x for x in enum.fields if x.name in enumList]: - # Make sure list is unique - enum.fieldExtensions.extend([extension] if extension not in enum.fieldExtensions else []) - enumField.extensions.extend([extension] if extension not in enumField.extensions else []) - extension.enumFields[group].extend([enumField] if enumField not in extension.enumFields[group] else []) - if group in self.vk.bitmasks: - if group not in extension.flags: - extension.flags[group] = [] # Dict needs init - bitmask = self.vk.bitmasks[group] - # Need to convert all alias so they match what is in Flags - flagList = list(map(lambda x: x if x not in self.flagAliasMap else self.flagAliasMap[x], dict[required][group])) - - for flags in [x for x in bitmask.flags if x.name in flagList]: - # Make sure list is unique - bitmask.flagExtensions.extend([extension] if extension not in bitmask.flagExtensions else []) - flags.extensions.extend([extension] if extension not in flags.extensions else []) - extension.flags[group].extend([flags] if flags not in extension.flags[group] else []) - - # Need to do 'enum'/'bitmask' after 'enumconstant' has applied everything so we can add implicit extensions - # - # Sometimes two extensions enable an Enum, but the newer extension version has extra flags allowed - # This information seems to be implicit, so need to update it here - # Go through each Flag and append the Enum extension to it - # - # ex. VkAccelerationStructureTypeKHR where GENERIC_KHR is not allowed with just VK_NV_ray_tracing - # This only works because the values are aliased as well, making the KHR a superset enum - for extension in self.vk.extensions.values(): - dict = self.featureDictionary[extension.name]['enum'] - for required in dict: - for group in dict[required]: - for enumName in dict[required][group]: - isAlias = enumName in self.enumAliasMap - enumName = self.enumAliasMap[enumName] if isAlias else enumName - if enumName in self.vk.enums: - enum = self.vk.enums[enumName] - enum.extensions.extend([extension] if extension not in enum.extensions else []) - extension.enums.extend([enum] if enum not in extension.enums else []) - # Update fields with implicit base extension - if isAlias: - continue - enum.fieldExtensions.extend([extension] if extension not in enum.fieldExtensions else []) - for enumField in [x for x in enum.fields if (not x.extensions or (x.extensions and all(e in enum.extensions for e in x.extensions)))]: - enumField.extensions.extend([extension] if extension not in enumField.extensions else []) - if enumName not in extension.enumFields: - extension.enumFields[enumName] = [] # Dict needs init - extension.enumFields[enumName].extend([enumField] if enumField not in extension.enumFields[enumName] else []) - - dict = self.featureDictionary[extension.name]['bitmask'] - for required in dict: - for group in dict[required]: - for bitmaskName in dict[required][group]: - bitmaskName = bitmaskName.replace('Flags', 'FlagBits') # Works since Flags isn't repeated in name - isAlias = bitmaskName in self.bitmaskAliasMap - bitmaskName = self.bitmaskAliasMap[bitmaskName] if isAlias else bitmaskName - if bitmaskName in self.vk.bitmasks: - bitmask = self.vk.bitmasks[bitmaskName] - bitmask.extensions.extend([extension] if extension not in bitmask.extensions else []) - extension.bitmasks.extend([bitmask] if bitmask not in extension.bitmasks else []) - # Update flags with implicit base extension - if isAlias: - continue - bitmask.flagExtensions.extend([extension] if extension not in bitmask.flagExtensions else []) - for flag in [x for x in bitmask.flags if (not x.extensions or (x.extensions and all(e in bitmask.extensions for e in x.extensions)))]: - flag.extensions.extend([extension] if extension not in flag.extensions else []) - if bitmaskName not in extension.flags: - extension.flags[bitmaskName] = [] # Dict needs init - extension.flags[bitmaskName].extend([flag] if flag not in extension.flags[bitmaskName] else []) - - # Some structs (ex VkAttachmentSampleCountInfoAMD) can have multiple alias pointing to same extension - for extension in self.vk.extensions.values(): - dict = self.featureDictionary[extension.name]['struct'] - for required in dict: - for group in dict[required]: - for structName in dict[required][group]: - isAlias = structName in self.structAliasMap - structName = self.structAliasMap[structName] if isAlias else structName - # An EXT struct can alias a KHR struct, - # that in turns aliaes a core struct - # => Try to propagate aliasing, it can safely result in a no-op - isAlias = structName in self.structAliasMap - structName = self.structAliasMap[structName] if isAlias else structName - if structName in self.vk.structs: - struct = self.vk.structs[structName] - struct.extensions.extend([extension] if extension not in struct.extensions else []) - - # While we update struct alias inside other structs, the command itself might have the struct as a first level param. - # We use this time to update params to have the promoted name - # Example - https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/9322 - for command in self.vk.commands.values(): - for member in command.params: - if member.type in self.structAliasMap: - member.type = self.structAliasMap[member.type] - - def endFile(self): - # This is the point were reg.py has ran, everything is collected - # We do some post processing now - self.applyExtensionDependency() - - # Use structs and commands to find which things are returnedOnly - for struct in [x for x in self.vk.structs.values() if not x.returnedOnly]: - for enum in [self.vk.enums[x.type] for x in struct.members if x.type in self.vk.enums]: - enum.returnedOnly = False - for bitmask in [self.vk.bitmasks[x.type] for x in struct.members if x.type in self.vk.bitmasks]: - bitmask.returnedOnly = False - for bitmask in [self.vk.bitmasks[x.type.replace('Flags', 'FlagBits')] for x in struct.members if x.type.replace('Flags', 'FlagBits') in self.vk.bitmasks]: - bitmask.returnedOnly = False - for command in self.vk.commands.values(): - for enum in [self.vk.enums[x.type] for x in command.params if x.type in self.vk.enums]: - enum.returnedOnly = False - for bitmask in [self.vk.bitmasks[x.type] for x in command.params if x.type in self.vk.bitmasks]: - bitmask.returnedOnly = False - for bitmask in [self.vk.bitmasks[x.type.replace('Flags', 'FlagBits')] for x in command.params if x.type.replace('Flags', 'FlagBits') in self.vk.bitmasks]: - bitmask.returnedOnly = False - - # Turn handle parents into pointers to classess - for handle in [x for x in self.vk.handles.values() if x.parent is not None]: - handle.parent = self.vk.handles[handle.parent] - # search up parent chain to see if instance or device - for handle in [x for x in self.vk.handles.values()]: - next_parent = handle.parent - while (not handle.instance and not handle.device): - handle.instance = next_parent.name == 'VkInstance' - handle.device = next_parent.name == 'VkDevice' - next_parent = next_parent.parent - - maxSyncSupport.queues = Queues.ALL - maxSyncSupport.stages = self.vk.bitmasks['VkPipelineStageFlagBits2'].flags - maxSyncEquivalent.accesses = self.vk.bitmasks['VkAccessFlagBits2'].flags - maxSyncEquivalent.stages = self.vk.bitmasks['VkPipelineStageFlagBits2'].flags - - # All inherited generators should run from here - self.generate() - - if cachingEnabled: - cachePath = os.path.join(tempfile.gettempdir(), f'vkobject_{os.getpid()}') - if not os.path.isfile(cachePath): - cacheFile = open(cachePath, 'wb') - pickle.dump(self.vk, cacheFile) - cacheFile.close() - - # This should not have to do anything but call into OutputGenerator - OutputGenerator.endFile(self) - - # - # Bypass the entire processing and load in the VkObject data - # Still need to handle the beingFile/endFile for reg.py - def generateFromCache(self, cacheVkObjectData, genOpts): - OutputGenerator.beginFile(self, genOpts) - self.filename = genOpts.filename - self.vk = cacheVkObjectData - self.generate() - OutputGenerator.endFile(self) - - # - # Processing point at beginning of each extension definition - def beginFeature(self, interface, emit): - OutputGenerator.beginFeature(self, interface, emit) - platform = interface.get('platform') - self.featureExtraProtec = self.vk.platforms[platform] if platform in self.vk.platforms else None - protect = self.vk.platforms[platform] if platform in self.vk.platforms else None - name = interface.get('name') - - if interface.tag == 'extension': - instance = interface.get('type') == 'instance' - device = not instance - depends = interface.get('depends') - vendorTag = interface.get('author') - platform = interface.get('platform') - provisional = boolGet(interface, 'provisional') - promotedto = interface.get('promotedto') - deprecatedby = interface.get('deprecatedby') - obsoletedby = interface.get('obsoletedby') - specialuse = splitIfGet(interface, 'specialuse') - # Not sure if better way to get this info - specVersion = self.featureDictionary[name]['enumconstant'][None][None][0] - nameString = self.featureDictionary[name]['enumconstant'][None][None][1] - - self.currentExtension = Extension(name, nameString, specVersion, instance, device, depends, vendorTag, - platform, protect, provisional, promotedto, deprecatedby, - obsoletedby, specialuse) - self.vk.extensions[name] = self.currentExtension - else: # version - number = interface.get('number') - if number != '1.0': - self.currentVersion = APISpecific.createApiVersion(self.targetApiName, name) - self.vk.versions[name] = self.currentVersion - - def endFeature(self): - OutputGenerator.endFeature(self) - self.currentExtension = None - self.currentVersion = None - - # - # All from XML - def genCmd(self, cmdinfo, name, alias): - OutputGenerator.genCmd(self, cmdinfo, name, alias) - - params = [] - for param in cmdinfo.elem.findall('param'): - paramName = param.find('name').text - paramType = textIfFind(param, 'type') - paramAlias = param.get('alias') - - cdecl = self.makeCParamDecl(param, 0) - pointer = '*' in cdecl or paramType.startswith('PFN_') - paramConst = 'const' in cdecl - fixedSizeArray = [x[:-1] for x in cdecl.split('[') if x.endswith(']')] - - paramNoautovalidity = boolGet(param, 'noautovalidity') - - nullTerminated = False - length = param.get('altlen') if param.get('altlen') is not None else param.get('len') - if length: - # we will either find it like "null-terminated" or "enabledExtensionCount,null-terminated" - # This finds both - nullTerminated = 'null-terminated' in length - length = length.replace(',null-terminated', '') if 'null-terminated' in length else length - length = None if length == 'null-terminated' else length - - if fixedSizeArray and not length: - length = ','.join(fixedSizeArray) - - # See Member::optional code for details of this - optionalValues = splitIfGet(param, 'optional') - optional = optionalValues is not None and optionalValues[0].lower() == "true" - optionalPointer = optionalValues is not None and len(optionalValues) > 1 and optionalValues[1].lower() == "true" - - # externsync will be 'true' or expression - # if expression, it should be same as 'true' - externSync = boolGet(param, 'externsync') - externSyncPointer = None if externSync else splitIfGet(param, 'externsync') - if not externSync and externSyncPointer is not None: - externSync = True - - params.append(Param(paramName, paramAlias, paramType, paramNoautovalidity, - paramConst, length, nullTerminated, pointer, fixedSizeArray, - optional, optionalPointer, - externSync, externSyncPointer, cdecl)) - - attrib = cmdinfo.elem.attrib - alias = attrib.get('alias') - tasks = splitIfGet(attrib, 'tasks') - - queues = getQueues(attrib) - successcodes = splitIfGet(attrib, 'successcodes') - errorcodes = splitIfGet(attrib, 'errorcodes') - cmdbufferlevel = attrib.get('cmdbufferlevel') - primary = cmdbufferlevel is not None and 'primary' in cmdbufferlevel - secondary = cmdbufferlevel is not None and 'secondary' in cmdbufferlevel - - renderpass = attrib.get('renderpass') - renderpass = CommandScope.NONE if renderpass is None else getattr(CommandScope, renderpass.upper()) - videocoding = attrib.get('videocoding') - videocoding = CommandScope.NONE if videocoding is None else getattr(CommandScope, videocoding.upper()) - - protoElem = cmdinfo.elem.find('proto') - returnType = textIfFind(protoElem, 'type') - - decls = self.makeCDecls(cmdinfo.elem) - cPrototype = decls[0] - cFunctionPointer = decls[1] - - protect = self.currentExtension.protect if self.currentExtension is not None else None - - # These coammds have no way from the XML to detect they would be an instance command - specialInstanceCommand = ['vkCreateInstance', 'vkEnumerateInstanceExtensionProperties','vkEnumerateInstanceLayerProperties', 'vkEnumerateInstanceVersion'] - instance = len(params) > 0 and (params[0].type == 'VkInstance' or params[0].type == 'VkPhysicalDevice' or name in specialInstanceCommand) - device = not instance - - implicitElem = cmdinfo.elem.find('implicitexternsyncparams') - implicitExternSyncParams = [x.text for x in implicitElem.findall('param')] if implicitElem else [] - - self.vk.commands[name] = Command(name, alias, protect, [], self.currentVersion, - returnType, params, instance, device, - tasks, queues, successcodes, errorcodes, - primary, secondary, renderpass, videocoding, - implicitExternSyncParams, cPrototype, cFunctionPointer) - - # - # List the enum for the commands - # TODO - Seems empty groups like `VkDeviceDeviceMemoryReportCreateInfoEXT` don't show up in here - def genGroup(self, groupinfo, groupName, alias): - # There can be case where the Enum/Bitmask is in a protect, but the individual - # fields also have their own protect - groupProtect = self.currentExtension.protect if hasattr(self.currentExtension, 'protect') and self.currentExtension.protect is not None else None - enumElem = groupinfo.elem - bitwidth = 32 if enumElem.get('bitwidth') is None else int(enumElem.get('bitwidth')) - fields = [] - if enumElem.get('type') == "enum": - if alias is not None: - self.enumAliasMap[groupName] = alias - return - - for elem in enumElem.findall('enum'): - fieldName = elem.get('name') - - if elem.get('alias') is not None: - self.enumFieldAliasMap[fieldName] = elem.get('alias') - continue - - negative = elem.get('dir') is not None - protect = elem.get('protect') - - # Some values have multiple extensions (ex VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR) - # genGroup() lists them twice - if next((x for x in fields if x.name == fieldName), None) is None: - fields.append(EnumField(fieldName, negative, protect, [])) - - self.vk.enums[groupName] = Enum(groupName, groupProtect, bitwidth, True, fields, [], []) - - else: # "bitmask" - if alias is not None: - self.bitmaskAliasMap[groupName] = alias - return - - for elem in enumElem.findall('enum'): - flagName = elem.get('name') - - if elem.get('alias') is not None: - self.flagAliasMap[flagName] = elem.get('alias') - continue - - flagMultiBit = False - flagZero = False - flagValue = intIfGet(elem, 'bitpos') - if flagValue is None: - flagValue = intIfGet(elem, 'value') - flagMultiBit = flagValue != 0 - flagZero = flagValue == 0 - protect = elem.get('protect') - - # Some values have multiple extensions (ex VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT) - # genGroup() lists them twice - if next((x for x in fields if x.name == flagName), None) is None: - fields.append(Flag(flagName, protect, flagValue, flagMultiBit, flagZero, [])) - - flagName = groupName.replace('FlagBits', 'Flags') - self.vk.bitmasks[groupName] = Bitmask(groupName, flagName, groupProtect, bitwidth, True, fields, [], []) - - def genType(self, typeInfo, typeName, alias): - OutputGenerator.genType(self, typeInfo, typeName, alias) - typeElem = typeInfo.elem - protect = self.currentExtension.protect if hasattr(self.currentExtension, 'protect') and self.currentExtension.protect is not None else None - category = typeElem.get('category') - if (category == 'struct' or category == 'union'): - extension = [self.currentExtension] if self.currentExtension is not None else [] - if alias is not None: - self.structAliasMap[typeName] = alias - return - - union = category == 'union' - - returnedOnly = boolGet(typeElem, 'returnedonly') - allowDuplicate = boolGet(typeElem, 'allowduplicate') - - extends = splitIfGet(typeElem, 'structextends') - extendedBy = self.registry.validextensionstructs[typeName] if len(self.registry.validextensionstructs[typeName]) > 0 else None - - membersElem = typeInfo.elem.findall('.//member') - members = [] - sType = None - - for member in membersElem: - for comment in member.findall('comment'): - member.remove(comment) - - name = textIfFind(member, 'name') - type = textIfFind(member, 'type') - sType = member.get('values') if member.get('values') is not None else sType - externSync = boolGet(member, 'externsync') - noautovalidity = boolGet(member, 'noautovalidity') - limittype = member.get('limittype') - - nullTerminated = False - length = member.get('altlen') if member.get('altlen') is not None else member.get('len') - if length: - # we will either find it like "null-terminated" or "enabledExtensionCount,null-terminated" - # This finds both - nullTerminated = 'null-terminated' in length - length = length.replace(',null-terminated', '') if 'null-terminated' in length else length - length = None if length == 'null-terminated' else length - - cdecl = self.makeCParamDecl(member, 0) - pointer = '*' in cdecl or type.startswith('PFN_') - const = 'const' in cdecl - # Some structs like VkTransformMatrixKHR have a 2D array - fixedSizeArray = [x[:-1] for x in cdecl.split('[') if x.endswith(']')] - - if fixedSizeArray and not length: - length = ','.join(fixedSizeArray) - - # if a pointer, this can be a something like: - # optional="true,false" for ppGeometries - # optional="false,true" for pPhysicalDeviceCount - # the first is if the variable itself is optional - # the second is the value of the pointer is optiona; - optionalValues = splitIfGet(member, 'optional') - optional = optionalValues is not None and optionalValues[0].lower() == "true" - optionalPointer = optionalValues is not None and len(optionalValues) > 1 and optionalValues[1].lower() == "true" - - members.append(Member(name, type, noautovalidity, limittype, - const, length, nullTerminated, pointer, fixedSizeArray, - optional, optionalPointer, - externSync, cdecl)) - - self.vk.structs[typeName] = Struct(typeName, extension, self.currentVersion, protect, members, - union, returnedOnly, sType, allowDuplicate, extends, extendedBy) - - elif category == 'handle': - if alias is not None: - return - type = typeElem.get('objtypeenum') - - # will resolve these later, the VulkanObjectType doesn't list things in dependent order - parent = typeElem.get('parent') - instance = typeName == 'VkInstance' - device = typeName == 'VkDevice' - - dispatchable = typeElem.find('type').text == 'VK_DEFINE_HANDLE' - - self.vk.handles[typeName] = Handle(typeName, type, protect, parent, instance, device, dispatchable) - - elif category == 'define': - if typeName == 'VK_HEADER_VERSION': - self.vk.headerVersion = typeElem.find('name').tail.strip() - - else: - # not all categories are used - # 'group'/'enum'/'bitmask' are routed to genGroup instead - # 'basetype'/'include' are only for headers - # 'funcpointer` ingore until needed - return - - def genSpirv(self, spirvinfo, spirvName, alias): - OutputGenerator.genSpirv(self, spirvinfo, spirvName, alias) - spirvElem = spirvinfo.elem - name = spirvElem.get('name') - extension = True if spirvElem.tag == 'spirvextension' else False - capability = not extension - - enables = [] - for elem in spirvElem: - version = elem.attrib.get('version') - extensionEnable = elem.attrib.get('extension') - struct = elem.attrib.get('struct') - feature = elem.attrib.get('feature') - requires = elem.attrib.get('requires') - propertyEnable = elem.attrib.get('property') - member = elem.attrib.get('member') - value = elem.attrib.get('value') - enables.append(SpirvEnables(version, extensionEnable, struct, feature, - requires, propertyEnable, member, value)) - - self.vk.spirv.append(Spirv(name, extension, capability, enables)) - - def genFormat(self, format, formatinfo, alias): - OutputGenerator.genFormat(self, format, formatinfo, alias) - formatElem = format.elem - name = formatElem.get('name') - - components = [] - for component in formatElem.iterfind('component'): - type = component.get('name') - bits = component.get('bits') - numericFormat = component.get('numericFormat') - planeIndex = intIfGet(component, 'planeIndex') - components.append(FormatComponent(type, bits, numericFormat, planeIndex)) - - planes = [] - for plane in formatElem.iterfind('plane'): - index = int(plane.get('index')) - widthDivisor = int(plane.get('widthDivisor')) - heightDivisor = int(plane.get('heightDivisor')) - compatible = plane.get('compatible') - planes.append(FormatPlane(index, widthDivisor, heightDivisor, compatible)) - - className = formatElem.get('class') - blockSize = int(formatElem.get('blockSize')) - texelsPerBlock = int(formatElem.get('texelsPerBlock')) - blockExtent = splitIfGet(formatElem, 'blockExtent') - packed = intIfGet(formatElem, 'packed') - chroma = formatElem.get('chroma') - compressed = formatElem.get('compressed') - spirvImageFormat = formatElem.find('spirvimageformat') - if spirvImageFormat is not None: - spirvImageFormat = spirvImageFormat.get('name') - - self.vk.formats[name] = Format(name, className, blockSize, texelsPerBlock, - blockExtent, packed, chroma, compressed, - components, planes, spirvImageFormat) - - def genSyncStage(self, sync): - OutputGenerator.genSyncStage(self, sync) - syncElem = sync.elem - - support = maxSyncSupport - supportElem = syncElem.find('syncsupport') - if supportElem is not None: - queues = getQueues(supportElem) - stageNames = splitIfGet(supportElem, 'stage') - stages = [x for x in self.vk.bitmasks['VkPipelineStageFlagBits2'].flags if x.name in stageNames] if stageNames is not None else None - support = SyncSupport(queues, stages, False) - - equivalent = maxSyncEquivalent - equivalentElem = syncElem.find('syncequivalent') - if equivalentElem is not None: - stageNames = splitIfGet(equivalentElem, 'stage') - stages = [x for x in self.vk.bitmasks['VkPipelineStageFlagBits2'].flags if x.name in stageNames] if stageNames is not None else None - accessNames = splitIfGet(equivalentElem, 'access') - accesses = [x for x in self.vk.bitmasks['VkAccessFlagBits2'].flags if x.name in accessNames] if accessNames is not None else None - equivalent = SyncEquivalent(stages, accesses, False) - - flagName = syncElem.get('name') - flag = [x for x in self.vk.bitmasks['VkPipelineStageFlagBits2'].flags if x.name == flagName] - # This check is needed because not all API variants have VK_KHR_synchronization2 - if flag: - self.vk.syncStage.append(SyncStage(flag[0], support, equivalent)) - - def genSyncAccess(self, sync): - OutputGenerator.genSyncAccess(self, sync) - syncElem = sync.elem - - support = maxSyncSupport - supportElem = syncElem.find('syncsupport') - if supportElem is not None: - queues = getQueues(supportElem) - stageNames = splitIfGet(supportElem, 'stage') - stages = [x for x in self.vk.bitmasks['VkPipelineStageFlagBits2'].flags if x.name in stageNames] if stageNames is not None else None - support = SyncSupport(queues, stages, False) - - equivalent = maxSyncEquivalent - equivalentElem = syncElem.find('syncequivalent') - if equivalentElem is not None: - stageNames = splitIfGet(equivalentElem, 'stage') - stages = [x for x in self.vk.bitmasks['VkPipelineStageFlagBits2'].flags if x.name in stageNames] if stageNames is not None else None - accessNames = splitIfGet(equivalentElem, 'access') - accesses = [x for x in self.vk.bitmasks['VkAccessFlagBits2'].flags if x.name in accessNames] if accessNames is not None else None - equivalent = SyncEquivalent(stages, accesses, False) - - flagName = syncElem.get('name') - flag = [x for x in self.vk.bitmasks['VkAccessFlagBits2'].flags if x.name == flagName] - # This check is needed because not all API variants have VK_KHR_synchronization2 - if flag: - self.vk.syncAccess.append(SyncAccess(flag[0], support, equivalent)) - - def genSyncPipeline(self, sync): - OutputGenerator.genSyncPipeline(self, sync) - syncElem = sync.elem - name = syncElem.get('name') - depends = splitIfGet(syncElem, 'depends') - stages = [] - for stageElem in syncElem.findall('syncpipelinestage'): - order = stageElem.get('order') - before = stageElem.get('before') - after = stageElem.get('after') - value = stageElem.text - stages.append(SyncPipelineStage(order, before, after, value)) - - self.vk.syncPipeline.append(SyncPipeline(name, depends, stages)) diff --git a/scripts/generators/dispatch_table_generator.py b/scripts/generators/dispatch_table_generator.py index ebab6ea..f2dd57d 100644 --- a/scripts/generators/dispatch_table_generator.py +++ b/scripts/generators/dispatch_table_generator.py @@ -7,7 +7,7 @@ # SPDX-License-Identifier: Apache-2.0 import os -from generators.base_generator import BaseGenerator +from base_generator import BaseGenerator from generators.generator_utils import PlatformGuardHelper class DispatchTableOutputGenerator(BaseGenerator): diff --git a/scripts/generators/enum_string_helper_generator.py b/scripts/generators/enum_string_helper_generator.py index 33a0a2a..28e7e54 100644 --- a/scripts/generators/enum_string_helper_generator.py +++ b/scripts/generators/enum_string_helper_generator.py @@ -7,7 +7,7 @@ # SPDX-License-Identifier: Apache-2.0 import os -from generators.base_generator import BaseGenerator +from base_generator import BaseGenerator from generators.generator_utils import PlatformGuardHelper class EnumStringHelperOutputGenerator(BaseGenerator): diff --git a/scripts/generators/format_utils_generator.py b/scripts/generators/format_utils_generator.py index ee05230..ed2cdd8 100644 --- a/scripts/generators/format_utils_generator.py +++ b/scripts/generators/format_utils_generator.py @@ -7,8 +7,8 @@ # SPDX-License-Identifier: Apache-2.0 import os -from generators.vulkan_object import (Format) -from generators.base_generator import BaseGenerator +from vulkan_object import (Format) +from base_generator import BaseGenerator # Make C name friendly class name def getClassName(className: str) -> str: diff --git a/scripts/generators/safe_struct_generator.py b/scripts/generators/safe_struct_generator.py index cb67ccb..0e415b3 100644 --- a/scripts/generators/safe_struct_generator.py +++ b/scripts/generators/safe_struct_generator.py @@ -10,8 +10,8 @@ import os import re -from generators.vulkan_object import Struct, Member -from generators.base_generator import BaseGenerator +from vulkan_object import Struct, Member +from base_generator import BaseGenerator from generators.generator_utils import PlatformGuardHelper class SafeStructOutputGenerator(BaseGenerator): diff --git a/scripts/generators/struct_helper_generator.py b/scripts/generators/struct_helper_generator.py index f92a872..12cb231 100644 --- a/scripts/generators/struct_helper_generator.py +++ b/scripts/generators/struct_helper_generator.py @@ -19,7 +19,7 @@ # limitations under the License. import os -from generators.base_generator import BaseGenerator +from base_generator import BaseGenerator from generators.generator_utils import PlatformGuardHelper class StructHelperOutputGenerator(BaseGenerator): diff --git a/scripts/generators/vulkan_object.py b/scripts/generators/vulkan_object.py deleted file mode 100644 index bb3bd24..0000000 --- a/scripts/generators/vulkan_object.py +++ /dev/null @@ -1,405 +0,0 @@ -#!/usr/bin/python3 -i -# -# Copyright (c) 2023-2024 Valve Corporation -# Copyright (c) 2023-2024 LunarG, Inc. -# -# SPDX-License-Identifier: Apache-2.0 - -from dataclasses import dataclass, field -from enum import IntFlag, Enum, auto - -@dataclass -class Extension: - """""" - name: str # ex) VK_KHR_SURFACE - nameString: str # marco with string, ex) VK_KHR_SURFACE_EXTENSION_NAME - specVersion: str # marco with string, ex) VK_KHR_SURFACE_SPEC_VERSION - - # Only one will be True, the other is False - instance: bool - device: bool - - depends: (str | None) - vendorTag: (str | None) # ex) EXT, KHR, etc - platform: (str | None) # ex) android - protect: (str | None) # ex) VK_USE_PLATFORM_ANDROID_KHR - provisional: bool - promotedTo: (str | None) # ex) VK_VERSION_1_1 - deprecatedBy: (str | None) - obsoletedBy: (str | None) - specialUse: list[str] - - # These are here to allow for easy reverse lookups - # Quotes allow us to forward declare the dataclass - commands: list['Command'] = field(default_factory=list, init=False) - enums: list['Enum'] = field(default_factory=list, init=False) - bitmasks: list['Bitmask'] = field(default_factory=list, init=False) - # Use the Enum name to see what fields are extended - enumFields: dict[str, list['EnumField']] = field(default_factory=dict, init=False) - # Use the Bitmaks name to see what flags are extended - flags: dict[str, list['Flag']] = field(default_factory=dict, init=False) - -@dataclass -class Version: - """ - which represents a version - This will NEVER be Version 1.0, since having 'no version' is same as being 1.0 - """ - name: str # ex) VK_VERSION_1_1 - nameString: str # ex) "VK_VERSION_1_1" (no marco, so has quotes) - nameApi: str # ex) VK_API_VERSION_1_1 - -@dataclass -class Handle: - """ which represents a dispatch handle""" - name: str # ex) VkBuffer - type: str # ex) VK_OBJECT_TYPE_BUFFER - protect: (str | None) # ex) VK_USE_PLATFORM_ANDROID_KHR - - parent: 'Handle' # Chain of parent handles, can be None - - # Only one will be True, the other is False - instance: bool - device: bool - - dispatchable: bool - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class Param: - """""" - name: str - alias: str - type: str # ex) void, VkFormat, etc - - noAutoValidity: bool - - const: bool # type contains 'const' - length: (str | None) # the known length of pointer, will never be 'null-terminated' - nullTerminated: bool # If a UTF-8 string, it will be null-terminated - pointer: bool # type contains a pointer (include 'PFN' function pointers) - fixedSizeArray: list[str] # for VkTransformMatrixKHR:matrix this is [3, 4] - - optional: bool - optionalPointer: bool # if type contains a pointer, is the pointer value optional - - externSync: bool - externSyncPointer: list[str] # if type contains a pointer, might only specific members modified - - # C string of member, example: - # - const void* pNext - # - VkFormat format - # - VkStructureType sType - cDeclaration: str - - def __lt__(self, other): - return self.name < other.name - -class Queues(IntFlag): - TRANSFER = auto() # VK_QUEUE_TRANSFER_BIT - GRAPHICS = auto() # VK_QUEUE_GRAPHICS_BIT - COMPUTE = auto() # VK_QUEUE_COMPUTE_BIT - PROTECTED = auto() # VK_QUEUE_PROTECTED_BIT - SPARSE_BINDING = auto() # VK_QUEUE_SPARSE_BINDING_BIT - OPTICAL_FLOW = auto() # VK_QUEUE_OPTICAL_FLOW_BIT_NV - DECODE = auto() # VK_QUEUE_VIDEO_DECODE_BIT_KHR - ENCODE = auto() # VK_QUEUE_VIDEO_ENCODE_BIT_KHR - ALL = TRANSFER | GRAPHICS | COMPUTE | PROTECTED | SPARSE_BINDING | OPTICAL_FLOW | DECODE | ENCODE - -class CommandScope(Enum): - NONE = auto() - INSIDE = auto() - OUTSIDE = auto() - BOTH = auto() - -@dataclass -class Command: - """""" - name: str # ex) vkCmdDraw - alias: str # Because commands are interfaces into layers/drivers, we need all command alias - protect: (str | None) # ex) 'VK_ENABLE_BETA_EXTENSIONS' - - extensions: list[Extension] # All extensions that enable the struct - version: (Version | None) # None if Version 1.0 - - returnType: str # ex) void, VkResult, etc - - params: list[Param] # Each parameter of the command - - # Only one will be True, the other is False - instance: bool - device: bool - - tasks: list[str] # ex) [ action, state, synchronization ] - queues: Queues # zero == No Queues found - successCodes: list[str] # ex) [ VK_SUCCESS, VK_INCOMPLETE ] - errorCodes: list[str] # ex) [ VK_ERROR_OUT_OF_HOST_MEMORY ] - - # Shows support if command can be in a primary and/or secondary command buffer - primary: bool - secondary: bool - - renderPass: CommandScope - videoCoding: CommandScope - - implicitExternSyncParams: list[str] - - # C prototype string - ex: - # VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( - # const VkInstanceCreateInfo* pCreateInfo, - # const VkAllocationCallbacks* pAllocator, - # VkInstance* pInstance); - cPrototype: str - - # function pointer typedef - ex: - # typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance) - # (const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance); - cFunctionPointer: str - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class Member: - """""" - name: str # ex) sharingMode - type: str # ex) VkSharingMode - - noAutoValidity: bool - limitType: (str | None) # ex) 'max', 'bitmask', 'bits', 'min,mul' - - const: bool # type contains 'const' - length: (str | None) # the known length of pointer, will never be 'null-terminated' - nullTerminated: bool # If a UTF-8 string, it will be null-terminated - pointer: bool # type contains a pointer (include 'PFN' function pointers) - fixedSizeArray: list[str] # for VkTransformMatrixKHR:matrix this is [3, 4] - - optional: bool - optionalPointer: bool # if type contains a pointer, is the pointer value optional - - externSync: bool - - # C string of member, example: - # - const void* pNext - # - VkFormat format - # - VkStructureType sType - cDeclaration: str - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class Struct: - """ or """ - name: str # ex. VkBufferCreateInfo - extensions: list[Extension] # All extensions that enable the struct - version: (Version | None) # None if Version 1.0 - protect: (str | None) # ex) VK_ENABLE_BETA_EXTENSIONS - - members: list[Member] - - union: bool # Unions are just a subset of a Structs - returnedOnly: bool - - sType: (str | None) # ex) VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO - allowDuplicate: bool # can have a pNext point to itself - - # These use to be list['Struct'] but some circular loops occur and cause - # pydevd warnings and made debugging slow (30 seconds to index a Struct) - extends: list[str] # Struct names that this struct extends - extendedBy: list[str] # Struct names that can be extended by this struct - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class EnumField: - """ of type enum""" - name: str # ex) VK_DYNAMIC_STATE_SCISSOR - negative: bool # True if negative values are allowed (ex. VkResult) - protect: (str | None) # ex) VK_ENABLE_BETA_EXTENSIONS - - # some fields are enabled from 2 extensions (ex) VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR) - extensions: list[Extension] # None if part of 1.0 core - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class Enum: - """ of type enum""" - name: str # ex) VkDynamicState - protect: (str | None) # ex) VK_ENABLE_BETA_EXTENSIONS - - bitWidth: int # 32 or 64 - returnedOnly: bool - - fields: list[EnumField] - - extensions: list[Extension] # None if part of 1.0 core - # Unique list of all extension that are involved in 'fields' (superset of 'extensions') - fieldExtensions: list[Extension] - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class Flag: - """ of type bitmask""" - name: str # ex) VK_ACCESS_2_SHADER_READ_BIT - protect: (str | None) # ex) VK_ENABLE_BETA_EXTENSIONS - - value: int - multiBit: bool # if true, more than one bit is set (ex) VK_SHADER_STAGE_ALL_GRAPHICS) - zero: bool # if true, the value is zero (ex) VK_PIPELINE_STAGE_NONE) - - # some fields are enabled from 2 extensions (ex) VK_TOOL_PURPOSE_DEBUG_REPORTING_BIT_EXT) - extensions: list[Extension] # None if part of 1.0 core - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class Bitmask: - """ of type bitmask""" - name: str # ex) VkAccessFlagBits2 - flagName: str # ex) VkAccessFlags2 - protect: (str | None) # ex) VK_ENABLE_BETA_EXTENSIONS - - bitWidth: int # 32 or 64 - returnedOnly: bool - - flags: list[Flag] - - extensions: list[Extension] # None if part of 1.0 core - # Unique list of all extension that are involved in 'flag' (superset of 'extensions') - flagExtensions: list[Extension] - - def __lt__(self, other): - return self.name < other.name - -@dataclass -class FormatComponent: - """""" - type: str # ex) R, G, B, A, D, S, etc - bits: str # will be an INT or 'compressed' - numericFormat: str # ex) UNORM, SINT, etc - planeIndex: (int | None) # None if no planeIndex in format - -@dataclass -class FormatPlane: - """""" - index: int - widthDivisor: int - heightDivisor: int - compatible: str - -@dataclass -class Format: - """""" - name: str - className: str - blockSize: int - texelsPerBlock: int - blockExtent: list[str] - packed: (int | None) # None == not-packed - chroma: (str | None) - compressed: (str | None) - components: list[FormatComponent] # - planes: list[FormatPlane] # - spirvImageFormat: (str | None) - -@dataclass -class SyncSupport: - """""" - queues: Queues - stages: list[Flag] # VkPipelineStageFlagBits2 - max: bool # If this supports max values - -@dataclass -class SyncEquivalent: - """""" - stages: list[Flag] # VkPipelineStageFlagBits2 - accesses: list[Flag] # VkAccessFlagBits2 - max: bool # If this equivalent to everything - -@dataclass -class SyncStage: - """""" - flag: Flag # VkPipelineStageFlagBits2 - support: SyncSupport - equivalent: SyncEquivalent - -@dataclass -class SyncAccess: - """""" - flag: Flag # VkAccessFlagBits2 - support: SyncSupport - equivalent: SyncEquivalent - -@dataclass -class SyncPipelineStage: - """""" - order: (str | None) - before: (str | None) - after: (str | None) - value: str - -@dataclass -class SyncPipeline: - """""" - name: str - depends: list[str] - stages: list[SyncPipelineStage] - -@dataclass -class SpirvEnables: - """What is needed to enable the SPIR-V element""" - version: (str | None) - extension: (str | None) - struct: (str | None) - feature: (str | None) - requires: (str | None) - property: (str | None) - member: (str | None) - value: (str | None) - -@dataclass -class Spirv: - """ and """ - name: str - # Only one will be True, the other is False - extension: bool - capability: bool - enable: list[SpirvEnables] - -# This is the global Vulkan Object that holds all the information from parsing the XML -# This class is designed so all generator scripts can use this to obtain data -@dataclass -class VulkanObject(): - headerVersion: int = 0 # value of VK_HEADER_VERSION - - extensions: dict[str, Extension] = field(default_factory=dict, init=False) - versions: dict[str, Version] = field(default_factory=dict, init=False) - - handles: dict[str, Handle] = field(default_factory=dict, init=False) - commands: dict[str, Command] = field(default_factory=dict, init=False) - structs: dict[str, Struct] = field(default_factory=dict, init=False) - enums: dict[str, Enum] = field(default_factory=dict, init=False) - bitmasks: dict[str, Bitmask] = field(default_factory=dict, init=False) - formats: dict[str, Format] = field(default_factory=dict, init=False) - - syncStage: list[SyncStage] = field(default_factory=list, init=False) - syncAccess: list[SyncAccess] = field(default_factory=list, init=False) - syncPipeline: list[SyncPipeline] = field(default_factory=list, init=False) - - spirv: list[Spirv] = field(default_factory=list, init=False) - - # ex) [ xlib : VK_USE_PLATFORM_XLIB_KHR ] - platforms: dict[str, str] = field(default_factory=dict, init=False) - # list of all vendor Sufix names (KHR, EXT, etc. ) - vendorTags: list[str] = field(default_factory=list, init=False) - # ex) [ Queues.COMPUTE : VK_QUEUE_COMPUTE_BIT ] - queueBits: dict[IntFlag, str] = field(default_factory=dict, init=False)