diff options
Diffstat (limited to 'scripts/generators/vulkaninfo_generator.py')
| -rw-r--r-- | scripts/generators/vulkaninfo_generator.py | 1983 |
1 files changed, 679 insertions, 1304 deletions
diff --git a/scripts/generators/vulkaninfo_generator.py b/scripts/generators/vulkaninfo_generator.py index 20e408e4..6843e7eb 100644 --- a/scripts/generators/vulkaninfo_generator.py +++ b/scripts/generators/vulkaninfo_generator.py @@ -19,16 +19,9 @@ # # Author: Charles Giessen <charles@lunarg.com> -import re -import os -import sys -import copy -import operator +from base_generator import BaseGenerator + from collections import OrderedDict -import generator as gen -from common_codegen import GetFeatureProtect -from generator import GeneratorOptions, OutputGenerator -import xml.etree.ElementTree as etree LICENSE_HEADER = ''' /* @@ -117,28 +110,24 @@ EXTENSION_CATEGORIES = OrderedDict(( ('phys_device_props2', {'extends': 'VkPhysicalDeviceProperties2', 'type': EXTENSION_TYPE_BOTH, - 'holder_type': 'VkPhysicalDeviceProperties2', 'print_iterator': True, 'can_show_promoted_structs': True, 'ignore_vendor_exclusion': False}), ('phys_device_mem_props2', {'extends': 'VkPhysicalDeviceMemoryProperties2', 'type': EXTENSION_TYPE_DEVICE, - 'holder_type':'VkPhysicalDeviceMemoryProperties2', 'print_iterator': False, 'can_show_promoted_structs': False, 'ignore_vendor_exclusion': False}), ('phys_device_features2', - {'extends': 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo', + {'extends': 'VkPhysicalDeviceFeatures2', 'type': EXTENSION_TYPE_DEVICE, - 'holder_type': 'VkPhysicalDeviceFeatures2', 'print_iterator': True, 'can_show_promoted_structs': True, 'ignore_vendor_exclusion': False}), ('surface_capabilities2', {'extends': 'VkSurfaceCapabilities2KHR', 'type': EXTENSION_TYPE_BOTH, - 'holder_type': 'VkSurfaceCapabilities2KHR', 'print_iterator': True, 'can_show_promoted_structs': False, 'ignore_vendor_exclusion': False, @@ -146,421 +135,221 @@ EXTENSION_CATEGORIES = OrderedDict(( ('format_properties2', {'extends': 'VkFormatProperties2', 'type': EXTENSION_TYPE_DEVICE, - 'holder_type':'VkFormatProperties2', 'print_iterator': True, 'can_show_promoted_structs': False, 'ignore_vendor_exclusion': False}), ('queue_properties2', {'extends': 'VkQueueFamilyProperties2', 'type': EXTENSION_TYPE_DEVICE, - 'holder_type': 'VkQueueFamilyProperties2', 'print_iterator': True, 'can_show_promoted_structs': False, 'ignore_vendor_exclusion': False}), ('video_profile_info', {'extends': 'VkVideoProfileInfoKHR', 'type': EXTENSION_TYPE_DEVICE, - 'holder_type': 'VkVideoProfileInfoKHR', 'print_iterator': True, 'can_show_promoted_structs': False, 'ignore_vendor_exclusion': True}), ('video_capabilities', {'extends': 'VkVideoCapabilitiesKHR', 'type': EXTENSION_TYPE_DEVICE, - 'holder_type': 'VkVideoCapabilitiesKHR', 'print_iterator': True, 'can_show_promoted_structs': False, 'ignore_vendor_exclusion': True,}), ('video_format_properties', {'extends': 'VkVideoFormatPropertiesKHR', 'type': EXTENSION_TYPE_DEVICE, - 'holder_type': 'VkVideoFormatPropertiesKHR', 'print_iterator': True, 'can_show_promoted_structs': False, 'ignore_vendor_exclusion': True}) )) -class VulkanInfoGeneratorOptions(GeneratorOptions): - def __init__(self, - conventions=None, - input=None, - filename=None, - directory='.', - genpath = None, - apiname=None, - profile=None, - versions='.*', - emitversions='.*', - defaultExtensions=None, - addExtensions=None, - removeExtensions=None, - emitExtensions=None, - sortProcedure=None, - prefixText='', - genFuncPointers=True, - protectFile=True, - protectFeature=True, - protectProto=None, - protectProtoStr=None, - apicall='', - apientry='', - apientryp='', - indentFuncProto=True, - indentFuncPointer=False, - alignFuncParam=0, - expandEnumerants=True, - registryFile='vk.xml' - ): - GeneratorOptions.__init__(self, - conventions = conventions, - filename = filename, - directory = directory, - genpath = genpath, - apiname = apiname, - profile = profile, - versions = versions, - emitversions = emitversions, - defaultExtensions = defaultExtensions, - addExtensions = addExtensions, - removeExtensions = removeExtensions, - emitExtensions = emitExtensions, - sortProcedure = sortProcedure) - self.input = input - self.prefixText = prefixText - self.genFuncPointers = genFuncPointers - self.protectFile = protectFile - self.protectFeature = protectFeature - self.protectProto = protectProto - self.protectProtoStr = protectProtoStr - self.apicall = apicall - self.apientry = apientry - self.apientryp = apientryp - self.indentFuncProto = indentFuncProto - self.indentFuncPointer = indentFuncPointer - self.alignFuncParam = alignFuncParam - self.registryFile = registryFile - -# VulkanInfoGenerator - subclass of OutputGenerator. -# Generates a vulkan info output helper function - - -class VulkanInfoGenerator(OutputGenerator): - - def __init__(self, - errFile=sys.stderr, - warnFile=sys.stderr, - diagFile=sys.stdout): - OutputGenerator.__init__(self, errFile, warnFile, diagFile) - - self.constants = OrderedDict() - - self.types_to_gen = set() - - self.extension_sets = OrderedDict() - for ext_cat in EXTENSION_CATEGORIES.keys(): - self.extension_sets[ext_cat] = set() - - self.enums = [] - self.flags = [] - self.bitmasks = [] +class VulkanInfoGenerator(BaseGenerator): + def __init__(self): + BaseGenerator.__init__(self) self.format_ranges = [] - self.all_structures = [] - self.aliases = OrderedDict() - - self.extFuncs = OrderedDict() - self.extTypes = OrderedDict() - - self.vendor_abbreviations = [] - self.vulkan_versions = [] - - def beginFile(self, genOpts): - gen.OutputGenerator.beginFile(self, genOpts) - - for node in self.registry.reg.findall('enums'): - if node.get('name') == 'API Constants': - for item in node.findall('enum'): - self.constants[item.get('name')] = item.get('value') - - for node in self.registry.reg.find('extensions').findall('extension'): - ext = VulkanExtension(node) - for item in ext.vktypes: - if item not in self.extTypes: - self.extTypes[item] = [] - self.extTypes[item].append(ext) - for item in ext.vkfuncs: - self.extFuncs[item] = ext - # need list of venders to blacklist vendor extensions - for tag in self.registry.reg.find('tags'): - if tag.get('name') not in ['KHR', 'EXT']: - self.vendor_abbreviations.append('_' + tag.get('name')) - - for ver in self.registry.reg.findall('feature'): - self.vulkan_versions.append(VulkanVersion(ver)) - - def endFile(self): + def generate(self): self.findFormatRanges() # gather the types that are needed to generate types_to_gen = set() - for s in ENUMS_TO_GEN: - types_to_gen.add(s) - - for f in FLAGS_TO_GEN: - types_to_gen.add(f) + types_to_gen.update(ENUMS_TO_GEN) + types_to_gen.update(FLAGS_TO_GEN) + types_to_gen.update(STRUCTURES_TO_GEN) + + extension_types = {} + for key, ext_info in EXTENSION_CATEGORIES.items(): + extension_types[key] = [] + + for extended_struct in self.vk.structs[ext_info.get('extends')].extendedBy: + if ext_info.get('exclude') is not None and extended_struct in ext_info.get('exclude'): + continue + elif ext_info.get('ignore_vendor_exclusion'): + extension_types[key].append(extended_struct) + continue + vendor_tags = [] + for extension in self.vk.structs[extended_struct].extensions: + vendor_tags.append(extension.split('_')[1]) + if len(vendor_tags) == 0 or 'KHR' in vendor_tags or 'EXT' in vendor_tags: + extension_types[key].append(extended_struct) + extension_types[key] = sorted(extension_types[key]) + types_to_gen.update(extension_types[key]) + + # find all the types that need + types_to_gen.update(self.findAllTypesToGen(types_to_gen)) - types_to_gen.update( - GatherTypesToGen(self.all_structures, STRUCTURES_TO_GEN)) - for key, info in EXTENSION_CATEGORIES.items(): - types_to_gen.update( - GatherTypesToGen(self.all_structures, self.extension_sets[key], info.get('exclude'))) types_to_gen = sorted(types_to_gen) - names_of_structures_to_gen = set() - for s in self.all_structures: - if s.name in types_to_gen: - names_of_structures_to_gen.add(s.name) - names_of_structures_to_gen = sorted(names_of_structures_to_gen) + comparison_types_to_gen = set() + comparison_types_to_gen.update(STRUCT_COMPARISONS_TO_GEN) + comparison_types_to_gen.update(self.findAllTypesToGen(comparison_types_to_gen)) + comparison_types_to_gen = sorted(comparison_types_to_gen) - structs_to_comp = set() - for s in STRUCT_COMPARISONS_TO_GEN: - structs_to_comp.add(s) - structs_to_comp.update( - GatherTypesToGen(self.all_structures, STRUCT_COMPARISONS_TO_GEN)) - - for key, value in self.extension_sets.items(): - self.extension_sets[key] = sorted(value) - - self.enums = sorted(self.enums, key=operator.attrgetter('name')) - self.flags = sorted(self.flags, key=operator.attrgetter('name')) - self.bitmasks = sorted(self.bitmasks, key=operator.attrgetter('name')) - self.all_structures = sorted(self.all_structures, key=operator.attrgetter('name')) # print the types gathered - out = '' - out += LICENSE_HEADER + '\n' - out += '#include "vulkaninfo.h"\n' - out += '#include "outputprinter.h"\n' - out += CUSTOM_FORMATTERS + out = [] + out.append(LICENSE_HEADER + '\n') + out.append('#include "vulkaninfo.h"\n') + out.append('#include "outputprinter.h"\n') + out.append(CUSTOM_FORMATTERS) + + out.extend(self.genVideoEnums()) - out += self.genVideoEnums() + for enum in (e for e in types_to_gen if e in self.vk.enums): + out.extend(self.PrintEnumToString(self.vk.enums[enum])) + out.extend(self.PrintEnum(self.vk.enums[enum])) - for enum in (e for e in self.enums if e.name in types_to_gen): - out += PrintEnumToString(enum, self) - out += PrintEnum(enum, self) + # Need to go through all flags to find if they or their associated bitmask needs printing + # This is because both bitmask and flag types are generated in PrintBitMask + for name in (x for x in sorted(self.vk.flags.keys()) if x in types_to_gen or self.vk.flags[x].bitmaskName in types_to_gen): + bitmask = self.vk.bitmasks[self.vk.flags[name].bitmaskName] - for flag in self.flags: - if flag.name in types_to_gen or flag.enum in types_to_gen: - for bitmask in (b for b in self.bitmasks if b.name == flag.enum): - out += PrintBitMask(bitmask, flag.name, self) + out.extend(self.PrintBitMask(bitmask, bitmask.flagName)) - if flag.name in FLAG_STRINGS_TO_GEN: - for bitmask in (b for b in self.bitmasks if b.name == flag.enum): - out += PrintBitMaskToString(bitmask, flag.name, self) + if bitmask.flagName in FLAG_STRINGS_TO_GEN: + out.extend(self.PrintBitMaskToString(bitmask, bitmask.flagName)) - for s in (x for x in self.all_structures if x.name in types_to_gen and x.name not in STRUCT_BLACKLIST): - out += PrintStructure(s) + for s in (x for x in types_to_gen if x in self.vk.structs and x not in STRUCT_BLACKLIST): + out.extend(self.PrintStructure(self.vk.structs[s])) for key, value in EXTENSION_CATEGORIES.items(): - out += PrintChainStruct(key, self.extension_sets[key], self.all_structures, value, self.extTypes, self.aliases, self.vulkan_versions) + out.extend(self.PrintChainStruct(key, extension_types[key], value)) - for s in (x for x in self.all_structures if x.name in structs_to_comp): - out += PrintStructComparisonForwardDecl(s) - for s in (x for x in self.all_structures if x.name in structs_to_comp): - out += PrintStructComparison(s) - for s in (x for x in self.all_structures if x.name in STRUCT_SHORT_VERSIONS_TO_GEN): - out += PrintStructShort(s) + for s in (x for x in comparison_types_to_gen if x in self.vk.structs): + out.extend(self.PrintStructComparisonForwardDecl(self.vk.structs[s])) + for s in (x for x in comparison_types_to_gen if x in self.vk.structs): + out.extend(self.PrintStructComparison(self.vk.structs[s])) + for s in (x for x in types_to_gen if x in self.vk.structs and x in STRUCT_SHORT_VERSIONS_TO_GEN): + out.extend(self.PrintStructShort(self.vk.structs[s])) - out += 'auto format_ranges = std::array{\n' + out.append('auto format_ranges = std::array{\n') for f in self.format_ranges: - out += f' FormatRange{{{f.minimum_instance_version}, {f.extension_name if f.extension_name is not None else "nullptr"}, ' - out += f'static_cast<VkFormat>({f.first_format}), static_cast<VkFormat>({f.last_format})}},\n' - out += '};\n' + out.append(f' FormatRange{{{f.minimum_instance_version}, {self.vk.extensions[f.extensions[0]].nameString if len(f.extensions) > 0 else "nullptr"}, ') + out.append(f'static_cast<VkFormat>({f.first_format}), static_cast<VkFormat>({f.last_format})}},\n') + out.append('};\n') - out += self.genVideoProfileUtils() + out.extend(self.genVideoProfileUtils()) - gen.write(out, file=self.outFile) + self.write(''.join(out)) - gen.OutputGenerator.endFile(self) def genVideoEnums(self): - # We need to add dumping utilities for enums declared in the video std headers and directly - # present in the Vulkan API structures. In order to do that we really have no choice but - # to parse the video.xml and generate the utilities based on the enum types defined there - videoRegistryFile = self.genOpts.registryFile.replace('vk.xml', 'video.xml') - if os.path.isfile(videoRegistryFile): - videoxml = etree.parse(videoRegistryFile) - else: - assert False, "Could not find video.xml to generate utilities for video enum types" - out = '' - for enum in videoxml.findall("./enums[@name]"): - enumname = enum.get('name') - out += f'std::string {enumname}String({enumname} value) {{\n' - out += ' switch (value) {\n' - for option in enum.findall("./enum[@name]"): - name = option.get('name') + out = [] + for enum in self.vk.videoStd.enums.values(): + out.append(f'std::string {enum.name}String({enum.name} value) {{\n') + out.append(' switch (value) {\n') + for field in enum.fields: # Ignore aliases - if option.get('value') is not None: - out += f' case {name}: return "{name}";\n' - out += f' default: return std::string("UNKNOWN_{enumname}_value") + std::to_string(value);\n' - out += ' }\n}\n' - out += f'void Dump{enumname}(Printer &p, std::string name, {enumname} value) {{\n' - out += f' p.PrintKeyString(name, {enumname}String(value));\n}}\n' + if field.value is not None: + out.append(f' case {field.name}: return "{field.name}";\n') + out.append(f' default: return std::string("UNKNOWN_{enum.name}_value") + std::to_string(value);\n') + out.append(' }\n}\n') + out.append(f'void Dump{enum.name}(Printer &p, std::string name, {enum.name} value) {{\n') + out.append(f' p.PrintKeyString(name, {enum.name}String(value));\n}}\n') return out - def genVideoProfileUtils(self): - out = '' - - # Parse video codec information from the XML - videoCodecs = OrderedDict() - xmlVideoCodecs = self.registry.reg.find("./videocodecs") - for xmlVideoCodec in xmlVideoCodecs.findall("./videocodec"): - name = xmlVideoCodec.get('name') - extend = xmlVideoCodec.get('extend') - value = xmlVideoCodec.get('value') - if value is None: - # Video codec category - videoCodecs[name] = VulkanVideoCodec(name) - else: - # Specific video codec - videoCodecs[name] = VulkanVideoCodec(name, videoCodecs[extend], value) - videoCodec = videoCodecs[name] - - for xmlVideoProfiles in xmlVideoCodec.findall("./videoprofiles"): - videoProfileStructName = xmlVideoProfiles.get('struct') - videoCodec.profileStructs[videoProfileStructName] = VulkanVideoProfileStruct(videoProfileStructName) - videoProfileStruct = videoCodec.profileStructs[videoProfileStructName] - - for xmlVideoProfileMember in xmlVideoProfiles.findall("./videoprofilemember"): - memberName = xmlVideoProfileMember.get('name') - videoProfileStruct.members[memberName] = VulkanVideoProfileStructMember(memberName) - videoProfileStructMember = videoProfileStruct.members[memberName] - - for xmlVideoProfile in xmlVideoProfileMember.findall("./videoprofile"): - videoProfileStructMember.values[xmlVideoProfile.get('value')] = xmlVideoProfile.get('name') - - for xmlVideoCapabilities in xmlVideoCodec.findall("./videocapabilities"): - capabilityStructName = xmlVideoCapabilities.get('struct') - videoCodec.capabilities[capabilityStructName] = capabilityStructName - - for xmlVideoFormat in xmlVideoCodec.findall("./videoformat"): - videoFormatName = xmlVideoFormat.get('name') - videoFormatExtend = xmlVideoFormat.get('extend') - if videoFormatName is not None: - # This is a new video format category - videoFormatUsage = xmlVideoFormat.get('usage') - videoCodec.formats[videoFormatName] = VulkanVideoFormat(videoFormatName, videoFormatUsage) - videoFormat = videoCodec.formats[videoFormatName] - elif videoFormatExtend is not None: - # This is an extension to an already defined video format category - if videoFormatExtend in videoCodec.formats: - videoFormat = videoCodec.formats[videoFormatExtend] - else: - assert False, f"Video format category '{videoFormatExtend}' not found but it is attempted to be extended" - else: - assert False, "'name' or 'extend' is attribute is required for 'videoformat' element" - - for xmlVideoFormatProperties in xmlVideoFormat.findall("./videoformatproperties"): - propertiesStructName = xmlVideoFormatProperties.get('struct') - videoFormat.properties[propertiesStructName] = propertiesStructName - - for xmlVideoFormatRequiredCap in xmlVideoFormat.findall("./videorequirecapabilities"): - requiredCapStruct = xmlVideoFormatRequiredCap.get('struct') - requiredCapMember = xmlVideoFormatRequiredCap.get('member') - requiredCapValue = xmlVideoFormatRequiredCap.get('value') - videoFormat.requiredCaps.append(VulkanVideoRequiredCapabilities(requiredCapStruct, requiredCapMember, requiredCapValue)) - - # Collect flag types in a set because we will need to look this up - flagTypes = set() - for flagType in self.flags: - flagTypes.add(flagType.name) - - # Utility to get structure definition from structure name - def GetStructDef(name): - for s in self.all_structures: - if s.name == name: - return s - assert False, f"Definition for structure '{name}' is missing" - - # Utility to get the extension / version precondition of a list of type names - def GetTypesPrecondition(typelist, indent): - indent = ' ' * indent - out = '' - extEnables = {} - for typename in typelist: - for k, elem in self.extTypes.items(): - if k == typename or (typename in self.aliases.keys() and k in self.aliases[typename]): - for e in elem: - extEnables[e.extNameStr] = e.type - - version = None - for typename in typelist: - for v in self.vulkan_versions: - if typename in v.names: - if version is not None and (v.major > version.major or (v.major == version.major and v.minor > version.minor)): - version = v - - has_version = version is not None - has_extNameStr = len(extEnables) > 0 or typename in self.aliases.keys() - if has_version or has_extNameStr: - out += f'{indent}if (' - has_printed_condition = False - if has_extNameStr: - for key, value in extEnables.items(): - if has_printed_condition: - out += f'\n{indent} || ' - else: - has_printed_condition = True - if has_version: - out += '(' - if value == EXTENSION_TYPE_DEVICE: - out += f'gpu.CheckPhysicalDeviceExtensionIncluded({key})' - else: - assert False, 'Should never get here' - if has_version: + + # Utility to get the extension / version precondition of a list of type names + def GetTypesPrecondition(self, typelist, indent): + indent = ' ' * indent + out = [] + extEnables = [] + for typename in typelist: + extEnables.extend(self.vk.structs[typename].extensions) + + version = None + for typename in typelist: + for v in self.vk.versions.values(): + if typename in v.name: + if version is not None and (v.major > version.major or (v.major == version.major and v.minor > version.minor)): + version = v + + + has_version = version is not None + has_extNameStr = len(extEnables) > 0 + if has_version or has_extNameStr: + out.append(f'{indent}if (') + has_printed_condition = False + if has_extNameStr: + for ext in extEnables: if has_printed_condition: - out += f'\n{indent} || (gpu.api_version >= {version.constant})' + out.append(f'\n{indent} || ') else: - out += f'gpu.api_version >= {version.constant}' - out += ') {\n' - else: - out = f'{indent}{{\n' - return out - - # Utility to construct a capability prerequisite condition evaluation expression - def GetRequiredCapsCondition(structName, memberName, memberRef, value): - condition = '' - requiredCapStructDef = GetStructDef(structName) - for member in requiredCapStructDef.members: - if member.name == memberName: - if member.typeID in flagTypes: - # Check that the flags contain all the required values - def genExpressionFromValue(value): - return value if value == "" else f"({memberRef} & {value}) != 0" - - for char in condition: - if char in ['(', ')', '+', ',']: - condition += genExpressionFromValue(value) - value = "" - if char == '+': - # '+' means AND - condition += ' && ' - elif char == ',': - # ',' means OR - condition += ' || ' - else: - condition += char - else: - value += char - condition += genExpressionFromValue(value) + has_printed_condition = True + if has_version: + out.append('(') + if self.vk.extensions[ext].device: + out.append(f'gpu.CheckPhysicalDeviceExtensionIncluded({self.vk.extensions[ext].nameString})') else: - condition = f'{memberRef} == {value}' - if condition == '': - return 'true' - else: - return f'({condition})' + assert False, 'Should never get here' + if has_version: + if has_printed_condition: + out.append(f'\n{indent} || (gpu.api_version >= {version.nameApi})') + else: + out.append(f'gpu.api_version >= {version.nameApi}') + out.append(') {\n') + else: + out = f'{indent}{{\n' + return out + + # Utility to construct a capability prerequisite condition evaluation expression + def GetRequiredCapsCondition(self, structName, memberName, memberRef, value): + condition = '' + requiredCapStructDef = self.vk.structs[structName] + for member in requiredCapStructDef.members: + if member.name == memberName: + if member.type in self.vk.flags: + # Check that the flags contain all the required values + def genExpressionFromValue(value): + return value if value == "" else f"({memberRef} & {value}) != 0" + + for char in condition: + if char in ['(', ')', '+', ',']: + condition += genExpressionFromValue(value) + value = "" + if char == '+': + # '+' means AND + condition += ' && ' + elif char == ',': + # ',' means OR + condition += ' || ' + else: + condition += char + else: + value += char + condition += genExpressionFromValue(value) + else: + condition = f'{memberRef} == {value}' + if condition == '': + return 'true' + else: + return f'({condition})' + + def genVideoProfileUtils(self): + out = [] # Generate video format properties comparator - out += ''' + out.append(''' bool is_video_format_same(const VkVideoFormatPropertiesKHR &format_a, const VkVideoFormatPropertiesKHR &format_b) { auto a = reinterpret_cast<const VkBaseInStructure*>(&format_a); auto b = reinterpret_cast<const VkBaseInStructure*>(&format_b); @@ -570,19 +359,19 @@ bool is_video_format_same(const VkVideoFormatPropertiesKHR &format_a, const VkVi // Structure type mismatch (extension structures are expected to be chained in the same order) same = false; } else { - switch (a->sType) {''' + switch (a->sType) {''') if 'VkVideoFormatPropertiesKHR' in self.registry.validextensionstructs: for extstruct in ['VkVideoFormatPropertiesKHR'] + self.registry.validextensionstructs['VkVideoFormatPropertiesKHR']: - extstructDef = GetStructDef(extstruct) - out += f''' - case {extstructDef.sTypeName}: + extstructDef = self.vk.structs[extstruct] + out.append(f''' + case {extstructDef.sType}: same = same && memcmp(reinterpret_cast<const char*>(a) + sizeof(VkBaseInStructure), reinterpret_cast<const char*>(b) + sizeof(VkBaseInStructure), sizeof({extstruct}) - sizeof(VkBaseInStructure)) == 0; - break;''' + break;''') - out += ''' + out.append(''' default: // Unexpected structure type same = false; @@ -594,10 +383,10 @@ bool is_video_format_same(const VkVideoFormatPropertiesKHR &format_a, const VkVi } return same; } -''' +''') # Generate video profile info capture utilities - out += ''' + out.append(''' std::vector<std::unique_ptr<AppVideoProfile>> enumerate_supported_video_profiles(AppGpu &gpu) { std::vector<std::unique_ptr<AppVideoProfile>> result{}; @@ -665,19 +454,19 @@ std::vector<std::unique_ptr<AppVideoProfile>> enumerate_supported_video_profiles result.push_back(std::move(profile)); } }; -''' +''') # Generate individual video profiles from the video codec metadata - for videoCodec in videoCodecs.values(): + for videoCodec in self.vk.videoCodecs.values(): # Ignore video codec categories if videoCodec.value is None: continue - out += '\n' - out += GetTypesPrecondition(videoCodec.profileStructs, 4) - out += f'{" " * 8}const std::string codec_name = "{videoCodec.name}";\n' + out.append('\n') + out.extend(self.GetTypesPrecondition(videoCodec.profiles.keys(), 4)) + out.append(f'{" " * 8}const std::string codec_name = "{videoCodec.name}";\n') - out += ''' + out.append(''' for (auto chroma_subsampling : chroma_subsampling_list) { for (auto luma_bit_depth : bit_depth_list) { for (auto chroma_bit_depth : bit_depth_list) { @@ -687,107 +476,107 @@ std::vector<std::unique_ptr<AppVideoProfile>> enumerate_supported_video_profiles } std::string profile_base_name = codec_name + base_format(chroma_subsampling, luma_bit_depth, chroma_bit_depth); -''' +''') # Setup video profile info - out += f'{" " * 20}VkVideoProfileInfoKHR profile_info{{\n' - out += f'{" " * 20} VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,\n' - out += f'{" " * 20} nullptr,\n' - out += f'{" " * 20} {videoCodec.value},\n' - out += f'{" " * 20} chroma_subsampling.value,\n' - out += f'{" " * 20} luma_bit_depth.value,\n' - out += f'{" " * 20} chroma_bit_depth.value\n' - out += f'{" " * 20}}};\n\n' + out.append(f'{" " * 20}VkVideoProfileInfoKHR profile_info{{\n') + out.append(f'{" " * 20} VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,\n') + out.append(f'{" " * 20} nullptr,\n') + out.append(f'{" " * 20} {videoCodec.value},\n') + out.append(f'{" " * 20} chroma_subsampling.value,\n') + out.append(f'{" " * 20} luma_bit_depth.value,\n') + out.append(f'{" " * 20} chroma_bit_depth.value\n') + out.append(f'{" " * 20}}};\n\n') # Setup video profile info chain creation callback - out += f'{" " * 20}auto create_profile_info_chain = [&](const void **ppnext) -> std::unique_ptr<video_profile_info_chain> {{\n' - out += f'{" " * 20} auto profile_info_chain = std::make_unique<video_profile_info_chain>();\n' - for profileStruct in videoCodec.profileStructs: - structDef = GetStructDef(profileStruct) - out += AddGuardHeader(structDef) - out += f'{" " * 24}if (profile_info_chain != nullptr) {{\n' - out += f'{" " * 28}profile_info_chain->{profileStruct[2:]}.sType = {structDef.sTypeName};\n' - out += f'{" " * 28}profile_info_chain->{profileStruct[2:]}.pNext = nullptr;\n' - out += f'{" " * 28}*ppnext = &profile_info_chain->{profileStruct[2:]};\n' - out += f'{" " * 28}ppnext = &profile_info_chain->{profileStruct[2:]}.pNext;\n' - out += f'{" " * 24}}}\n' - if structDef.guard: - out += f'#else\n{" " * 20}profile_info_chain = nullptr;\n' - out += AddGuardFooter(structDef) - out += f'{" " * 20} return profile_info_chain;\n' - out += f'{" " * 20}}};\n\n' + out.append(f'{" " * 20}auto create_profile_info_chain = [&](const void **ppnext) -> std::unique_ptr<video_profile_info_chain> {{\n') + out.append(f'{" " * 20} auto profile_info_chain = std::make_unique<video_profile_info_chain>();\n') + for profileStruct in videoCodec.profiles: + structDef = self.vk.structs[profileStruct] + out.append(self.AddGuardHeader(structDef)) + out.append(f'{" " * 24}if (profile_info_chain != nullptr) {{\n') + out.append(f'{" " * 28}profile_info_chain->{profileStruct[2:]}.sType = {structDef.sType};\n') + out.append(f'{" " * 28}profile_info_chain->{profileStruct[2:]}.pNext = nullptr;\n') + out.append(f'{" " * 28}*ppnext = &profile_info_chain->{profileStruct[2:]};\n') + out.append(f'{" " * 28}ppnext = &profile_info_chain->{profileStruct[2:]}.pNext;\n') + out.append(f'{" " * 24}}}\n') + if structDef.protect: + out.append(f'#else\n{" " * 20}profile_info_chain = nullptr;\n') + out.append(self.AddGuardFooter(structDef)) + out.append(f'{" " * 20} return profile_info_chain;\n') + out.append(f'{" " * 20}}};\n\n') # Setup video capabilities chain creation callback - out += f'{" " * 20}auto create_capabilities_chain = [&](void **ppnext) -> std::unique_ptr<video_capabilities_chain> {{\n' - out += f'{" " * 20} auto capabilities_chain = std::make_unique<video_capabilities_chain>();\n' + out.append(f'{" " * 20}auto create_capabilities_chain = [&](void **ppnext) -> std::unique_ptr<video_capabilities_chain> {{\n') + out.append(f'{" " * 20} auto capabilities_chain = std::make_unique<video_capabilities_chain>();\n') for capabilities in videoCodec.capabilities: - structDef = GetStructDef(capabilities) - out += AddGuardHeader(structDef) - out += f'{" " * 24}if (capabilities_chain != nullptr) {{\n' - out += GetTypesPrecondition([capabilities], 28) - out += f'{" " * 32}capabilities_chain->{capabilities[2:]}.sType = {structDef.sTypeName};\n' - out += f'{" " * 32}capabilities_chain->{capabilities[2:]}.pNext = nullptr;\n' - out += f'{" " * 32}*ppnext = &capabilities_chain->{capabilities[2:]};\n' - out += f'{" " * 32}ppnext = &capabilities_chain->{capabilities[2:]}.pNext;\n' - out += f'{" " * 28}}}\n' - out += f'{" " * 24}}}\n' - out += AddGuardFooter(structDef) - out += f'{" " * 20} return capabilities_chain;\n' - out += f'{" " * 20}}};\n\n' + structDef = self.vk.structs[capabilities] + out.append(self.AddGuardHeader(structDef)) + out.append(f'{" " * 24}if (capabilities_chain != nullptr) {{\n') + out.extend(self.GetTypesPrecondition([capabilities], 28)) + out.append(f'{" " * 32}capabilities_chain->{capabilities[2:]}.sType = {structDef.sType};\n') + out.append(f'{" " * 32}capabilities_chain->{capabilities[2:]}.pNext = nullptr;\n') + out.append(f'{" " * 32}*ppnext = &capabilities_chain->{capabilities[2:]};\n') + out.append(f'{" " * 32}ppnext = &capabilities_chain->{capabilities[2:]}.pNext;\n') + out.append(f'{" " * 28}}}\n') + out.append(f'{" " * 24}}}\n') + out.append(self.AddGuardFooter(structDef)) + out.append(f'{" " * 20} return capabilities_chain;\n') + out.append(f'{" " * 20}}};\n\n') # Setup video format properties chain creation callbacks - out += f'{" " * 20}const AppVideoProfile::CreateFormatPropertiesChainCbList create_format_properties_chain_list = {{\n' + out.append(f'{" " * 20}const AppVideoProfile::CreateFormatPropertiesChainCbList create_format_properties_chain_list = {{\n') for format in videoCodec.formats.values(): - out += f'{" " * 24}AppVideoProfile::CreateFormatPropertiesChainCb {{\n' - out += f'{" " * 28}"{format.name}",\n' - out += f'{" " * 28}{format.usage.replace("+", " | ")},\n' + out.append(f'{" " * 24}AppVideoProfile::CreateFormatPropertiesChainCb {{\n') + out.append(f'{" " * 28}"{format.name}",\n') + out.append(f'{" " * 28}{format.usage.replace("+", " | ")},\n') # Callback to check required capabilities - out += f'{" " * 28}[&](const VkVideoCapabilitiesKHR &capabilities) -> bool {{\n' - out += f'{" " * 28} bool supported = true;\n' + out.append(f'{" " * 28}[&](const VkVideoCapabilitiesKHR &capabilities) -> bool {{\n') + out.append(f'{" " * 28} bool supported = true;\n') for requiredCap in format.requiredCaps: - structDef = GetStructDef(requiredCap.struct) - out += AddGuardHeader(structDef) - out += GetTypesPrecondition([requiredCap.struct], 32) - out += f'{" " * 32} auto caps = reinterpret_cast<const {requiredCap.struct}*>(find_caps_struct(capabilities, {structDef.sTypeName}));\n' - out += f'{" " * 32} if (caps != nullptr) {{\n' - out += f'{" " * 32} supported = supported && {GetRequiredCapsCondition(requiredCap.struct, requiredCap.member, f"caps->{requiredCap.member}", requiredCap.value)};\n' - out += f'{" " * 32} }} else {{\n' - out += f'{" " * 32} supported = false;\n' - out += f'{" " * 32} }}\n' - out += f'{" " * 32}}} else {{\n' - out += f'{" " * 32} supported = false;\n' - out += f'{" " * 32}}}\n' - if structDef.guard: - out += f'#else\n{" " * 32}supported = false;\n' - out += AddGuardFooter(structDef) - out += f'{" " * 28} return supported;\n' - out += f'{" " * 28}}},\n' + structDef = self.vk.structs[requiredCap.struct] + out.append(self.AddGuardHeader(structDef)) + out.extend(self.GetTypesPrecondition([requiredCap.struct], 32)) + out.append(f'{" " * 32} auto caps = reinterpret_cast<const {requiredCap.struct}*>(find_caps_struct(capabilities, {structDef.sType}));\n') + out.append(f'{" " * 32} if (caps != nullptr) {{\n') + out.append(f'{" " * 32} supported = supported && {self.GetRequiredCapsCondition(requiredCap.struct, requiredCap.member, f"caps->{requiredCap.member}", requiredCap.value)};\n') + out.append(f'{" " * 32} }} else {{\n') + out.append(f'{" " * 32} supported = false;\n') + out.append(f'{" " * 32} }}\n') + out.append(f'{" " * 32}}} else {{\n') + out.append(f'{" " * 32} supported = false;\n') + out.append(f'{" " * 32}}}\n') + if structDef.protect: + out.append(f'#else\n{" " * 32}supported = false;\n') + out.append(self.AddGuardFooter(structDef)) + out.append(f'{" " * 28} return supported;\n') + out.append(f'{" " * 28}}},\n') # Callback to create video format properties chain - out += f'{" " * 28}[&](void **ppnext) -> std::unique_ptr<video_format_properties_chain> {{\n' - out += f'{" " * 28} auto format_properties_chain = std::make_unique<video_format_properties_chain>();\n' + out.append(f'{" " * 28}[&](void **ppnext) -> std::unique_ptr<video_format_properties_chain> {{\n') + out.append(f'{" " * 28} auto format_properties_chain = std::make_unique<video_format_properties_chain>();\n') for formatProps in format.properties: - structDef = GetStructDef(formatProps) - out += AddGuardHeader(structDef) - out += f'{" " * 32}if (format_properties_chain != nullptr) {{\n' - out += GetTypesPrecondition([formatProps], 36) - out += f'{" " * 40}format_properties_chain->{formatProps[2:]}.sType = {structDef.sTypeName};\n' - out += f'{" " * 40}format_properties_chain->{formatProps[2:]}.pNext = nullptr;\n' - out += f'{" " * 40}*ppnext = &format_properties_chain->{formatProps[2:]};\n' - out += f'{" " * 40}ppnext = &format_properties_chain->{formatProps[2:]}.pNext;\n' - out += f'{" " * 36}}}\n' - out += f'{" " * 32}}}\n' - out += AddGuardFooter(structDef) - out += f'{" " * 28} return format_properties_chain;\n' - out += f'{" " * 28}}},\n' - - out += f'{" " * 24}}},\n' - out += f'{" " * 20}}};\n\n' + structDef = self.vk.structs[formatProps] + out.append(self.AddGuardHeader(structDef)) + out.append(f'{" " * 32}if (format_properties_chain != nullptr) {{\n') + out.extend(self.GetTypesPrecondition([formatProps], 36)) + out.append(f'{" " * 40}format_properties_chain->{formatProps[2:]}.sType = {structDef.sType};\n') + out.append(f'{" " * 40}format_properties_chain->{formatProps[2:]}.pNext = nullptr;\n') + out.append(f'{" " * 40}*ppnext = &format_properties_chain->{formatProps[2:]};\n') + out.append(f'{" " * 40}ppnext = &format_properties_chain->{formatProps[2:]}.pNext;\n') + out.append(f'{" " * 36}}}\n') + out.append(f'{" " * 32}}}\n') + out.append(self.AddGuardFooter(structDef)) + out.append(f'{" " * 28} return format_properties_chain;\n') + out.append(f'{" " * 28}}},\n') + + out.append(f'{" " * 24}}},\n') + out.append(f'{" " * 20}}};\n\n') # Permute profiles for each profile struct member value profiles = {'': []} - for profileStruct in videoCodec.profileStructs.values(): + for profileStruct in videoCodec.profiles.values(): for profileStructMember in profileStruct.members.values(): newProfiles = {} for profileStructMemberValue, profileStructMemberName in profileStructMember.values.items(): @@ -795,246 +584,144 @@ std::vector<std::unique_ptr<AppVideoProfile>> enumerate_supported_video_profiles # Only add video profile name suffix to the full descriptive name if not empty to avoid excess whitespace newProfileName = profileName if profileStructMemberName == '' else f'{profileName} {profileStructMemberName}' newProfiles[newProfileName] = profile + [{ - "struct": profileStruct.struct, + "struct": profileStruct.name, "member": profileStructMember.name, "value": profileStructMemberValue }] profiles = newProfiles for profileName, profile in profiles.items(): - out += f'{" " * 20}add_profile(profile_base_name + "{profileName}", profile_info,\n' - out += f'{" " * 20} create_profile_info_chain, create_capabilities_chain,\n' - out += f'{" " * 20} create_format_properties_chain_list,\n' - out += f'{" " * 20} [](AppVideoProfile& profile) {{\n' - for profileStruct in videoCodec.profileStructs: - structDef = GetStructDef(profileStruct) - out += AddGuardHeader(structDef) + out.append(f'{" " * 20}add_profile(profile_base_name + "{profileName}", profile_info,\n') + out.append(f'{" " * 20} create_profile_info_chain, create_capabilities_chain,\n') + out.append(f'{" " * 20} create_format_properties_chain_list,\n') + out.append(f'{" " * 20} [](AppVideoProfile& profile) {{\n') + for profileStruct in videoCodec.profiles: + structDef = self.vk.structs[profileStruct] + out.append(self.AddGuardHeader(structDef)) for elem in profile: if elem['struct'] == profileStruct: - out += f'{" " * 24}profile.profile_info_chain->{elem["struct"][2:]}.{elem["member"]} = {elem["value"]};\n' - out += AddGuardFooter(structDef) - out += f'{" " * 20}}});\n' + out.append(f'{" " * 24}profile.profile_info_chain->{elem["struct"][2:]}.{elem["member"]} = {elem["value"]};\n') + out.append(self.AddGuardFooter(structDef)) + out.append(f'{" " * 20}}});\n') - out += f'{" " * 16}}}\n' - out += f'{" " * 12}}}\n' - out += f'{" " * 8}}}\n' - out += f'{" " * 4}}}\n' + out.append(f'{" " * 16}}}\n') + out.append(f'{" " * 12}}}\n') + out.append(f'{" " * 8}}}\n') + out.append(f'{" " * 4}}}\n') - out += ' return result;\n' - out += '}\n\n' + out.append(' return result;\n') + out.append('}\n\n') return out - def genCmd(self, cmd, name, alias): - gen.OutputGenerator.genCmd(self, cmd, name, alias) - # These are actually constants - def genEnum(self, enuminfo, name, alias): - gen.OutputGenerator.genEnum(self, enuminfo, name, alias) + # finds all the ranges of formats from core (1.0), core versions (1.1+), and extensions + def findFormatRanges(self): + min_val = 2**32 + prev_field = None + max_val = 0 + for f in self.vk.enums['VkFormat'].fields: + if f.value is None: + continue + if prev_field is not None and f.value != prev_field.value + 1: + for ext in prev_field.extensions: + if self.vk.extensions[ext].promotedTo is not None: + self.format_ranges.append(VulkanFormatRange(self.vk.extensions[ext].promotedTo.replace("VK_", "VK_API_"), [], min_val, max_val)) + break + # only bother with the first extension + self.format_ranges.append(VulkanFormatRange(0, prev_field.extensions, min_val, max_val)) + min_val = 2**32 + max_val = 0 + min_val = min(min_val, f.value) + max_val = max(max_val, f.value) - # These are actually enums - def genGroup(self, groupinfo, groupName, alias): - gen.OutputGenerator.genGroup(self, groupinfo, groupName, alias) + prev_field = f - if alias is not None: - if alias in self.aliases.keys(): - self.aliases[alias].append(groupName) - else: - self.aliases[alias] = [groupName, ] - return + for ext in prev_field.extensions: + if self.vk.extensions[ext].promotedTo is not None: + self.format_ranges.append(VulkanFormatRange(self.vk.extensions[ext].promotedTo.replace("VK_", "VK_API_"), [], min_val, max_val)) + break - if groupinfo.elem.get('type') == 'bitmask': - self.bitmasks.append(VulkanBitmask(groupinfo.elem)) - elif groupinfo.elem.get('type') == 'enum': - self.enums.append(VulkanEnum(groupinfo.elem)) + self.format_ranges.append(VulkanFormatRange(0, prev_field.extensions, min_val, max_val)) - def genType(self, typeinfo, name, alias): - gen.OutputGenerator.genType(self, typeinfo, name, alias) + def findAllTypesToGen(self, initial_type_set): + out_set = set() + current_set = initial_type_set + while len(current_set) > 0: + out_set.update(current_set) + next_set = set() - if alias is not None: - if alias in self.aliases.keys(): - self.aliases[alias].append(name) - else: - self.aliases[alias] = [name, ] - return - - if typeinfo.elem.get('category') == 'bitmask': - self.flags.append(VulkanFlags(typeinfo.elem)) - - if typeinfo.elem.get('category') == 'struct': - self.all_structures.append(VulkanStructure( - name, typeinfo.elem, self.constants, self.extTypes)) - - is_vendor_type = False - for vendor in self.vendor_abbreviations: - for node in typeinfo.elem.findall('member'): - if node.get('values') is not None: - if node.get('values').find(vendor) != -1: - is_vendor_type = True - break - if is_vendor_type: - break + for current_item in current_set: + if current_item in self.vk.structs: + for member in self.vk.structs[current_item].members: + if member.type not in out_set and member.name not in NAMES_TO_IGNORE: + next_set.add(member.type) - for key, value in EXTENSION_CATEGORIES.items(): - if str(typeinfo.elem.get('structextends')).find(value.get('extends')) != -1: - if value.get('exclude') is None or name not in value.get('exclude'): - if not is_vendor_type or value.get('ignore_vendor_exclusion'): - self.extension_sets[key].add(name) + current_set = next_set + return out_set - # finds all the ranges of formats from core (1.0), core versions (1.1+), and extensions - def findFormatRanges(self): - for enums in self.registry.reg.findall('enums'): - if enums.get('name') == 'VkFormat': - min_val = 2**32 - max_val = 0 - for enum in enums.findall('enum'): - if enum.get('value') is None: - continue - value = int(enum.get('value')) - min_val = min(min_val, value) - max_val = max(max_val, value) - if min_val < 2**32 and max_val > 0: - self.format_ranges.append(VulkanFormatRange(0, None, min_val, max_val)) - - for feature in self.registry.reg.findall('feature'): - for require in feature.findall('require'): - comment = require.get('comment') - original_ext = None - if comment is not None and comment.find('Promoted from') >= 0: - # may need tweaking in the future - some ext names aren't just the upper case version - original_ext = comment.split(' ')[2].upper() + '_EXTENSION_NAME' - # insert an underscore before numbers in the name define - original_ext = re.sub(r'([A-Z])(\d+)', r'\1_\2', original_ext) - min_val = 2**32 - max_val = 0 - for enum in require.findall('enum'): - if enum.get('extends') == 'VkFormat': - value = CalcEnumValue(int(enum.get('extnumber')), int(enum.get('offset'))) - min_val = min(min_val, value) - max_val = max(max_val, value) - if min_val < 2**32 and max_val > 0: - self.format_ranges.append(VulkanFormatRange(feature.get('name').replace('_VERSION_', '_API_VERSION_'), None, min_val, max_val)) - # If the formats came from an extension, add a format range for that extension so it'll be printed if the ext is supported but not the core version - if original_ext is not None: - self.format_ranges.append(VulkanFormatRange(0, original_ext, min_val, max_val)) - - for extension in self.registry.reg.find('extensions').findall('extension'): - if not self.genOpts.apiname in extension.get('supported').split(','): - continue + def AddGuardHeader(self,obj): + if obj is not None and obj.protect is not None: + return f'#ifdef {obj.protect}\n' + else: + return '' + + + def AddGuardFooter(self,obj): + if obj is not None and obj.protect is not None: + return f'#endif // {obj.protect}\n' + else: + return '' + + def PrintEnumToString(self,enum): + out = [] + out.append(self.AddGuardHeader(enum)) + out.append(f'std::string {enum.name}String({enum.name} value) {{\n') + out.append(' switch (value) {\n') + for v in enum.fields: + out.append(f' case ({v.name}): return "{v.name[3:]}";\n') + out.append(f' default: return std::string("UNKNOWN_{enum.name}_value") + std::to_string(value);\n') + out.append(' }\n}\n') + out.append(self.AddGuardFooter(enum)) + return out - min_val = 2**32 - max_val = 0 - enum_name_string = '' - for require in extension.findall('require'): - for enum in require.findall('enum'): - if enum.get('value') is not None and enum.get('value').find(extension.get('name')): - enum_name_string = enum.get('name') - if enum.get('extends') == 'VkFormat': - if enum.get('offset') is None: - continue - value = CalcEnumValue(int(extension.get('number')), int(enum.get('offset'))) - min_val = min(min_val, value) - max_val = max(max_val, value) - if min_val < 2**32 and max_val > 0: - self.format_ranges.append(VulkanFormatRange(0, enum_name_string, min_val, max_val)) - - - -def GatherTypesToGen(structure_list, structures, exclude = None): - if exclude is None: - exclude = [] - types = set() - for s in structures: - types.add(s) - added_stuff = True # repeat until no new types are added - while added_stuff is True: - added_stuff = False - for s in structure_list: - if s.name in types: - for m in s.members: - if m.typeID not in PREDEFINED_TYPES and m.name not in NAMES_TO_IGNORE: - if m.typeID not in types: - if s.name not in exclude: - types.add(m.typeID) - added_stuff = True - return types - - -def GetExtension(name, generator): - if name in generator.extFuncs: - return generator.extFuncs[name] - elif name in generator.extTypes: - return generator.extTypes[name][0] - else: - return None - - -def AddGuardHeader(obj): - if obj is not None and obj.guard is not None: - return f'#ifdef {obj.guard}\n' - else: - return '' - - -def AddGuardFooter(obj): - if obj is not None and obj.guard is not None: - return f'#endif // {obj.guard}\n' - else: - return '' - -def CalcEnumValue(num, offset): - base = 1000000000 - block_size = 1000 - return base + (num - 1) * block_size + offset - -def PrintEnumToString(enum, generator): - out = '' - out += AddGuardHeader(GetExtension(enum.name, generator)) - out += f'std::string {enum.name}String({enum.name} value) {{\n' - out += ' switch (value) {\n' - for v in enum.options: - out += f' case ({v.name}): return "{v.name[3:]}";\n' - out += f' default: return std::string("UNKNOWN_{enum.name}_value") + std::to_string(value);\n' - out += ' }\n}\n' - out += AddGuardFooter(GetExtension(enum.name, generator)) - return out - - -def PrintEnum(enum, generator): - out = '' - out += AddGuardHeader(GetExtension(enum.name, generator)) - out += f'''void Dump{enum.name}(Printer &p, std::string name, {enum.name} value) {{ + + def PrintEnum(self,enum): + out = [] + out.append(self.AddGuardHeader(enum)) + out.append(f'''void Dump{enum.name}(Printer &p, std::string name, {enum.name} value) {{ if (p.Type() == OutputType::json) p.PrintKeyString(name, std::string("VK_") + {enum.name}String(value)); else p.PrintKeyString(name, {enum.name}String(value)); }} -''' - out += AddGuardFooter(GetExtension(enum.name, generator)) - return out - - -def PrintGetFlagStrings(name, bitmask): - out = '' - out += f'std::vector<const char *> {name}GetStrings({name} value) {{\n' - out += ' std::vector<const char *> strings;\n' - # If a bitmask contains a field whose value is zero, we want to support printing the correct bitflag - # Otherwise, use "None" for when there are not bits set in the bitmask - if bitmask.options[0].value != 0: - out += ' if (value == 0) { strings.push_back("None"); return strings; }\n' - else: - out += f' if (value == 0) {{ strings.push_back("{bitmask.options[0].name[3:]}"); return strings; }}\n' - for v in bitmask.options: - # only check single-bit flags - if v.value != 0 and (v.value & (v.value - 1)) == 0: - out += f' if ({v.name} & value) strings.push_back("{v.name[3:]}");\n' - out += ' return strings;\n}\n' - return out - - -def PrintFlags(bitmask, name): - out = f'void Dump{name}(Printer &p, std::string name, {name} value) {{\n' - out += f''' if (static_cast<{bitmask.name}>(value) == 0) {{ +''') + out.append(self.AddGuardFooter(enum)) + return out + + + def PrintGetFlagStrings(self,name, bitmask): + out = [] + out.append(f'std::vector<const char *> {name}GetStrings({name} value) {{\n') + out.append(' std::vector<const char *> strings;\n') + # If a bitmask contains a field whose value is zero, we want to support printing the correct bitflag + # Otherwise, use "None" for when there are not bits set in the bitmask + if bitmask.flags[0].value != 0: + out.append(' if (value == 0) { strings.push_back("None"); return strings; }\n') + else: + out.append(f' if (value == 0) {{ strings.push_back("{bitmask.flags[0].name[3:]}"); return strings; }}\n') + for v in bitmask.flags: + # only check single-bit flags + if v.value != 0 and (v.value & (v.value - 1)) == 0: + out.append(f' if ({v.name} & value) strings.push_back("{v.name[3:]}");\n') + out.append(' return strings;\n}\n') + return out + + + def PrintFlags(self, bitmask, name): + out = [] + out.append(f'void Dump{name}(Printer &p, std::string name, {name} value) {{\n') + out.append(f''' if (static_cast<{bitmask.name}>(value) == 0) {{ ArrayWrapper arr(p, name, 0); if (p.Type() != OutputType::json && p.Type() != OutputType::vkconfig_output) p.SetAsType().PrintString("None"); @@ -1049,12 +736,12 @@ def PrintFlags(bitmask, name): p.SetAsType().PrintString(str); }} }} -''' - return out +''') + return out -def PrintFlagBits(bitmask): - return f'''void Dump{bitmask.name}(Printer &p, std::string name, {bitmask.name} value) {{ + def PrintFlagBits(self, bitmask): + return [f'''void Dump{bitmask.name}(Printer &p, std::string name, {bitmask.name} value) {{ auto strings = {bitmask.name}GetStrings(value); if (strings.size() > 0) {{ if (p.Type() == OutputType::json) @@ -1063,263 +750,249 @@ def PrintFlagBits(bitmask): p.PrintKeyString(name, strings.at(0)); }} }} -''' +'''] + + + def PrintBitMask(self,bitmask, name): + out = [] + out.extend(self.PrintGetFlagStrings(bitmask.name, bitmask)) + out.append(self.AddGuardHeader(bitmask)) + out.extend(self.PrintFlags(bitmask, name)) + out.extend(self.PrintFlagBits(bitmask)) + out.append(self.AddGuardFooter(bitmask)) + out.append('\n') + return out + + def PrintBitMaskToString(self, bitmask, name): + out = [] + out.append(self.AddGuardHeader(bitmask)) + out.append(f'std::string {name}String({name} value) {{\n') + out.append(' std::string out;\n') + out.append(' bool is_first = true;\n') + for v in bitmask.flags: + out.append(f' if ({v.name} & value) {{\n') + out.append(' if (is_first) { is_first = false; } else { out += " | "; }\n') + out.append(f' out += "{str(v.name)[3:]}";\n') + out.append(' }\n') + out.append(' return out;\n') + out.append('}\n') + out.append(self.AddGuardFooter(bitmask)) + return out -def PrintBitMask(bitmask, name, generator): - out = PrintGetFlagStrings(bitmask.name, bitmask) - out += AddGuardHeader(GetExtension(bitmask.name, generator)) - out += PrintFlags(bitmask, name) - out += PrintFlagBits(bitmask) - out += AddGuardFooter(GetExtension(bitmask.name, generator)) - out += '\n' - return out - - -def PrintBitMaskToString(bitmask, name, generator): - out = AddGuardHeader(GetExtension(bitmask.name, generator)) - out += f'std::string {name}String({name} value) {{\n' - out += ' std::string out;\n' - out += ' bool is_first = true;\n' - for v in bitmask.options: - out += f' if ({v.name} & value) {{\n' - out += ' if (is_first) { is_first = false; } else { out += " | "; }\n' - out += f' out += "{str(v.name)[3:]}";\n' - out += ' }\n' - out += ' return out;\n' - out += '}\n' - out += AddGuardFooter(GetExtension(bitmask.name, generator)) - return out - - -def PrintStructure(struct): - if len(struct.members) == 0: - return '' - out = '' - out += AddGuardHeader(struct) - max_key_len = 0 - for v in struct.members: - if v.arrayLength is not None: - if len(v.name) + len(v.arrayLength) + 2 > max_key_len: - max_key_len = len(v.name) + len(v.arrayLength) + 2 - elif v.typeID in PREDEFINED_TYPES or v.typeID in STRUCT_BLACKLIST: - if len(v.name) > max_key_len: - max_key_len = len(v.name) - - out += f'void Dump{struct.name}(Printer &p, std::string name, const {struct.name} &obj) {{\n' - if struct.name == 'VkPhysicalDeviceLimits': - out += ' if (p.Type() == OutputType::json)\n' - out += ' p.ObjectStart("limits");\n' - out += ' else\n' - out += ' p.SetSubHeader().ObjectStart(name);\n' - elif struct.name == 'VkPhysicalDeviceSparseProperties': - out += ' if (p.Type() == OutputType::json)\n' - out += ' p.ObjectStart("sparseProperties");\n' - out += ' else\n' - out += ' p.SetSubHeader().ObjectStart(name);\n' - else: - out += ' ObjectWrapper object{p, name};\n' - if max_key_len > 0: - out += f' p.SetMinKeyWidth({max_key_len});\n' - for v in struct.members: - # arrays - if v.arrayLength is not None: - # strings - if v.typeID == 'char': - out += f' p.PrintKeyString("{v.name}", obj.{v.name});\n' - # uuid's - elif v.typeID == 'uint8_t' and (v.arrayLength == '8' or v.arrayLength == '16'): # VK_UUID_SIZE - if v.arrayLength == '8': - out += ' if (obj.deviceLUIDValid) { // special case\n' - out += f' p.PrintKeyValue("{v.name}", obj.{v.name});\n' - if v.arrayLength == '8': - out += ' }\n' - elif struct.name == 'VkQueueFamilyGlobalPriorityProperties' and v.name == 'priorities': - out += f' ArrayWrapper arr(p,"{v.name}", obj.priorityCount);\n' - out += ' for (uint32_t i = 0; i < obj.priorityCount; i++) {\n' - out += ' if (p.Type() == OutputType::json)\n' - out += ' p.PrintString(std::string("VK_") + VkQueueGlobalPriorityString(obj.priorities[i]));\n' - out += ' else\n' - out += ' p.PrintString(VkQueueGlobalPriorityString(obj.priorities[i]));\n' - out += ' }\n' - elif v.arrayLength.isdigit(): - out += f' {{\n ArrayWrapper arr(p,"{v.name}", ' + v.arrayLength + ');\n' - out += f' for (uint32_t i = 0; i < {v.arrayLength}; i++) {{ p.PrintElement(obj.{v.name}[i]); }}\n' - out += ' }\n' - else: # dynamic array length based on other member - out += f' if (obj.{v.arrayLength} == 0 || obj.{v.name} == nullptr) {{\n' - out += f' p.PrintKeyString("{v.name}", "NULL");\n' - out += ' } else {\n' - out += f' ArrayWrapper arr(p,"{v.name}", obj.{v.arrayLength});\n' - out += f' for (uint32_t i = 0; i < obj.{v.arrayLength}; i++) {{\n' - out += f' Dump{v.typeID}(p, std::to_string(i), obj.{v.name}[i]);\n' - out += ' }\n' - out += ' }\n' - elif v.typeID == 'VkBool32': - out += f' p.PrintKeyBool("{v.name}", static_cast<bool>(obj.{v.name}));\n' - elif v.typeID == 'uint8_t': - out += f' p.PrintKeyValue("{v.name}", static_cast<uint32_t>(obj.{v.name}));\n' - elif v.typeID == 'VkDeviceSize' or (v.typeID == 'uint32_t' and v.name in ['vendorID', 'deviceID']): - out += f' p.PrintKeyValue("{v.name}", to_hex_str(p, obj.{v.name}));\n' - elif v.typeID in PREDEFINED_TYPES: - out += f' p.PrintKeyValue("{v.name}", obj.{v.name});\n' - elif v.name not in NAMES_TO_IGNORE: - # if it is an enum/flag/bitmask - if v.typeID in ['VkFormatFeatureFlags', 'VkFormatFeatureFlags2']: - out += ' p.SetOpenDetails();\n' # special case so that feature flags are open in html output - out += f' Dump{v.typeID}(p, "{v.name}", obj.{v.name});\n' - - if struct.name in ['VkPhysicalDeviceLimits', 'VkPhysicalDeviceSparseProperties']: - out += ' p.ObjectEnd();\n' - out += '}\n' - - out += AddGuardFooter(struct) - return out - - -def PrintStructShort(struct): - out = '' - out += AddGuardHeader(struct) - out += f'std::ostream &operator<<(std::ostream &o, {struct.name} &obj) {{\n' - out += ' return o << "(" << ' - - first = True - for v in struct.members: - if first: - first = False - out += f'obj.{v.name} << ' + def PrintStructure(self,struct): + if len(struct.members) == 0: + return [] + out = [] + out.append(self.AddGuardHeader(struct)) + max_key_len = 0 + for v in struct.members: + if (v.type in PREDEFINED_TYPES or v.type in STRUCT_BLACKLIST) and (v.length is None or v.type in ['char'] or v.fixedSizeArray[0] in ['VK_UUID_SIZE', 'VK_LUID_SIZE']): + max_key_len = max(max_key_len, len(v.name)) + + out.append(f'void Dump{struct.name}(Printer &p, std::string name, const {struct.name} &obj) {{\n') + if struct.name == 'VkPhysicalDeviceLimits': + out.append(' if (p.Type() == OutputType::json)\n') + out.append(' p.ObjectStart("limits");\n') + out.append(' else\n') + out.append(' p.SetSubHeader().ObjectStart(name);\n') + elif struct.name == 'VkPhysicalDeviceSparseProperties': + out.append(' if (p.Type() == OutputType::json)\n') + out.append(' p.ObjectStart("sparseProperties");\n') + out.append(' else\n') + out.append(' p.SetSubHeader().ObjectStart(name);\n') else: - out += f'\',\' << obj.{v.name} << ' - out += '")";\n' - out += '}\n' - out += AddGuardFooter(struct) - return out - -def PrintChainStruct(listName, structures, all_structures, chain_details, extTypes, aliases, vulkan_versions): - sorted_structures = sorted( - all_structures, key=operator.attrgetter('name')) - - version_desc = '' - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - version_desc = 'gpu.api_version' - else: - version_desc = 'inst.instance_version' - - out = '' - structs_to_print = [] - for s in sorted_structures: - if s.name in structures: - structs_to_print.append(s) - # use default constructor and delete copy & move operators - out += f'''struct {listName}_chain {{ + out.append(' ObjectWrapper object{p, name};\n') + if max_key_len > 0: + out.append(f' p.SetMinKeyWidth({max_key_len});\n') + for v in struct.members: + # arrays + if v.length is not None: + # strings + if v.type == 'char': + out.append(f' p.PrintKeyString("{v.name}", obj.{v.name});\n') + # uuid's + elif v.type == 'uint8_t' and (v.fixedSizeArray[0] == 'VK_LUID_SIZE' or v.fixedSizeArray[0] == 'VK_UUID_SIZE'): # VK_UUID_SIZE + if v.fixedSizeArray[0] == 'VK_LUID_SIZE': + out.append(' if (obj.deviceLUIDValid) { // special case\n') + out.append(f' p.PrintKeyValue("{v.name}", obj.{v.name});\n') + if v.fixedSizeArray[0] == 'VK_LUID_SIZE': + out.append(' }\n') + elif struct.name == 'VkQueueFamilyGlobalPriorityProperties' and v.name == 'priorities': + out.append(f' ArrayWrapper arr(p,"{v.name}", obj.priorityCount);\n') + out.append(' for (uint32_t i = 0; i < obj.priorityCount; i++) {\n') + out.append(' if (p.Type() == OutputType::json)\n') + out.append(' p.PrintString(std::string("VK_") + VkQueueGlobalPriorityString(obj.priorities[i]));\n') + out.append(' else\n') + out.append(' p.PrintString(VkQueueGlobalPriorityString(obj.priorities[i]));\n') + out.append(' }\n') + elif len(v.fixedSizeArray) == 2: + out.append(f' {{\n ArrayWrapper arr(p,"{v.name}", ' + v.fixedSizeArray[0] + ');\n') + out.append(f' for (uint32_t i = 0; i < {v.fixedSizeArray[0]}; i++) {{\n') + out.append(f' for (uint32_t j = 0; j < {v.fixedSizeArray[1]}; j++) {{\n') + out.append(f' p.PrintElement(obj.{v.name}[i][j]); }} }}\n') + out.append(' }\n') + elif len(v.fixedSizeArray) == 1: + out.append(f' {{\n ArrayWrapper arr(p,"{v.name}", ' + v.fixedSizeArray[0] + ');\n') + out.append(f' for (uint32_t i = 0; i < {v.fixedSizeArray[0]}; i++) {{ p.PrintElement(obj.{v.name}[i]); }}\n') + out.append(' }\n') + else: # dynamic array length based on other member + out.append(f' if (obj.{v.length} == 0 || obj.{v.name} == nullptr) {{\n') + out.append(f' p.PrintKeyString("{v.name}", "NULL");\n') + out.append(' } else {\n') + out.append(f' ArrayWrapper arr(p,"{v.name}", obj.{v.length});\n') + out.append(f' for (uint32_t i = 0; i < obj.{v.length}; i++) {{\n') + out.append(f' Dump{v.type}(p, std::to_string(i), obj.{v.name}[i]);\n') + out.append(' }\n') + out.append(' }\n') + elif v.type == 'VkBool32': + out.append(f' p.PrintKeyBool("{v.name}", static_cast<bool>(obj.{v.name}));\n') + elif v.type == 'uint8_t': + out.append(f' p.PrintKeyValue("{v.name}", static_cast<uint32_t>(obj.{v.name}));\n') + elif v.type == 'VkDeviceSize' or (v.type == 'uint32_t' and v.name in ['vendorID', 'deviceID']): + out.append(f' p.PrintKeyValue("{v.name}", to_hex_str(p, obj.{v.name}));\n') + elif v.type in PREDEFINED_TYPES: + out.append(f' p.PrintKeyValue("{v.name}", obj.{v.name});\n') + elif v.name not in NAMES_TO_IGNORE: + # if it is an enum/flag/bitmask + if v.type in ['VkFormatFeatureFlags', 'VkFormatFeatureFlags2']: + out.append(' p.SetOpenDetails();\n') # special case so that feature flags are open in html output + out.append(f' Dump{v.type}(p, "{v.name}", obj.{v.name});\n') + + if struct.name in ['VkPhysicalDeviceLimits', 'VkPhysicalDeviceSparseProperties']: + out.append(' p.ObjectEnd();\n') + out.append('}\n') + + out.append(self.AddGuardFooter(struct)) + return out + + + def PrintStructShort(self,struct): + out = [] + out.append(self.AddGuardHeader(struct)) + out.append(f'std::ostream &operator<<(std::ostream &o, {struct.name} &obj) {{\n') + out.append(' return o << "(" << ') + + first = True + for v in struct.members: + if first: + first = False + out.append(f'obj.{v.name} << ') + else: + out.append(f'\',\' << obj.{v.name} << ') + out.append('")";\n') + out.append('}\n') + out.append(self.AddGuardFooter(struct)) + return out + + def PrintChainStruct(self, listName, structs_to_print, chain_details): + version_desc = '' + if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: + version_desc = 'gpu.api_version' + else: + version_desc = 'inst.instance_version' + + out = [] + + # use default constructor and delete copy & move operators + out.append(f'''struct {listName}_chain {{ {listName}_chain() = default; {listName}_chain(const {listName}_chain &) = delete; {listName}_chain& operator=(const {listName}_chain &) = delete; {listName}_chain({listName}_chain &&) = delete; {listName}_chain& operator=({listName}_chain &&) = delete; -''' +''') + + out.append(' void* start_of_chain = nullptr;\n') + for s in structs_to_print: + if s in STRUCT_BLACKLIST: + continue + struct = self.vk.structs[s] + out.append(self.AddGuardHeader(struct)) + if struct.sType is not None: + out.append(f' {struct.name} {struct.name[2:]}{{}};\n') + # Specific versions of drivers have an incorrect definition of the size of these structs. + # We need to artificially pad the structure it just so the driver doesn't write out of bounds and + # into other structures that are adjacent. This bug comes from the in-development version of + # the extension having a larger size than the final version, so older drivers try to write to + # members which don't exist. + if struct.name in ['VkPhysicalDeviceShaderIntegerDotProductFeatures', 'VkPhysicalDeviceHostImageCopyFeaturesEXT']: + out.append(f' char {struct.name}_padding[64];\n') + for member in struct.members: + if member.length is not None and len(member.fixedSizeArray) == 0: + out.append(f' std::vector<{member.type}> {struct.name}_{member.name};\n') + out.append(self.AddGuardFooter(struct)) + out.append(' void initialize_chain(') + if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: + out.append('AppInstance &inst, ') + if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: + out.append('AppGpu &gpu ') + if chain_details.get('can_show_promoted_structs'): + out.append(', bool show_promoted_structs') + out.append(') noexcept {\n') + for s in structs_to_print: + if s in STRUCT_BLACKLIST: + continue + struct = self.vk.structs[s] - out += ' void* start_of_chain = nullptr;\n' - for s in structs_to_print: - if s.name in STRUCT_BLACKLIST: - continue - out += AddGuardHeader(s) - if s.sTypeName is not None: - out += f' {s.name} {s.name[2:]}{{}};\n' - # Specific versions of drivers have an incorrect definition of the size of these structs. - # We need to artificially pad the structure it just so the driver doesn't write out of bounds and - # into other structures that are adjacent. This bug comes from the in-development version of - # the extension having a larger size than the final version, so older drivers try to write to - # members which don't exist. - if s.name in ['VkPhysicalDeviceShaderIntegerDotProductFeatures', 'VkPhysicalDeviceHostImageCopyFeaturesEXT']: - out += f' char {s.name}_padding[64];\n' - if s.hasLengthmember: - for member in s.members: - if member.lengthMember: - out += f' std::vector<{member.typeID}> {s.name}_{member.name};\n' - out += AddGuardFooter(s) - out += ' void initialize_chain(' - if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: - out += 'AppInstance &inst, ' - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - out += 'AppGpu &gpu ' - if chain_details.get('can_show_promoted_structs'): - out += ', bool show_promoted_structs' - out += ') noexcept {\n' - for s in structs_to_print: - if s.name in STRUCT_BLACKLIST: - continue - out += AddGuardHeader(s) - out += f' {s.name[2:]}.sType = {s.sTypeName};\n' - out += AddGuardFooter(s) - - - out += ' std::vector<VkBaseOutStructure*> chain_members{};\n' - for s in structs_to_print: - if s.name in STRUCT_BLACKLIST: - continue - out += AddGuardHeader(s) - extEnables = {} - for k, elem in extTypes.items(): - if k == s.name or (s.name in aliases.keys() and k in aliases[s.name]): - for e in elem: - extEnables[e.extNameStr] = e.type + out.append(self.AddGuardHeader(struct)) + out.append(f' {struct.name[2:]}.sType = {struct.sType};\n') + out.append(self.AddGuardFooter(struct)) - version = None - oldVersionName = None - for v in vulkan_versions: - if s.name in v.names: - version = v - if s.name in aliases.keys(): - for alias in aliases[s.name]: - oldVersionName = alias - has_version = version is not None - has_extNameStr = len(extEnables) > 0 or s.name in aliases.keys() - if has_version or has_extNameStr: - out += ' if (' - has_printed_condition = False - if has_extNameStr: - for key, value in extEnables.items(): - if has_printed_condition: - out += '\n || ' - else: - has_printed_condition = True - if has_version: - out += '(' - if value == EXTENSION_TYPE_DEVICE: - out += f'gpu.CheckPhysicalDeviceExtensionIncluded({key})' - elif value == EXTENSION_TYPE_INSTANCE: - out += f'inst.CheckExtensionEnabled({key})' + out.append(' std::vector<VkBaseOutStructure*> chain_members{};\n') + for s in structs_to_print: + if s in STRUCT_BLACKLIST: + continue + struct = self.vk.structs[s] + out.append(self.AddGuardHeader(struct)) + + has_version = struct.version is not None + has_extNameStr = len(struct.extensions) > 0 or len(struct.aliases) > 0 + if has_version or has_extNameStr: + out.append(' if (') + has_printed_condition = False + if has_extNameStr: + for ext in struct.extensions: + if has_printed_condition: + out.append('\n || ') + else: + has_printed_condition = True + if has_version: + out.append('(') + if self.vk.extensions[ext].device: + out.append(f'gpu.CheckPhysicalDeviceExtensionIncluded({self.vk.extensions[ext].nameString})') + elif self.vk.extensions[ext].instance: + out.append(f'inst.CheckExtensionEnabled({self.vk.extensions[ext].nameString})') + else: + assert False, 'Should never get here' + if has_version: + str_show_promoted_structs = '|| show_promoted_structs' if chain_details.get('can_show_promoted_structs') else '' + if struct.name in STRUCT_1_1_LIST: + out.append(f'{version_desc} == {struct.version.nameApi} {str_show_promoted_structs}') + elif has_printed_condition: + out.append(f')\n && ({version_desc} < {struct.version.nameApi} {str_show_promoted_structs})') else: - assert False, 'Should never get here' - if has_version: - str_show_promoted_structs = '|| show_promoted_structs' if chain_details.get('can_show_promoted_structs') else '' - if s.name in STRUCT_1_1_LIST: - out += f'{version_desc} == {version.constant} {str_show_promoted_structs}' - elif has_printed_condition: - out += f')\n && ({version_desc} < {version.constant} {str_show_promoted_structs})' - else: - out += f'({version_desc} >= {version.constant})' - out += ')\n ' - else: - out += ' ' - out += f'chain_members.push_back(reinterpret_cast<VkBaseOutStructure*>(&{s.name[2:]}));\n' - out += AddGuardFooter(s) - chain_param_list = [] - chain_arg_list = [] - if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: - chain_param_list.append('AppInstance &inst') - chain_arg_list.append('inst') - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - chain_param_list.append('AppGpu &gpu') - chain_arg_list.append('gpu') - if chain_details.get('can_show_promoted_structs'): - chain_param_list.append('bool show_promoted_structs') - chain_arg_list.append('show_promoted_structs') - - out += f''' + out.append(f'({version_desc} >= {struct.version.nameApi})') + out.append(')\n ') + else: + out.append(' ') + out.append(f'chain_members.push_back(reinterpret_cast<VkBaseOutStructure*>(&{struct.name[2:]}));\n') + out.append(self.AddGuardFooter(struct)) + chain_param_list = [] + chain_arg_list = [] + if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: + chain_param_list.append('AppInstance &inst') + chain_arg_list.append('inst') + if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: + chain_param_list.append('AppGpu &gpu') + chain_arg_list.append('gpu') + if chain_details.get('can_show_promoted_structs'): + chain_param_list.append('bool show_promoted_structs') + chain_arg_list.append('show_promoted_structs') + + out.append(f''' if (!chain_members.empty()) {{ for(size_t i = 0; i < chain_members.size() - 1; i++){{ chain_members[i]->pNext = chain_members[i + 1]; @@ -1328,402 +1001,104 @@ def PrintChainStruct(listName, structures, all_structures, chain_details, extTyp }} }} }}; -void setup_{listName}_chain({chain_details['holder_type']}& start, std::unique_ptr<{listName}_chain>& chain, {','.join(chain_param_list)}){{ +void setup_{listName}_chain({chain_details['extends']}& start, std::unique_ptr<{listName}_chain>& chain, {','.join(chain_param_list)}){{ chain = std::unique_ptr<{listName}_chain>(new {listName}_chain()); chain->initialize_chain({','.join(chain_arg_list)}); start.pNext = chain->start_of_chain; }}; -''' - if chain_details.get('print_iterator'): - out += '\n' - out += f'void chain_iterator_{listName}(Printer &p, ' - if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: - out += 'AppInstance &inst, ' - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - out += 'AppGpu &gpu, ' - if chain_details.get('can_show_promoted_structs'): - out += 'bool show_promoted_structs, ' - out += 'const void * place) {\n' - out += ' while (place) {\n' - out += ' const VkBaseOutStructure *structure = (const VkBaseOutStructure *)place;\n' - out += ' p.SetSubHeader();\n' - - for s in sorted_structures: - if s.sTypeName is None or s.name in STRUCT_BLACKLIST: - continue - - extEnables = {} - for k, elem in extTypes.items(): - if k == s.name or (s.name in aliases.keys() and k in aliases[s.name]): - for e in elem: - extEnables[e.extNameStr] = e.type - - version = None - oldVersionName = None - for v in vulkan_versions: - if s.name in v.names: - version = v - if s.name in aliases.keys(): - for alias in aliases[s.name]: - oldVersionName = alias - - if s.name in structures: - out += AddGuardHeader(s) - out += f' if (structure->sType == {s.sTypeName}' - if s.name in PORTABILITY_STRUCTS: - out += ' && p.Type() != OutputType::json' - has_version = version is not None - has_extNameStr = len(extEnables) > 0 or s.name in aliases.keys() - out += ') {\n' - out += f' const {s.name}* props = (const {s.name}*)structure;\n' - out += f' Dump{s.name}(p, ' - if s.name in aliases.keys() and version is not None: - out += f'{version_desc} >= {version.constant} ?"{s.name}":"{oldVersionName}"' +''') + if chain_details.get('print_iterator'): + out.append('\n') + out.append(f'void chain_iterator_{listName}(Printer &p, ') + if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: + out.append('AppInstance &inst, ') + if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: + out.append('AppGpu &gpu, ') + if chain_details.get('can_show_promoted_structs'): + out.append('bool show_promoted_structs, ') + out.append('const void * place) {\n') + out.append(' while (place) {\n') + out.append(' const VkBaseOutStructure *structure = (const VkBaseOutStructure *)place;\n') + out.append(' p.SetSubHeader();\n') + + for s in structs_to_print: + if s in STRUCT_BLACKLIST: + continue + struct = self.vk.structs[s] + + out.append(self.AddGuardHeader(struct)) + out.append(f' if (structure->sType == {struct.sType}') + if struct.name in PORTABILITY_STRUCTS: + out.append(' && p.Type() != OutputType::json') + has_version = struct.version is not None + has_extNameStr = len(struct.extensions) > 0 or len(struct.aliases) > 0 + out.append(') {\n') + out.append(f' const {struct.name}* props = (const {struct.name}*)structure;\n') + out.append(f' Dump{struct.name}(p, ') + if len(struct.aliases) > 0 and struct.version is not None: + out.append(f'{version_desc} >= {struct.version.nameApi} ?"{struct.name}":"{struct.aliases[0]}"') else: - out += f'"{s.name}"' - out += ', *props);\n' - out += ' p.AddNewline();\n' - out += ' }\n' - out += AddGuardFooter(s) - out += ' place = structure->pNext;\n' - out += ' }\n' - out += '}\n' - - out += '\n' - out += f'bool prepare_{listName}_twocall_chain_vectors(std::unique_ptr<{listName}_chain>& chain) {{\n' - out += ' (void)chain;\n' - is_twocall = False - for s in structs_to_print: - if not s.hasLengthmember: - continue - if s.name in STRUCT_BLACKLIST: - continue - out += AddGuardHeader(s) - for member in s.members: - if member.lengthMember: - out += f' chain->{s.name}_{member.name}.resize(chain->{s.name[2:]}.{member.arrayLength});\n' - out += f' chain->{s.name[2:]}.{member.name} = chain->{s.name}_{member.name}.data();\n' - out += AddGuardFooter(s) - is_twocall = True - out += f' return {"true" if is_twocall else "false"};\n' - out += '}\n' - - return out - - -def PrintStructComparisonForwardDecl(structure): - out = '' - out += f'bool operator==(const {structure.name} & a, const {structure.name} b);\n' - return out - - -def PrintStructComparison(structure): - out = '' - out += f'bool operator==(const {structure.name} & a, const {structure.name} b) {{\n' - out += ' return ' - is_first = True - for m in structure.members: - if m.name not in NAMES_TO_IGNORE: - if not is_first: - out += '\n && ' - else: - is_first = False - out += f'a.{m.name} == b.{m.name}' - out += ';\n' - out += '}\n' - return out - - -class VulkanEnum: - class Option: - - def __init__(self, name, value, bitpos, comment): - self.name = name - self.comment = comment - - if bitpos is not None: - value = 1 << int(bitpos) - elif isinstance(value, str): - if value.lower().startswith('0x'): - value = int(value, 16) - else: - value = int(value) - - self.value = value - - def values(self): - return { - 'optName': self.name, - 'optValue': self.value, - 'optComment': self.comment, - } - - def __init__(self, rootNode): - self.name = rootNode.get('name') - self.type = rootNode.get('type') - self.options = [] - - for child in rootNode: - childName = child.get('name') - childValue = child.get('value') - childBitpos = child.get('bitpos') - childComment = child.get('comment') - childExtends = child.get('extends') - childOffset = child.get('offset') - childExtNum = child.get('extnumber') - support = child.get('supported') - if support == 'disabled': - continue - - if childName is None: + out.append(f'"{struct.name}"') + out.append(', *props);\n') + out.append(' p.AddNewline();\n') + out.append(' }\n') + out.append(self.AddGuardFooter(struct)) + out.append(' place = structure->pNext;\n') + out.append(' }\n') + out.append('}\n') + + out.append('\n') + out.append(f'bool prepare_{listName}_twocall_chain_vectors(std::unique_ptr<{listName}_chain>& chain) {{\n') + out.append(' (void)chain;\n') + is_twocall = False + for s in structs_to_print: + if s in STRUCT_BLACKLIST: continue - if childValue is None and childBitpos is None and childOffset is None: + struct = self.vk.structs[s] + has_length = False + for member in struct.members: + if member.length is not None and len(member.fixedSizeArray) == 0: + has_length = True + if not has_length: continue + out.append(self.AddGuardHeader(struct)) + for member in struct.members: + if member.length is not None and len(member.fixedSizeArray) == 0: + out.append(f' chain->{struct.name}_{member.name}.resize(chain->{struct.name[2:]}.{member.length});\n') + out.append(f' chain->{struct.name[2:]}.{member.name} = chain->{struct.name}_{member.name}.data();\n') + out.append(self.AddGuardFooter(struct)) + is_twocall = True + out.append(f' return {"true" if is_twocall else "false"};\n') + out.append('}\n') - if childExtends is not None and childExtNum is not None and childOffset is not None: - childValue = CalcEnumValue(int(childExtNum), int(childOffset)) - if 'dir' in child.keys(): - childValue = -childValue - duplicate = False - for o in self.options: - if o.values()['optName'] == childName: - duplicate = True - if duplicate: - continue - - self.options.append(VulkanEnum.Option( - childName, childValue, childBitpos, childComment)) - - -class VulkanBitmask: - - def __init__(self, rootNode): - self.name = rootNode.get('name') - self.type = rootNode.get('type') + return out - # Read each value that the enum contains - self.options = [] - for child in rootNode: - childName = child.get('name') - childValue = child.get('value') - childBitpos = child.get('bitpos') - childComment = child.get('comment') - support = child.get('supported') - if childName is None or (childValue is None and childBitpos is None): - continue - if support == 'disabled': - continue - duplicate = False - for option in self.options: - if option.name == childName: - duplicate = True - if duplicate: - continue + def PrintStructComparisonForwardDecl(self,structure): + out = [] + out.append(f'bool operator==(const {structure.name} & a, const {structure.name} b);\n') + return out - self.options.append(VulkanEnum.Option( - childName, childValue, childBitpos, childComment)) - - -class VulkanFlags: - - def __init__(self, rootNode): - self.name = rootNode.get('name') - self.type = rootNode.get('type') - self.enum = rootNode.get('requires') - # 64 bit flags use bitvalues, not requires - if self.enum is None: - self.enum = rootNode.get('bitvalues') - - -class VulkanVariable: - def __init__(self, rootNode, constants): - self.name = rootNode.find('name').text - # Typename, dereferenced and converted to a useable C++ token - self.typeID = rootNode.find('type').text - self.baseType = self.typeID - self.childType = None - self.arrayLength = None - self.text = '' - for node in rootNode.itertext(): - comment = rootNode.find('comment') - if comment is not None and comment.text == node: - continue - self.text += node - - typeMatch = re.search('.+?(?=' + self.name + ')', self.text) - self.type = typeMatch.string[typeMatch.start():typeMatch.end()] - self.type = ' '.join(self.type.split()) - bracketMatch = re.search('(?<=\\[)[a-zA-Z0-9_]+(?=\\])', self.text) - if bracketMatch is not None: - matchText = bracketMatch.string[bracketMatch.start( - ):bracketMatch.end()] - self.childType = self.type - self.type += '[' + matchText + ']' - if matchText in constants: - self.arrayLength = constants[matchText] - else: - self.arrayLength = matchText - - self.lengthMember = False - lengthString = rootNode.get('len') - lengths = [] - if lengthString is not None: - lengths = re.split(',', lengthString) - lengths = list(filter(('null-terminated').__ne__, lengths)) - if self.arrayLength is None and len(lengths) > 0: - self.childType = '*'.join(self.type.split('*')[0:-1]) - self.arrayLength = lengths[0] - self.lengthMember = True - if self.arrayLength is not None and self.arrayLength.startswith('latexmath'): - code = self.arrayLength[10:len(self.arrayLength)] - code = re.sub('\\[', '', code) - code = re.sub('\\]', '', code) - code = re.sub('\\\\(lceil|rceil)', '', code) - code = re.sub('{|}', '', code) - code = re.sub('\\\\mathit', '', code) - code = re.sub('\\\\over', '/', code) - code = re.sub('\\\\textrm', '', code) - self.arrayLength = code - - # Dereference if necessary and handle members of variables - if self.arrayLength is not None: - self.arrayLength = re.sub('::', '->', self.arrayLength) - sections = self.arrayLength.split('->') - if sections[-1][0] == 'p' and sections[0][1].isupper(): - self.arrayLength = '*' + self.arrayLength - - -class VulkanStructure: - def __init__(self, name, rootNode, constants, extTypes): - self.name = name - self.members = [] - self.guard = None - self.sTypeName = None - self.extendsStruct = rootNode.get('structextends') - self.hasLengthmember = False - - for node in rootNode.findall('member'): - if node.get('values') is not None: - self.sTypeName = node.get('values') - self.members.append(VulkanVariable(node, constants)) - - for member in self.members: - if member.lengthMember: - self.hasLengthmember = True - break - for k, elem in extTypes.items(): - if k == self.name: - for e in elem: - if e.guard is not None: - self.guard = e.guard - - -class VulkanExtension: - def __init__(self, rootNode): - self.name = rootNode.get('name') - self.number = int(rootNode.get('number')) - self.type = rootNode.get('type') - self.dependency = rootNode.get('requires') - self.guard = GetFeatureProtect(rootNode) - self.supported = rootNode.get('supported') - self.extNameStr = None - self.vktypes = [] - self.vkfuncs = [] - self.constants = OrderedDict() - self.enumValues = OrderedDict() - self.node = rootNode - - for req in rootNode.findall('require'): - for ty in req.findall('type'): - self.vktypes.append(ty.get('name')) - - for func in req.findall('command'): - self.vkfuncs.append(func.get('name')) - - for enum in req.findall('enum'): - base = enum.get('extends') - name = enum.get('name') - value = enum.get('value') - bitpos = enum.get('bitpos') - offset = enum.get('offset') - # gets the VK_XXX_EXTENSION_NAME string - if value == f'"{self.name}"': - self.extNameStr = name - - if value is None and bitpos is not None: - value = 1 << int(bitpos) - - if offset is not None: - offset = int(offset) - if base is not None and offset is not None: - enumValue = 1000000000 + 1000*(self.number - 1) + offset - if enum.get('dir') == '-': - enumValue = -enumValue - self.enumValues[base] = (name, enumValue) + def PrintStructComparison(self,structure): + out = [] + out.append(f'bool operator==(const {structure.name} & a, const {structure.name} b) {{\n') + out.append(' return ') + is_first = True + for m in structure.members: + if m.name not in NAMES_TO_IGNORE: + if not is_first: + out.append('\n && ') else: - self.constants[name] = value - - -class VulkanVersion: - def __init__(self, rootNode): - self.name = rootNode.get('name') - self.constant = self.name.replace('_VERSION_', '_API_VERSION_') - self.names = set() - - match = re.search(r"^[A-Z]+_VERSION_([1-9][0-9]*)_([0-9]+)$", self.name) - self.major = int(match.group(1)) - self.minor = int(match.group(2)) - - for req in rootNode.findall('require'): - for ty in req.findall('type'): - self.names.add(ty.get('name')) - for func in req.findall('command'): - self.names.add(func.get('name')) - for enum in req.findall('enum'): - self.names.add(enum.get('name')) - self.names = sorted(self.names) + is_first = False + out.append(f'a.{m.name} == b.{m.name}') + out.append(';\n') + out.append('}\n') + return out class VulkanFormatRange: - def __init__(self, min_inst_version, ext_name, first, last): + def __init__(self, min_inst_version, extensions, first, last): self.minimum_instance_version = min_inst_version - self.extension_name = ext_name + self.extensions = extensions self.first_format = first self.last_format = last - -class VulkanVideoRequiredCapabilities(): - def __init__(self, struct, member, value): - self.struct = struct - self.member = member - self.value = value - -class VulkanVideoFormat(): - def __init__(self, name, usage): - self.name = name - self.usage = usage - self.properties = OrderedDict() - self.requiredCaps = list() - super().__init__() - -class VulkanVideoProfileStructMember(): - def __init__(self, name): - self.name = name - self.values = OrderedDict() - -class VulkanVideoProfileStruct(): - def __init__(self, struct): - self.struct = struct - self.members = OrderedDict() - -class VulkanVideoCodec(): - def __init__(self, name, extend = None, value = None): - self.name = name - self.value = value - self.profileStructs = OrderedDict() - self.capabilities = OrderedDict() - self.formats = OrderedDict() - if extend is not None: - self.profileStructs = copy.deepcopy(extend.profileStructs) - self.capabilities = copy.deepcopy(extend.capabilities) - self.formats = copy.deepcopy(extend.formats) |
