3 # Copyright (c) 2019 Valve Corporation
4 # Copyright (c) 2019 LunarG, Inc.
5 # Copyright (c) 2019 Google Inc.
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
19 # Author: Charles Giessen <charles@lunarg.com>
25 import xml.etree.ElementTree as etree
26 import generator as gen
29 from collections import namedtuple
30 from collections import OrderedDict
31 from generator import *
32 from common_codegen import *
36 * Copyright (c) 2019 The Khronos Group Inc.
37 * Copyright (c) 2019 Valve Corporation
38 * Copyright (c) 2019 LunarG, Inc.
40 * Licensed under the Apache License, Version 2.0 (the "License");
41 * you may not use this file except in compliance with the License.
42 * You may obtain a copy of the License at
44 * http://www.apache.org/licenses/LICENSE-2.0
46 * Unless required by applicable law or agreed to in writing, software
47 * distributed under the License is distributed on an "AS IS" BASIS,
48 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
49 * See the License for the specific language governing permissions and
50 * limitations under the License.
52 * Author: Charles Giessen <charles@lunarg.com>
57 * This file is generated from the Khronos Vulkan XML API Registry.
61 custom_formaters = r'''
62 void DumpVkConformanceVersion(Printer &p, std::string name, VkConformanceVersion &c, int width = 0) {
63 p.PrintKeyString("conformanceVersion", std::to_string(c.major)+ "." + std::to_string(c.minor) + "." + std::to_string(c.subminor) + "."
64 + std::to_string(c.patch), width);
68 std::string to_hex_str(T i) {
69 std::stringstream stream;
70 stream << "0x" << std::setfill('0') << std::setw(sizeof(T)) << std::hex << i;
75 std::string to_hex_str(Printer &p, T i) {
76 if (p.Type() == OutputType::json)
77 return std::to_string(i);
78 else if (p.Type() == OutputType::vkconfig_output)
79 return std::string("\"") + to_hex_str(i) + std::string("\"");
86 # used in the .cpp code
87 structures_to_gen = ['VkExtent3D', 'VkExtent2D', 'VkPhysicalDeviceLimits', 'VkPhysicalDeviceFeatures', 'VkPhysicalDeviceSparseProperties',
88 'VkSurfaceCapabilitiesKHR', 'VkSurfaceFormatKHR', 'VkLayerProperties', 'VkPhysicalDeviceToolPropertiesEXT']
89 enums_to_gen = ['VkResult', 'VkFormat', 'VkPresentModeKHR',
90 'VkPhysicalDeviceType', 'VkImageTiling']
91 flags_to_gen = ['VkSurfaceTransformFlagsKHR', 'VkCompositeAlphaFlagsKHR', 'VkSurfaceCounterFlagsEXT',
92 'VkDeviceGroupPresentModeFlagsKHR', 'VkFormatFeatureFlags', 'VkMemoryPropertyFlags', 'VkMemoryHeapFlags']
93 flags_strings_to_gen = ['VkQueueFlags']
95 struct_short_versions_to_gen = ['VkExtent3D']
97 struct_comparisons_to_gen = ['VkSurfaceFormatKHR', 'VkSurfaceFormat2KHR', 'VkSurfaceCapabilitiesKHR',
98 'VkSurfaceCapabilities2KHR', 'VkSurfaceCapabilities2EXT']
99 # don't generate these structures
100 struct_blacklist = ['VkConformanceVersion']
102 # iostream or custom outputter handles these types
103 predefined_types = ['char', 'VkBool32', 'uint32_t', 'uint8_t', 'int32_t',
104 'float', 'uint64_t', 'size_t', 'VkDeviceSize']
106 # Types that need pNext Chains built. 'extends' is the xml tag used in the structextends member. 'type' can be device, instance, or both
107 EXTENSION_CATEGORIES = {'phys_device_props2': {'extends': 'VkPhysicalDeviceProperties2', 'type': 'both'},
108 'phys_device_mem_props2': {'extends': 'VkPhysicalDeviceMemoryProperties2', 'type': 'device'},
109 'phys_device_features2': {'extends': 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo', 'type': 'device'},
110 'surface_capabilities2': {'extends': 'VkSurfaceCapabilities2KHR', 'type': 'both'},
111 'format_properties2': {'extends': 'VkFormatProperties2', 'type': 'device'}
115 class VulkanInfoGeneratorOptions(GeneratorOptions):
125 defaultExtensions=None,
127 removeExtensions=None,
131 genFuncPointers=True,
135 protectProtoStr=None,
139 indentFuncProto=True,
140 indentFuncPointer=False,
142 expandEnumerants=True,
144 GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
145 versions, emitversions, defaultExtensions,
146 addExtensions, removeExtensions, emitExtensions, sortProcedure)
148 self.prefixText = prefixText
149 self.genFuncPointers = genFuncPointers
150 self.protectFile = protectFile
151 self.protectFeature = protectFeature
152 self.protectProto = protectProto
153 self.protectProtoStr = protectProtoStr
154 self.apicall = apicall
155 self.apientry = apientry
156 self.apientryp = apientryp
157 self.indentFuncProto = indentFuncProto
158 self.indentFuncPointer = indentFuncPointer
159 self.alignFuncParam = alignFuncParam
161 # VulkanInfoGenerator - subclass of OutputGenerator.
162 # Generates a vulkan info output helper function
165 class VulkanInfoGenerator(OutputGenerator):
170 diagFile=sys.stdout):
171 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
173 self.constants = OrderedDict()
175 self.types_to_gen = set()
177 self.extension_sets = OrderedDict()
178 for ext_cat in EXTENSION_CATEGORIES.keys():
179 self.extension_sets[ext_cat] = set()
184 self.all_structures = []
185 self.aliases = OrderedDict()
187 self.extFuncs = OrderedDict()
188 self.extTypes = OrderedDict()
190 self.vendor_abbreviations = []
191 self.vulkan_versions = []
193 def beginFile(self, genOpts):
194 gen.OutputGenerator.beginFile(self, genOpts)
196 for node in self.registry.reg.findall('enums'):
197 if node.get('name') == 'API Constants':
198 for item in node.findall('enum'):
199 self.constants[item.get('name')] = item.get('value')
201 for node in self.registry.reg.find('extensions').findall('extension'):
202 ext = VulkanExtension(node)
203 for item in ext.vktypes:
204 self.extTypes[item] = ext
205 for item in ext.vkfuncs:
206 self.extFuncs[item] = ext
208 # need list of venders to blacklist vendor extensions
209 for tag in self.registry.reg.find('tags'):
210 if tag.get("name") not in ["KHR", "EXT"]:
211 self.vendor_abbreviations.append("_" + tag.get('name'))
213 for ver in self.registry.reg.findall('feature'):
214 self.vulkan_versions.append(VulkanVersion(ver))
217 # gather the types that are needed to generate
219 for s in enums_to_gen:
222 for f in flags_to_gen:
225 types_to_gen = types_to_gen.union(
226 GatherTypesToGen(self.all_structures, structures_to_gen))
227 for key in EXTENSION_CATEGORIES.keys():
228 types_to_gen = types_to_gen.union(
229 GatherTypesToGen(self.all_structures, self.extension_sets[key]))
231 names_of_structures_to_gen = set()
232 for s in self.all_structures:
233 if s.name in types_to_gen:
234 names_of_structures_to_gen.add(s.name)
236 structs_to_comp = set()
237 for s in struct_comparisons_to_gen:
238 structs_to_comp.add(s)
239 structs_to_comp = structs_to_comp.union(
240 GatherTypesToGen(self.all_structures, struct_comparisons_to_gen))
242 for key, value in self.extension_sets.items():
243 self.extension_sets[key] = sorted(value)
246 for version in self.vulkan_versions:
247 for aliased_type, aliases in self.aliases.items():
248 for alias in aliases:
249 if alias in version.names:
250 alias_versions[alias] = version.minorVersion
252 # print the types gathered
254 out += license_header + "\n"
255 out += "#include \"vulkaninfo.h\"\n"
256 out += "#include \"outputprinter.h\"\n"
257 out += custom_formaters
259 for enum in (e for e in self.enums if e.name in types_to_gen):
260 out += PrintEnumToString(enum, self)
261 out += PrintEnum(enum, self)
263 for flag in self.flags:
264 if flag.name in types_to_gen:
265 for bitmask in (b for b in self.bitmasks if b.name == flag.enum):
266 out += PrintBitMask(bitmask, flag.name, self)
268 if flag.name in flags_strings_to_gen:
269 for bitmask in (b for b in self.bitmasks if b.name == flag.enum):
270 out += PrintBitMaskToString(bitmask, flag.name, self)
272 for s in (x for x in self.all_structures if x.name in types_to_gen and x.name not in struct_blacklist):
273 out += PrintStructure(s, types_to_gen, names_of_structures_to_gen)
275 out += "pNextChainInfos get_chain_infos() {\n"
276 out += " pNextChainInfos infos;\n"
277 for key in EXTENSION_CATEGORIES.keys():
278 out += PrintChainBuilders(key,
279 self.extension_sets[key], self.all_structures)
280 out += " return infos;\n}\n"
282 for key, value in EXTENSION_CATEGORIES.items():
283 out += PrintChainIterator(key,
284 self.extension_sets[key], self.all_structures, value.get('type'), self.extTypes, self.aliases, self.vulkan_versions)
286 for s in (x for x in self.all_structures if x.name in structs_to_comp):
287 out += PrintStructComparison(s)
288 for s in (x for x in self.all_structures if x.name in struct_short_versions_to_gen):
289 out += PrintStructShort(s)
291 gen.write(out, file=self.outFile)
293 gen.OutputGenerator.endFile(self)
295 def genCmd(self, cmd, name, alias):
296 gen.OutputGenerator.genCmd(self, cmd, name, alias)
298 # These are actually constants
299 def genEnum(self, enuminfo, name, alias):
300 gen.OutputGenerator.genEnum(self, enuminfo, name, alias)
302 # These are actually enums
303 def genGroup(self, groupinfo, groupName, alias):
304 gen.OutputGenerator.genGroup(self, groupinfo, groupName, alias)
306 if alias is not None:
307 if alias in self.aliases.keys():
308 self.aliases[alias].append(groupName)
310 self.aliases[alias] = [groupName, ]
313 if groupinfo.elem.get('type') == 'bitmask':
314 self.bitmasks.append(VulkanBitmask(groupinfo.elem))
315 elif groupinfo.elem.get('type') == 'enum':
316 self.enums.append(VulkanEnum(groupinfo.elem))
318 def genType(self, typeinfo, name, alias):
319 gen.OutputGenerator.genType(self, typeinfo, name, alias)
321 if alias is not None:
322 if alias in self.aliases.keys():
323 self.aliases[alias].append(name)
325 self.aliases[alias] = [name, ]
328 if typeinfo.elem.get('category') == 'bitmask':
329 self.flags.append(VulkanFlags(typeinfo.elem))
331 if typeinfo.elem.get('category') == 'struct':
332 self.all_structures.append(VulkanStructure(
333 name, typeinfo.elem, self.constants, self.extTypes))
335 for vendor in self.vendor_abbreviations:
336 for node in typeinfo.elem.findall('member'):
337 if(node.get('values') is not None):
338 if(node.get('values').find(vendor)) != -1:
341 for key, value in EXTENSION_CATEGORIES.items():
342 if typeinfo.elem.get('structextends') == value.get('extends'):
343 self.extension_sets[key].add(name)
346 def GatherTypesToGen(structure_list, structures):
348 added_stuff = True # repeat until no new types are added
349 while added_stuff == True:
351 for s in (x for x in structure_list if x.name in structures):
354 if len(types) != size:
357 if m.typeID not in predefined_types and m.name not in ['sType', 'pNext']:
362 def GetExtension(name, generator):
363 if name in generator.extFuncs:
364 return generator.extFuncs[name]
365 elif name in generator.extTypes:
366 return generator.extTypes[name]
371 def AddGuardHeader(obj):
372 if obj is not None and obj.guard is not None:
373 return "#ifdef {}\n".format(obj.guard)
378 def AddGuardFooter(obj):
379 if obj is not None and obj.guard is not None:
380 return "#endif // {}\n".format(obj.guard)
385 def PrintEnumToString(enum, gen):
387 out += AddGuardHeader(GetExtension(enum.name, gen))
389 out += "static const char *" + enum.name + \
390 "String(" + enum.name + " value) {\n"
391 out += " switch (value) {\n"
392 for v in enum.options:
393 out += " case (" + str(v.value) + \
394 "): return \"" + v.name[3:] + "\";\n"
395 out += " default: return \"UNKNOWN_" + enum.name + "\";\n"
397 out += AddGuardFooter(GetExtension(enum.name, gen))
401 def PrintEnum(enum, gen):
403 out += AddGuardHeader(GetExtension(enum.name, gen))
404 out += "void Dump" + enum.name + \
405 "(Printer &p, std::string name, " + \
406 enum.name + " value, int width = 0) {\n"
407 out += " if (p.Type() == OutputType::json) {\n"
408 out += " p.PrintKeyValue(name, value, width);\n"
410 out += " p.PrintKeyString(name, " + \
411 enum.name + "String(value), width);\n }\n"
413 out += AddGuardFooter(GetExtension(enum.name, gen))
417 def PrintGetFlagStrings(name, bitmask):
419 out += "std::vector<const char *>" + name + \
420 "GetStrings(" + name + " value) {\n"
422 out += " std::vector<const char *> strings;\n"
423 out += " if (value == 0) strings.push_back(\"None\");\n"
424 for v in bitmask.options:
425 val = v.value if isinstance(v.value, str) else str(hex(v.value))
426 out += " if (" + val + " & value) strings.push_back(\"" + \
427 str(v.name[3:]) + "\");\n"
428 out += " return strings;\n}\n"
432 def PrintFlags(bitmask, name):
433 out = "void Dump" + name + \
434 "(Printer &p, std::string name, " + name + " value, int width = 0) {\n"
435 out += " if (p.Type() == OutputType::json) { p.PrintKeyValue(name, value); return; }\n"
436 out += " auto strings = " + bitmask.name + \
437 "GetStrings(static_cast<" + bitmask.name + ">(value));\n"
438 out += " if (static_cast<" + bitmask.name + ">(value) == 0) {\n"
439 out += " ArrayWrapper arr(p, name, 0);\n"
440 out += " p.SetAsType().PrintString(\"None\");\n"
443 out += " ArrayWrapper arr(p, name, strings.size());\n"
444 out += " for(auto& str : strings){\n"
445 out += " p.SetAsType().PrintString(str);\n"
451 def PrintFlagBits(bitmask):
452 out = "void Dump" + bitmask.name + \
453 "(Printer &p, std::string name, " + \
454 bitmask.name + " value, int width = 0) {\n"
455 out += " auto strings = " + bitmask.name + "GetStrings(value);\n"
456 out += " p.PrintKeyString(name, strings.at(0), width);\n"
461 def PrintBitMask(bitmask, name, gen):
462 out = PrintGetFlagStrings(bitmask.name, bitmask)
463 out += AddGuardHeader(GetExtension(bitmask.name, gen))
464 out += PrintFlags(bitmask, name)
465 out += PrintFlagBits(bitmask)
466 out += AddGuardFooter(GetExtension(bitmask.name, gen))
471 def PrintBitMaskToString(bitmask, name, gen):
472 out = AddGuardHeader(GetExtension(bitmask.name, gen))
473 out += "std::string " + name + \
474 "String(" + name + " value, int width = 0) {\n"
475 out += " std::string out;\n"
476 out += " bool is_first = true;\n"
477 for v in bitmask.options:
478 out += " if (" + str(v.value) + " & value) {\n"
479 out += " if (is_first) { is_first = false; } else { out += \" | \"; }\n"
480 out += " out += \"" + \
481 str(v.name).strip("VK_").strip("_BIT") + "\";\n"
483 out += " return out;\n"
485 out += AddGuardFooter(GetExtension(bitmask.name, gen))
489 def PrintStructure(struct, types_to_gen, structure_names):
490 if len(struct.members) == 0:
493 out += AddGuardHeader(struct)
495 for v in struct.members:
496 if v.arrayLength is not None:
497 if len(v.name) + len(v.arrayLength) + 2 > max_key_len:
498 max_key_len = len(v.name) + len(v.arrayLength) + 2
499 elif v.typeID in predefined_types or v.typeID in struct_blacklist:
500 if len(v.name) > max_key_len:
501 max_key_len = len(v.name)
503 out += "void Dump" + struct.name + \
504 "(Printer &p, std::string name, " + struct.name + " &obj) {\n"
505 if struct.name == "VkPhysicalDeviceLimits":
506 out += " if (p.Type() == OutputType::json)\n"
507 out += " p.ObjectStart(\"limits\");\n"
509 out += " p.SetSubHeader().ObjectStart(name);\n"
510 elif struct.name == "VkPhysicalDeviceSparseProperties":
511 out += " if (p.Type() == OutputType::json)\n"
512 out += " p.ObjectStart(\"sparseProperties\");\n"
514 out += " p.SetSubHeader().ObjectStart(name);\n"
516 out += " ObjectWrapper object{p, name};\n"
518 for v in struct.members:
520 if v.arrayLength is not None:
522 if v.typeID == "char":
523 out += " p.PrintKeyString(\"" + v.name + "\", obj." + \
524 v.name + ", " + str(max_key_len) + ");\n"
526 elif (v.arrayLength == str(16) and v.typeID == "uint8_t"): # VK_UUID_SIZE
527 out += " p.PrintKeyString(\"" + v.name + "\", to_string_16(obj." + \
528 v.name + "), " + str(max_key_len) + ");\n"
529 elif (v.arrayLength == str(8) and v.typeID == "uint8_t"): # VK_LUID_SIZE
530 out += " if (obj.deviceLUIDValid)" # special case
531 out += " p.PrintKeyString(\"" + v.name + "\", to_string_8(obj." + \
532 v.name + "), " + str(max_key_len) + ");\n"
533 elif v.arrayLength.isdigit():
534 out += " { ArrayWrapper arr(p,\"" + v.name + \
535 "\", "+v.arrayLength+");\n"
536 for i in range(0, int(v.arrayLength)):
537 out += " p.PrintElement(obj." + \
538 v.name + "[" + str(i) + "]);\n"
540 else: # dynamic array length based on other member
541 out += " ArrayWrapper arr(p,\"" + v.name + \
542 "\", obj."+v.arrayLength+");\n"
543 out += " for (uint32_t i = 0; i < obj." + \
544 v.arrayLength+"; i++) {\n"
545 if v.typeID in types_to_gen:
546 out += " if (obj." + v.name + " != nullptr) {\n"
547 out += " p.SetElementIndex(i);\n"
548 out += " Dump" + v.typeID + \
549 "(p, \"" + v.name + "\", obj." + v.name + "[i]);\n"
552 out += " p.PrintElement(obj." + v.name + "[i]);\n"
554 elif v.typeID == "VkBool32":
555 out += " p.PrintKeyBool(\"" + v.name + "\", static_cast<bool>(obj." + \
556 v.name + "), " + str(max_key_len) + ");\n"
557 elif v.typeID == "VkConformanceVersion":
558 out += " DumpVkConformanceVersion(p, \"conformanceVersion\", obj." + \
559 v.name + ", " + str(max_key_len) + ");\n"
560 elif v.typeID == "VkDeviceSize":
561 out += " p.PrintKeyValue(\"" + v.name + "\", to_hex_str(p, obj." + \
562 v.name + "), " + str(max_key_len) + ");\n"
563 elif v.typeID in predefined_types:
564 out += " p.PrintKeyValue(\"" + v.name + "\", obj." + \
565 v.name + ", " + str(max_key_len) + ");\n"
566 elif v.name not in ['sType', 'pNext']:
567 # if it is an enum/flag/bitmask, add the calculated width
568 if v.typeID not in structure_names:
569 out += " Dump" + v.typeID + \
570 "(p, \"" + v.name + "\", obj." + \
571 v.name + ", " + str(max_key_len) + ");\n"
573 out += " Dump" + v.typeID + \
574 "(p, \"" + v.name + "\", obj." + v.name + ");\n"
575 if struct.name in ["VkPhysicalDeviceLimits", "VkPhysicalDeviceSparseProperties"]:
576 out += " p.ObjectEnd();\n"
579 out += AddGuardFooter(struct)
583 def PrintStructShort(struct):
585 out += AddGuardHeader(struct)
586 out += "std::ostream &operator<<(std::ostream &o, " + \
587 struct.name + " &obj) {\n"
588 out += " return o << \"(\" << "
591 for v in struct.members:
594 out += "obj." + v.name + " << "
596 out += "\',\' << obj." + v.name + " << "
599 out += AddGuardFooter(struct)
603 def PrintChainBuilders(listName, structures, all_structures):
604 sorted_structures = sorted(
605 all_structures, key=operator.attrgetter('name'))
608 out += " infos." + listName + " = {\n"
609 for s in sorted_structures:
610 if s.name in structures:
611 out += AddGuardHeader(s)
612 if s.sTypeName is not None:
613 out += " {" + s.sTypeName + \
614 ", sizeof(" + s.name + ")},\n"
615 out += AddGuardFooter(s)
620 def PrintChainIterator(listName, structures, all_structures, checkExtLoc, extTypes, aliases, versions):
622 out += "void chain_iterator_" + listName + "(Printer &p, "
623 if checkExtLoc == "device":
625 elif checkExtLoc == "instance":
626 out += "AppInstance &inst"
627 elif checkExtLoc == "both":
628 out += "AppInstance &inst, AppGpu &gpu"
629 out += ", void * place, VulkanVersion version) {\n"
631 out += " while (place) {\n"
632 out += " struct VkStructureHeader *structure = (struct VkStructureHeader *)place;\n"
633 out += " p.SetSubHeader();\n"
634 for s in all_structures:
635 if s.sTypeName is None:
640 for k, e in extTypes.items():
641 if k == s.name or (s.name in aliases.keys() and k in aliases[s.name]):
642 if e.extNameStr is not None:
643 extNameStr = e.extNameStr
644 if e.type is not None:
648 oldVersionName = None
650 if s.name in v.names:
651 version = v.minorVersion
652 if s.name in aliases.keys():
653 for alias in aliases[s.name]:
654 oldVersionName = alias
656 if s.name in structures:
657 out += AddGuardHeader(s)
658 out += " if (structure->sType == " + s.sTypeName
659 has_version = version is not None
660 has_extNameStr = extNameStr is not None or s.name in aliases.keys()
662 if has_version or has_extNameStr:
665 if extType == "device":
666 out += "gpu.CheckPhysicalDeviceExtensionIncluded(" + \
668 elif extType == "instance":
669 out += "inst.CheckExtensionEnabled(" + extNameStr + ")"
670 if has_version and extType is not None:
673 out += "version.minor >= " + str(version)
676 out += " " + s.name + "* props = " + \
677 "("+s.name+"*)structure;\n"
679 out += " Dump" + s.name + "(p, "
680 if s.name in aliases.keys() and version is not None:
681 out += "version.minor >= " + version + " ?\"" + \
682 s.name + "\":\"" + oldVersionName + "\""
684 out += "\"" + s.name + "\""
685 out += ", *props);\n"
686 out += " p.AddNewline();\n"
688 out += AddGuardFooter(s)
689 out += " place = structure->pNext;\n"
695 def PrintStructComparison(structure):
697 out += "bool operator==(const " + structure.name + \
698 " & a, const " + structure.name + " b) {\n"
701 for m in structure.members:
702 if m.name not in ['sType', 'pNext']:
707 out += "a." + m.name + " == b." + m.name
716 def __init__(self, name, value, bitpos, comment):
718 self.comment = comment
720 if value == 0 or value is None:
721 value = 1 << int(bitpos)
727 'optName': self.name,
728 'optValue': self.value,
729 'optComment': self.comment,
732 def __init__(self, rootNode):
733 self.name = rootNode.get('name')
734 self.type = rootNode.get('type')
737 for child in rootNode:
738 childName = child.get('name')
739 childValue = child.get('value')
740 childBitpos = child.get('bitpos')
741 childComment = child.get('comment')
742 childExtends = child.get('extends')
743 childOffset = child.get('offset')
744 childExtNum = child.get('extnumber')
745 support = child.get('supported')
746 if(support == "disabled"):
749 if childName is None:
751 if (childValue is None and childBitpos is None and childOffset is None):
754 if childExtends is not None and childExtNum is not None and childOffset is not None:
756 extNum = int(childExtNum)
757 extOffset = int(childOffset)
760 childValue = extBase + (extNum - 1) * extBlockSize + extOffset
761 if ('dir' in child.keys()):
762 childValue = -childValue
764 for o in self.options:
765 if o.values()['optName'] == childName:
770 self.options.append(VulkanEnum.Option(
771 childName, childValue, childBitpos, childComment))
776 def __init__(self, rootNode):
777 self.name = rootNode.get('name')
778 self.type = rootNode.get('type')
780 # Read each value that the enum contains
782 for child in rootNode:
783 childName = child.get('name')
784 childValue = child.get('value')
785 childBitpos = child.get('bitpos')
786 childComment = child.get('comment')
787 support = child.get('supported')
788 if childName is None or (childValue is None and childBitpos is None):
790 if(support == "disabled"):
794 for option in self.options:
795 if option.name == childName:
800 self.options.append(VulkanEnum.Option(
801 childName, childValue, childBitpos, childComment))
806 def __init__(self, rootNode):
807 self.name = rootNode.get('name')
808 self.type = rootNode.get('type')
809 self.enum = rootNode.get('requires')
812 class VulkanVariable:
813 def __init__(self, rootNode, constants, parentName):
814 self.name = rootNode.find('name').text
815 # Typename, dereferenced and converted to a useable C++ token
816 self.typeID = rootNode.find('type').text
817 self.baseType = self.typeID
818 self.childType = None
819 self.arrayLength = None
822 for node in rootNode.itertext():
823 comment = rootNode.find('comment')
824 if comment is not None and comment.text == node:
828 typeMatch = re.search('.+?(?=' + self.name + ')', self.text)
829 self.type = typeMatch.string[typeMatch.start():typeMatch.end()]
830 self.type = ' '.join(self.type.split())
831 bracketMatch = re.search('(?<=\\[)[a-zA-Z0-9_]+(?=\\])', self.text)
832 if bracketMatch is not None:
833 matchText = bracketMatch.string[bracketMatch.start(
834 ):bracketMatch.end()]
835 self.childType = self.type
836 self.type += '[' + matchText + ']'
837 if matchText in constants:
838 self.arrayLength = constants[matchText]
840 self.arrayLength = matchText
842 self.lengthMember = False
843 lengthString = rootNode.get('len')
845 if lengthString is not None:
846 lengths = re.split(',', lengthString)
847 lengths = list(filter(('null-terminated').__ne__, lengths))
848 assert(len(lengths) <= 1)
849 if self.arrayLength is None and len(lengths) > 0:
850 self.childType = '*'.join(self.type.split('*')[0:-1])
851 self.arrayLength = lengths[0]
852 self.lengthMember = True
853 if self.arrayLength is not None and self.arrayLength.startswith('latexmath'):
854 code = self.arrayLength[10:len(self.arrayLength)]
855 code = re.sub('\\[', '', code)
856 code = re.sub('\\]', '', code)
857 code = re.sub('\\\\(lceil|rceil)', '', code)
858 code = re.sub('{|}', '', code)
859 code = re.sub('\\\\mathit', '', code)
860 code = re.sub('\\\\over', '/', code)
861 code = re.sub('\\\\textrm', '', code)
862 self.arrayLength = code
864 # Dereference if necessary and handle members of variables
865 if self.arrayLength is not None:
866 self.arrayLength = re.sub('::', '->', self.arrayLength)
867 sections = self.arrayLength.split('->')
868 if sections[-1][0] == 'p' and sections[0][1].isupper():
869 self.arrayLength = '*' + self.arrayLength
872 class VulkanStructure:
873 def __init__(self, name, rootNode, constants, extTypes):
877 self.sTypeName = None
878 self.extendsStruct = rootNode.get('structextends')
880 for node in rootNode.findall('member'):
881 if(node.get('values') is not None):
882 self.sTypeName = node.get('values')
883 self.members.append(VulkanVariable(
884 node, constants, self.name))
886 for k, e in extTypes.items():
888 if e.guard is not None:
892 class VulkanExtension:
893 def __init__(self, rootNode):
894 self.name = rootNode.get('name')
895 self.number = int(rootNode.get('number'))
896 self.type = rootNode.get('type')
897 self.dependency = rootNode.get('requires')
898 self.guard = GetFeatureProtect(rootNode)
899 self.supported = rootNode.get('supported')
900 self.extNameStr = None
908 promotedto = rootNode.get('promotedto')
909 if promotedto != None:
910 # get last char of VK_VERSION_1_1 or VK_VERSION_1_2
911 minorVersion = promotedto[-1:]
912 if minorVersion.isdigit():
913 self.version = minorVersion
915 for req in rootNode.findall('require'):
916 for ty in req.findall('type'):
917 self.vktypes.append(ty.get('name'))
919 for func in req.findall('command'):
920 self.vkfuncs.append(func.get('name'))
922 for enum in req.findall('enum'):
923 base = enum.get('extends')
924 name = enum.get('name')
925 value = enum.get('value')
926 bitpos = enum.get('bitpos')
927 offset = enum.get('offset')
928 # gets the VK_XXX_EXTENSION_NAME string
929 if value == "\"" + self.name + "\"":
930 self.extNameStr = name
932 if value is None and bitpos is not None:
933 value = 1 << int(bitpos)
935 if offset is not None:
937 if base is not None and offset is not None:
938 enumValue = 1000000000 + 1000*(self.number - 1) + offset
939 if enum.get('dir') == '-':
940 enumValue = -enumValue
941 self.enumValues[base] = (name, enumValue)
943 self.constants[name] = value
947 def __init__(self, rootNode):
948 self.name = rootNode.get('name')
949 version_str = rootNode.get('number').split('.')
950 self.majorVersion = version_str[0]
951 self.minorVersion = version_str[1]
954 for req in rootNode.findall('require'):
955 for ty in req.findall('type'):
956 self.names.add(ty.get('name'))
957 for func in req.findall('command'):
958 self.names.add(func.get('name'))
959 for enum in req.findall('enum'):
960 self.names.add(enum.get('name'))