blob: aabfac9b6cedc85621220f4914229590d2654b2a [file] [log] [blame]
#!/usr/bin/python3
#
# Copyright (c) 2019 Valve Corporation
# Copyright (c) 2019 LunarG, Inc.
# Copyright (c) 2019 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: Charles Giessen <charles@lunarg.com>
import os
import re
import sys
import string
import xml.etree.ElementTree as etree
import generator as gen
import operator
from collections import namedtuple
from collections import OrderedDict
from generator import *
from common_codegen import *
license_header = '''
/*
* Copyright (c) 2019 The Khronos Group Inc.
* Copyright (c) 2019 Valve Corporation
* Copyright (c) 2019 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Charles Giessen <charles@lunarg.com>
*
*/
/*
* This file is generated from the Khronos Vulkan XML API Registry.
*/
'''
custom_formaters = '''
std::ostream &operator<<(std::ostream &o, VkConformanceVersionKHR &c) {
return o << std::to_string(c.major) << "." << std::to_string(c.minor) << "." << std::to_string(c.subminor) << "."
<< std::to_string(c.patch);
}
std::string VkExtent3DString(VkExtent3D e) {
return std::string("(") + std::to_string(e.width) + ", " + std::to_string(e.height) + ", " + std::to_string(e.depth) + ")";
}
template <typename T>
std::string to_hex_str(T i) {
std::stringstream stream;
stream << "0x" << std::setfill('0') << std::setw(sizeof(T)) << std::hex << i;
return stream.str();
}
template <typename T>
std::string to_hex_str(Printer &p, T i) {
if (p.Type() == OutputType::json)
return std::to_string(i);
else
return to_hex_str(i);
}
'''
# used in the .cpp code
structures_to_gen = ['VkExtent3D', 'VkExtent2D', 'VkPhysicalDeviceLimits', 'VkPhysicalDeviceFeatures',
'VkPhysicalDeviceSparseProperties', 'VkSurfaceCapabilitiesKHR', 'VkSurfaceFormatKHR', 'VkLayerProperties']
enums_to_gen = ['VkResult', 'VkFormat', 'VkPresentModeKHR',
'VkPhysicalDeviceType', 'VkImageTiling']
flags_to_gen = ['VkSurfaceTransformFlagsKHR', 'VkCompositeAlphaFlagsKHR',
'VkDeviceGroupPresentModeFlagsKHR', 'VkFormatFeatureFlags', 'VkMemoryPropertyFlags', 'VkMemoryHeapFlags']
flags_strings_to_gen = ['VkQueueFlags']
struct_comparisons_to_gen = ['VkSurfaceFormatKHR', 'VkSurfaceFormat2KHR', 'VkSurfaceCapabilitiesKHR',
'VkSurfaceCapabilities2KHR', 'VkSurfaceCapabilities2EXT']
# iostream or custom outputter handles these types
predefined_types = ['char', 'VkBool32', 'uint32_t', 'uint8_t', 'int32_t',
'float', 'uint64_t', 'size_t', 'VkDeviceSize', 'VkConformanceVersionKHR']
# need list of venders to blacklist vendor extensions
vendor_abbreviations = ['_IMG', '_AMD', '_AMDX', '_ARM', '_FSL', '_BRCM', '_NXP', '_NV', '_NVX', '_VIV', '_VSI', '_KDAB',
'_ANDROID', '_CHROMIUM', '_FUCHSIA', '_GGP', '_GOOGLE', '_QCOM', '_LUNARG', '_SAMSUNG', '_SEC', '_TIZEN',
'_RENDERDOC', '_NN', '_MVK', '_KHX', '_MESA', '_INTEL']
# Types that need pNext Chains built. 'extends' is the xml tag used in the structextends member. 'type' can be device, instance, or both
EXTENSION_CATEGORIES = {'phys_device_props2': {'extends': 'VkPhysicalDeviceProperties2', 'type': 'device'},
'phys_device_mem_props2': {'extends': 'VkPhysicalDeviceMemoryProperties2', 'type': 'device'},
'phys_device_features2': {'extends': 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo', 'type': 'device'},
'surface_capabilities2': {'extends': 'VkSurfaceCapabilities2KHR', 'type': 'both'},
'format_properties2': {'extends': 'VkFormatProperties2', 'type': 'device'}
}
class VulkanInfoGeneratorOptions(GeneratorOptions):
def __init__(self,
conventions=None,
input=None,
filename=None,
directory='.',
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,
):
GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
versions, emitversions, defaultExtensions,
addExtensions, removeExtensions, emitExtensions, 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
# 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.extension_sets = OrderedDict()
for ext_cat in EXTENSION_CATEGORIES.keys():
self.extension_sets[ext_cat] = set()
self.enums = set()
self.flags = set()
self.bitmasks = set()
self.structures = set()
self.structs_to_comp = set()
self.all_structures = set()
self.types_to_gen = set()
self.extFuncs = OrderedDict()
self.extTypes = OrderedDict()
def beginFile(self, genOpts):
gen.OutputGenerator.beginFile(self, genOpts)
root = self.registry.reg
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 root.find('extensions').findall('extension'):
ext = VulkanExtension(node)
for item in ext.vktypes:
self.extTypes[item] = ext
for item in ext.vkfuncs:
self.extFuncs[item] = ext
def endFile(self):
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 = types_to_gen.union(GatherTypesToGen(self.structures))
for key, value in EXTENSION_CATEGORIES.items():
types_to_gen = types_to_gen.union(
GatherTypesToGen(self.extension_sets[key]))
structs_to_comp = set()
for s in struct_comparisons_to_gen:
structs_to_comp.add(s)
structs_to_comp = structs_to_comp.union(
GatherTypesToGen(self.structs_to_comp))
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.structures = sorted(
self.structures, key=operator.attrgetter('name'))
self.all_structures = sorted(
self.all_structures, key=operator.attrgetter('name'))
for key, value in self.extension_sets.items():
self.extension_sets[key] = sorted(
value, key=operator.attrgetter('name'))
out = ''
out += license_header + "\n"
out += "#include \"vulkaninfo.h\"\n"
out += "#include \"outputprinter.h\"\n"
out += custom_formaters
for e in self.enums:
if e.name in types_to_gen:
out += PrintEnumToString(e, self)
out += PrintEnum(e, self)
for f in self.flags:
if f.name in types_to_gen:
for b in self.bitmasks:
if b.name == f.enum:
out += PrintFlags(f, b, self)
out += PrintBitMask(b, f.name, self)
if f.name in flags_strings_to_gen:
for b in self.bitmasks:
if b.name == f.enum:
out += PrintBitMaskToString(b, f.name, self)
# find all structures needed to dump the requested structures
structure_names = set()
for s in self.all_structures:
if s.name in types_to_gen:
structure_names.add(s.name)
for s in self.all_structures:
if s.name in types_to_gen:
out += PrintForwardDeclaration(s, self)
for s in self.all_structures:
if s.name in types_to_gen:
out += PrintStructure(s, structure_names, self)
out += "pNextChainInfos get_chain_infos() {\n"
out += " pNextChainInfos infos;\n"
for key, value in EXTENSION_CATEGORIES.items():
out += PrintChainBuilders(key, self.extension_sets[key])
out += " return infos;\n}\n"
for key, value in EXTENSION_CATEGORIES.items():
out += PrintChainIterator(key,
self.extension_sets[key], value.get('type'))
for s in self.all_structures:
if s.name in structs_to_comp:
out += PrintStructComparisonForwardDef(s)
for s in self.all_structures:
if s.name in structs_to_comp:
out += PrintStructComparison(s)
gen.write(out, file=self.outFile)
gen.OutputGenerator.endFile(self)
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)
# These are actually enums
def genGroup(self, groupinfo, groupName, alias):
gen.OutputGenerator.genGroup(self, groupinfo, groupName, alias)
if alias is not None:
return
if groupinfo.elem.get('type') == 'bitmask':
self.bitmasks.add(VulkanBitmask(groupinfo.elem))
elif groupinfo.elem.get('type') == 'enum':
self.enums.add(VulkanEnum(groupinfo.elem))
def genType(self, typeinfo, name, alias):
gen.OutputGenerator.genType(self, typeinfo, name, alias)
if alias is not None:
return
if typeinfo.elem.get('category') == 'bitmask':
self.flags.add(VulkanFlags(typeinfo.elem))
if typeinfo.elem.get('category') == 'struct' and name in structures_to_gen:
self.structures.add(VulkanStructure(
name, typeinfo.elem, self.constants, self.extTypes))
if typeinfo.elem.get('category') == 'struct' and name in struct_comparisons_to_gen:
self.structs_to_comp.add(VulkanStructure(
name, typeinfo.elem, self.constants, self.extTypes))
if typeinfo.elem.get('category') == 'struct':
self.all_structures.add(VulkanStructure(
name, typeinfo.elem, self.constants, self.extTypes))
for vendor in vendor_abbreviations:
for node in typeinfo.elem.findall('member'):
if(node.get('values') is not None):
if(node.get('values').find(vendor)) != -1:
return
for key, value in EXTENSION_CATEGORIES.items():
if typeinfo.elem.get('structextends') == value.get('extends'):
self.extension_sets[key].add(VulkanStructure(
name, typeinfo.elem, self.constants, self.extTypes))
def GatherTypesToGen(structures):
types = set()
added_stuff = True # repeat until no new types are added
while added_stuff == True:
added_stuff = False
for s in structures:
size = len(types)
types.add(s.name)
if len(types) != size:
added_stuff = True
for m in s.members:
if m.typeID not in predefined_types and m.name not in ['sType', 'pNext']:
types.add(m.typeID)
return types
def GetExtension(name, generator):
if name in generator.extFuncs:
return generator.extFuncs[name]
elif name in generator.extTypes:
return generator.extTypes[name]
else:
return None
def AddGuardHeader(obj):
if obj is not None and obj.guard is not None:
return "#ifdef {}\n".format(obj.guard)
else:
return ""
def AddGuardFooter(obj):
if obj is not None and obj.guard is not None:
return "#endif // {}\n".format(obj.guard)
else:
return ""
def PrintEnumToString(e, gen):
out = ''
out += AddGuardHeader(GetExtension(e.name, gen))
out += "static const char *" + e.name + "String(" + e.name + " value) {\n"
out += " switch (value) {\n"
for v in e.options:
out += " case (" + str(v.value) + \
"): return \"" + v.name[3:] + "\";\n"
out += " default: return \"UNKNOWN_" + e.name + "\";\n"
out += " }\n}\n"
out += AddGuardFooter(GetExtension(e.name, gen))
return out
def PrintEnum(e, gen):
out = ''
out += AddGuardHeader(GetExtension(e.name, gen))
out += "void Dump" + e.name + \
"(Printer &p, std::string name, " + \
e.name + " value, int width = 0) {\n"
out += " if (p.Type() == OutputType::json) {\n"
out += " p.PrintKeyValue(name, value, width);\n"
out += " return;\n"
out += " } else {\n"
out += " p.PrintKeyValue(name, " + \
e.name + "String(value), width);\n }\n"
out += "}\n"
out += AddGuardFooter(GetExtension(e.name, gen))
return out
def PrintFlags(f, b, gen):
out = ''
out += AddGuardHeader(GetExtension(f.name, gen))
out += "void Dump" + f.name + \
"(Printer &p, std::string name, " + \
f.enum + " value, int width = 0) {\n"
out += " if (value == 0) p.PrintElement(\"None\");\n"
for v in b.options:
out += " if (" + str(v.value) + \
" & value) p.SetAsType().PrintElement(\"" + \
str(v.name[3:]) + "\");\n"
out += "}\n"
out += AddGuardFooter(GetExtension(f.name, gen))
return out
def PrintBitMask(b, name, gen):
out = ''
out += AddGuardHeader(GetExtension(b.name, gen))
out += "void Dump" + name + \
"(Printer &p, std::string name, " + name + " value, int width = 0) {\n"
out += " if (p.Type() == OutputType::json) { p.PrintKeyValue(name, value); return; }\n"
out += " p.ObjectStart(name);\n"
out += " Dump" + name + \
"(p, name, static_cast<" + b.name + ">(value), width);\n"
out += " p.ObjectEnd();\n"
out += "}\n"
out += "void Dump" + b.name + \
"(Printer &p, std::string name, " + \
b.name + " value, int width = 0) {\n"
out += " if (p.Type() == OutputType::json) { p.PrintKeyValue(name, value); return; }\n"
out += " p.ObjectStart(name);\n"
out += " Dump" + name + "(p, name, value, width);\n"
out += " p.ObjectEnd();\n"
out += "}\n"
out += AddGuardFooter(GetExtension(b.name, gen))
return out
def PrintBitMaskToString(b, name, gen):
out = ''
out += AddGuardHeader(GetExtension(b.name, gen))
out += "std::string " + name + \
"String(" + name + " value, int width = 0) {\n"
out += " std::string out;\n"
out += " bool is_first = true;\n"
for v in b.options:
out += " if (" + str(v.value) + " & value) {\n"
out += " if (is_first) { is_first = false; } else { out += \" | \"; }\n"
out += " out += \"" + \
str(v.name).strip("VK_").strip("_BIT") + "\";\n"
out += " }\n"
out += " return out;\n"
out += "}\n"
out += AddGuardFooter(GetExtension(b.name, gen))
return out
def PrintForwardDeclaration(struct, gen):
out = ''
out += AddGuardHeader(struct)
out += "void Dump" + struct.name + \
"(Printer &p, std::string name, " + struct.name + " &obj);\n"
out += AddGuardFooter(struct)
return out
def PrintStructure(struct, structure_names, gen):
out = ''
out += AddGuardHeader(struct)
max_key_len = len(struct.members[0].name)
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:
if len(v.name) > max_key_len:
max_key_len = len(v.name)
out += "void Dump" + struct.name + \
"(Printer &p, std::string name, " + 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 += " p.ObjectStart(name);\n"
for v in struct.members:
# arrays
if v.arrayLength is not None:
# strings
if v.typeID == "char":
out += " p.PrintKeyString(\"" + v.name + "\", obj." + \
v.name + ", " + str(max_key_len) + ");\n"
# uuid's
elif (v.arrayLength == str(16) and v.typeID == "uint8_t"): # VK_UUID_SIZE
out += " p.PrintKeyString(\"" + v.name + "\", to_string_16(obj." + \
v.name + "), " + str(max_key_len) + ");\n"
elif (v.arrayLength == str(8) and v.typeID == "uint8_t"): # VK_LUID_SIZE
out += " if (obj.deviceLUIDValid)" # special case
out += " p.PrintKeyString(\"" + v.name + "\", to_string_8(obj." + \
v.name + "), " + str(max_key_len) + ");\n"
elif v.arrayLength.isdigit():
out += " p.ArrayStart(\"" + v.name + \
"\", "+v.arrayLength+");\n"
for i in range(0, int(v.arrayLength)):
out += " p.PrintElement(obj." + \
v.name + "[" + str(i) + "]);\n"
out += " p.ArrayEnd();\n"
else: # dynamic array length based on other member
out += " p.ArrayStart(\"" + v.name + \
"\", obj."+v.arrayLength+");\n"
out += " for (uint32_t i = 0; i < obj." + \
v.arrayLength+"; i++) {\n"
if v.typeID in structure_names:
out += " if (obj." + v.name + " != nullptr) {\n"
out += " p.SetElementIndex(i);\n"
out += " Dump" + v.typeID + \
"(p, \"" + v.name + "\", obj." + v.name + "[i]);\n"
out += " }\n"
else:
out += " p.PrintElement(obj." + v.name + "[i]);\n"
out += " }\n p.ArrayEnd();\n"
elif v.typeID == "VkBool32":
out += " p.PrintKeyBool(\"" + v.name + "\", static_cast<bool>(obj." + \
v.name + "), " + str(max_key_len) + ");\n"
elif v.typeID == "VkDeviceSize":
out += " p.PrintKeyValue(\"" + v.name + "\", to_hex_str(p, obj." + \
v.name + "), " + str(max_key_len) + ");\n"
elif v.typeID in predefined_types:
out += " p.PrintKeyValue(\"" + v.name + "\", obj." + \
v.name + ", " + str(max_key_len) + ");\n"
elif v.name not in ['sType', 'pNext']:
if v.typeID in structure_names:
out += " Dump" + v.typeID + \
"(p, \"" + v.name + "\", obj." + v.name + ");\n"
else:
out += " Dump" + v.typeID + \
"(p, \"" + v.name + "\", obj." + \
v.name + ", " + str(max_key_len) + ");\n"
out += " p.ObjectEnd();\n"
out += "}\n"
out += AddGuardFooter(struct)
return out
def PrintChainBuilders(listName, structures):
out = ''
out += " infos." + listName + " = {\n"
for s in structures:
out += AddGuardHeader(s)
if s.sTypeName is not None:
out += " {" + s.sTypeName + ", sizeof(" + s.name + ")},\n"
out += AddGuardFooter(s)
out += " };\n"
return out
def PrintChainIterator(listName, structures, checkExtLoc):
sorted_structures = sorted(structures, key=operator.attrgetter("name"))
out = ''
out += "void chain_iterator_" + listName + "(Printer &p, "
if checkExtLoc == "device":
out += "AppGpu &gpu"
elif checkExtLoc == "instance":
out += "AppInstance &inst"
elif checkExtLoc == "both":
out += "AppInstance &inst, AppGpu &gpu"
out += ", void * place) {\n"
out += " while (place) {\n"
out += " struct VkStructureHeader *structure = (struct VkStructureHeader *)place;\n"
out += " p.SetSubHeader();\n"
for s in sorted_structures:
out += AddGuardHeader(s)
if s.sTypeName is not None:
if s.extNameStr is not None:
out += " if (structure->sType == " + \
s.sTypeName + " &&\n"
if s.extType == "device":
out += " gpu.CheckPhysicalDeviceExtensionIncluded(" + \
s.extNameStr + ")) {\n"
elif s.extType == "instance":
out += " inst.CheckExtensionEnabled(" + \
s.extNameStr + ")) {\n"
else:
out += " if (structure->sType == " + \
s.sTypeName + ") {\n"
out += " " + s.name + "* props = " + \
"("+s.name+"*)structure;\n"
out += " Dump" + s.name + \
"(p, \"" + s.name + "\", *props);\n"
out += " p.AddNewline();\n"
out += " }\n"
out += AddGuardFooter(s)
out += " place = structure->pNext;\n"
out += " }\n"
out += "}\n"
return out
def PrintStructComparisonForwardDef(structure):
out = ''
out += "bool operator==(const " + structure.name + \
" & a, const " + structure.name + " b);\n"
return out
def PrintStructComparison(structure):
out = ''
out += "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 ['sType', 'pNext']:
if not is_first:
out += "\n && "
else:
is_first = False
out += "a." + m.name + " == b." + m.name
out += ";\n"
out += "}\n"
return out
def isPow2(num):
return num != 0 and ((num & (num - 1)) == 0)
def StrToInt(s):
try:
return int(s)
except ValueError:
return int(s, 16)
class VulkanEnum:
class Option:
def __init__(self, name, value, bitpos, comment):
self.name = name
self.comment = comment
self.multiValue = None
if value is not None:
self.multiValue = not isPow2(StrToInt(value))
if value == 0 or value is None:
value = 1 << int(bitpos)
self.value = value
def values(self):
return {
'optName': self.name,
'optValue': self.value,
'optComment': self.comment,
'optMultiValue': self.multiValue,
}
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:
continue
if (childValue is None and childBitpos is None and childOffset is None):
continue
if childExtends is not None and childExtNum is not None and childOffset is not None:
enumNegative = False
extNum = int(childExtNum)
extOffset = int(childOffset)
extBase = 1000000000
extBlockSize = 1000
childValue = extBase + (extNum - 1) * extBlockSize + extOffset
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')
# 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
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')
class VulkanVariable:
def __init__(self, rootNode, constants, parentName):
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))
assert(len(lengths) <= 1)
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.extNameStr = None
self.extType = None
for node in rootNode.findall('member'):
if(node.get('values') is not None):
self.sTypeName = node.get('values')
self.members.append(VulkanVariable(
node, constants, self.name))
for k, e in extTypes.items():
if k == self.name:
if e.guard is not None:
self.guard = e.guard
if e.extNameStr is not None:
self.extNameStr = e.extNameStr
if e.type is not None:
self.extType = e.type
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 = {}
self.enumValues = {}
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 == "\"" + 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)
else:
self.constants[name] = value