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("\"");
87 # used in the .cpp code
88 structures_to_gen = ['VkExtent3D', 'VkExtent2D', 'VkPhysicalDeviceLimits', 'VkPhysicalDeviceFeatures', 'VkPhysicalDeviceSparseProperties',
89 'VkSurfaceCapabilitiesKHR', 'VkSurfaceFormatKHR', 'VkLayerProperties', 'VkPhysicalDeviceToolPropertiesEXT']
90 enums_to_gen = ['VkResult', 'VkFormat', 'VkPresentModeKHR',
91 'VkPhysicalDeviceType', 'VkImageTiling']
92 flags_to_gen = ['VkSurfaceTransformFlagsKHR', 'VkCompositeAlphaFlagsKHR', 'VkSurfaceCounterFlagsEXT',
93 'VkDeviceGroupPresentModeFlagsKHR', 'VkFormatFeatureFlags', 'VkMemoryPropertyFlags', 'VkMemoryHeapFlags']
94 flags_strings_to_gen = ['VkQueueFlags']
96 struct_short_versions_to_gen = ['VkExtent3D']
98 struct_comparisons_to_gen = ['VkSurfaceFormatKHR', 'VkSurfaceFormat2KHR', 'VkSurfaceCapabilitiesKHR',
99 'VkSurfaceCapabilities2KHR', 'VkSurfaceCapabilities2EXT']
100 # don't generate these structures
101 struct_blacklist = ['VkConformanceVersion']
103 # iostream or custom outputter handles these types
104 predefined_types = ['char', 'VkBool32', 'uint32_t', 'uint8_t', 'int32_t',
105 'float', 'uint64_t', 'size_t', 'VkDeviceSize']
107 # Types that need pNext Chains built. 'extends' is the xml tag used in the structextends member. 'type' can be device, instance, or both
108 EXTENSION_CATEGORIES = OrderedDict((('phys_device_props2', {'extends': 'VkPhysicalDeviceProperties2', 'type': 'both'}),
109 ('phys_device_mem_props2', {'extends': 'VkPhysicalDeviceMemoryProperties2', 'type': 'device'}),
110 ('phys_device_features2', {'extends': 'VkPhysicalDeviceFeatures2,VkDeviceCreateInfo', 'type': 'device'}),
111 ('surface_capabilities2', {'extends': 'VkSurfaceCapabilities2KHR', 'type': 'both'}),
112 ('format_properties2', {'extends': 'VkFormatProperties2', 'type': 'device'})
114 class VulkanInfoGeneratorOptions(GeneratorOptions):
124 defaultExtensions=None,
126 removeExtensions=None,
130 genFuncPointers=True,
134 protectProtoStr=None,
138 indentFuncProto=True,
139 indentFuncPointer=False,
141 expandEnumerants=True,
143 GeneratorOptions.__init__(self,
144 conventions = conventions,
146 directory = directory,
150 emitversions = emitversions,
151 defaultExtensions = defaultExtensions,
152 addExtensions = addExtensions,
153 removeExtensions = removeExtensions,
154 emitExtensions = emitExtensions,
155 sortProcedure = sortProcedure)
157 self.prefixText = prefixText
158 self.genFuncPointers = genFuncPointers
159 self.protectFile = protectFile
160 self.protectFeature = protectFeature
161 self.protectProto = protectProto
162 self.protectProtoStr = protectProtoStr
163 self.apicall = apicall
164 self.apientry = apientry
165 self.apientryp = apientryp
166 self.indentFuncProto = indentFuncProto
167 self.indentFuncPointer = indentFuncPointer
168 self.alignFuncParam = alignFuncParam
170 # VulkanInfoGenerator - subclass of OutputGenerator.
171 # Generates a vulkan info output helper function
174 class VulkanInfoGenerator(OutputGenerator):
179 diagFile=sys.stdout):
180 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
182 self.constants = OrderedDict()
184 self.types_to_gen = set()
186 self.extension_sets = OrderedDict()
187 for ext_cat in EXTENSION_CATEGORIES.keys():
188 self.extension_sets[ext_cat] = set()
193 self.all_structures = []
194 self.aliases = OrderedDict()
196 self.extFuncs = OrderedDict()
197 self.extTypes = OrderedDict()
199 self.vendor_abbreviations = []
200 self.vulkan_versions = []
202 def beginFile(self, genOpts):
203 gen.OutputGenerator.beginFile(self, genOpts)
205 for node in self.registry.reg.findall('enums'):
206 if node.get('name') == 'API Constants':
207 for item in node.findall('enum'):
208 self.constants[item.get('name')] = item.get('value')
210 for node in self.registry.reg.find('extensions').findall('extension'):
211 ext = VulkanExtension(node)
212 for item in ext.vktypes:
213 self.extTypes[item] = ext
214 for item in ext.vkfuncs:
215 self.extFuncs[item] = ext
217 # need list of venders to blacklist vendor extensions
218 for tag in self.registry.reg.find('tags'):
219 if tag.get("name") not in ["KHR", "EXT"]:
220 self.vendor_abbreviations.append("_" + tag.get('name'))
222 for ver in self.registry.reg.findall('feature'):
223 self.vulkan_versions.append(VulkanVersion(ver))
226 # gather the types that are needed to generate
228 for s in enums_to_gen:
231 for f in flags_to_gen:
235 GatherTypesToGen(self.all_structures, structures_to_gen))
236 for key in EXTENSION_CATEGORIES.keys():
238 GatherTypesToGen(self.all_structures, self.extension_sets[key]))
239 types_to_gen = sorted(types_to_gen)
241 names_of_structures_to_gen = set()
242 for s in self.all_structures:
243 if s.name in types_to_gen:
244 names_of_structures_to_gen.add(s.name)
245 names_of_structures_to_gen = sorted(names_of_structures_to_gen)
247 structs_to_comp = set()
248 for s in struct_comparisons_to_gen:
249 structs_to_comp.add(s)
250 structs_to_comp.update(
251 GatherTypesToGen(self.all_structures, struct_comparisons_to_gen))
253 for key, value in self.extension_sets.items():
254 self.extension_sets[key] = sorted(value)
256 alias_versions = OrderedDict()
257 for version in self.vulkan_versions:
258 for aliased_type, aliases in self.aliases.items():
259 for alias in aliases:
260 if alias in version.names:
261 alias_versions[alias] = version.minorVersion
263 self.enums = sorted(self.enums, key=operator.attrgetter('name'))
264 self.flags = sorted(self.flags, key=operator.attrgetter('name'))
265 self.bitmasks = sorted(self.bitmasks, key=operator.attrgetter('name'))
266 self.all_structures = sorted(self.all_structures, key=operator.attrgetter('name'))
268 # print the types gathered
270 out += license_header + "\n"
271 out += "#include \"vulkaninfo.h\"\n"
272 out += "#include \"outputprinter.h\"\n"
273 out += custom_formaters
275 for enum in (e for e in self.enums if e.name in types_to_gen):
276 out += PrintEnumToString(enum, self)
277 out += PrintEnum(enum, self)
279 for flag in self.flags:
280 if flag.name in types_to_gen:
281 for bitmask in (b for b in self.bitmasks if b.name == flag.enum):
282 out += PrintBitMask(bitmask, flag.name, self)
284 if flag.name in flags_strings_to_gen:
285 for bitmask in (b for b in self.bitmasks if b.name == flag.enum):
286 out += PrintBitMaskToString(bitmask, flag.name, self)
288 for s in (x for x in self.all_structures if x.name in types_to_gen and x.name not in struct_blacklist):
289 out += PrintStructure(s, types_to_gen, names_of_structures_to_gen)
291 out += "pNextChainInfos get_chain_infos() {\n"
292 out += " pNextChainInfos infos;\n"
293 for key in EXTENSION_CATEGORIES.keys():
294 out += PrintChainBuilders(key,
295 self.extension_sets[key], self.all_structures)
296 out += " return infos;\n}\n"
298 for key, value in EXTENSION_CATEGORIES.items():
299 out += PrintChainIterator(key,
300 self.extension_sets[key], self.all_structures, value.get('type'), self.extTypes, self.aliases, self.vulkan_versions)
302 for s in (x for x in self.all_structures if x.name in structs_to_comp):
303 out += PrintStructComparisonForwardDecl(s)
304 for s in (x for x in self.all_structures if x.name in structs_to_comp):
305 out += PrintStructComparison(s)
306 for s in (x for x in self.all_structures if x.name in struct_short_versions_to_gen):
307 out += PrintStructShort(s)
309 gen.write(out, file=self.outFile)
311 gen.OutputGenerator.endFile(self)
313 def genCmd(self, cmd, name, alias):
314 gen.OutputGenerator.genCmd(self, cmd, name, alias)
316 # These are actually constants
317 def genEnum(self, enuminfo, name, alias):
318 gen.OutputGenerator.genEnum(self, enuminfo, name, alias)
320 # These are actually enums
321 def genGroup(self, groupinfo, groupName, alias):
322 gen.OutputGenerator.genGroup(self, groupinfo, groupName, alias)
324 if alias is not None:
325 if alias in self.aliases.keys():
326 self.aliases[alias].append(groupName)
328 self.aliases[alias] = [groupName, ]
331 if groupinfo.elem.get('type') == 'bitmask':
332 self.bitmasks.append(VulkanBitmask(groupinfo.elem))
333 elif groupinfo.elem.get('type') == 'enum':
334 self.enums.append(VulkanEnum(groupinfo.elem))
336 def genType(self, typeinfo, name, alias):
337 gen.OutputGenerator.genType(self, typeinfo, name, alias)
339 if alias is not None:
340 if alias in self.aliases.keys():
341 self.aliases[alias].append(name)
343 self.aliases[alias] = [name, ]
346 if typeinfo.elem.get('category') == 'bitmask':
347 self.flags.append(VulkanFlags(typeinfo.elem))
349 if typeinfo.elem.get('category') == 'struct':
350 self.all_structures.append(VulkanStructure(
351 name, typeinfo.elem, self.constants, self.extTypes))
353 for vendor in self.vendor_abbreviations:
354 for node in typeinfo.elem.findall('member'):
355 if(node.get('values') is not None):
356 if(node.get('values').find(vendor)) != -1:
359 for key, value in EXTENSION_CATEGORIES.items():
360 if typeinfo.elem.get('structextends') == value.get('extends'):
361 self.extension_sets[key].add(name)
364 def GatherTypesToGen(structure_list, structures):
366 added_stuff = True # repeat until no new types are added
367 while added_stuff == True:
369 for s in (x for x in structure_list if x.name in structures):
372 if len(types) != size:
375 if m.typeID not in predefined_types and m.name not in ['sType', 'pNext']:
377 types = sorted(types)
381 def GetExtension(name, generator):
382 if name in generator.extFuncs:
383 return generator.extFuncs[name]
384 elif name in generator.extTypes:
385 return generator.extTypes[name]
390 def AddGuardHeader(obj):
391 if obj is not None and obj.guard is not None:
392 return "#ifdef {}\n".format(obj.guard)
397 def AddGuardFooter(obj):
398 if obj is not None and obj.guard is not None:
399 return "#endif // {}\n".format(obj.guard)
404 def PrintEnumToString(enum, gen):
406 out += AddGuardHeader(GetExtension(enum.name, gen))
408 out += "static const char *" + enum.name + \
409 "String(" + enum.name + " value) {\n"
410 out += " switch (value) {\n"
411 for v in enum.options:
412 out += " case (" + str(v.value) + \
413 "): return \"" + v.name[3:] + "\";\n"
414 out += " default: return \"UNKNOWN_" + enum.name + "\";\n"
416 out += AddGuardFooter(GetExtension(enum.name, gen))
420 def PrintEnum(enum, gen):
422 out += AddGuardHeader(GetExtension(enum.name, gen))
423 out += "void Dump" + enum.name + \
424 "(Printer &p, std::string name, " + \
425 enum.name + " value, int width = 0) {\n"
426 out += " if (p.Type() == OutputType::json) {\n"
427 out += " p.PrintKeyValue(name, value, width);\n"
429 out += " p.PrintKeyString(name, " + \
430 enum.name + "String(value), width);\n }\n"
432 out += AddGuardFooter(GetExtension(enum.name, gen))
436 def PrintGetFlagStrings(name, bitmask):
438 out += "std::vector<const char *>" + name + \
439 "GetStrings(" + name + " value) {\n"
441 out += " std::vector<const char *> strings;\n"
442 out += " if (value == 0) strings.push_back(\"None\");\n"
443 for v in bitmask.options:
444 val = v.value if isinstance(v.value, str) else str(hex(v.value))
445 out += " if (" + val + " & value) strings.push_back(\"" + \
446 str(v.name[3:]) + "\");\n"
447 out += " return strings;\n}\n"
451 def PrintFlags(bitmask, name):
452 out = "void Dump" + name + \
453 "(Printer &p, std::string name, " + name + " value, int width = 0) {\n"
454 out += " if (p.Type() == OutputType::json) { p.PrintKeyValue(name, value); return; }\n"
455 out += " auto strings = " + bitmask.name + \
456 "GetStrings(static_cast<" + bitmask.name + ">(value));\n"
457 out += " if (static_cast<" + bitmask.name + ">(value) == 0) {\n"
458 out += " ArrayWrapper arr(p, name, 0);\n"
459 out += " p.SetAsType().PrintString(\"None\");\n"
462 out += " ArrayWrapper arr(p, name, strings.size());\n"
463 out += " for(auto& str : strings){\n"
464 out += " p.SetAsType().PrintString(str);\n"
470 def PrintFlagBits(bitmask):
471 out = "void Dump" + bitmask.name + \
472 "(Printer &p, std::string name, " + \
473 bitmask.name + " value, int width = 0) {\n"
474 out += " auto strings = " + bitmask.name + "GetStrings(value);\n"
475 out += " p.PrintKeyString(name, strings.at(0), width);\n"
480 def PrintBitMask(bitmask, name, gen):
481 out = PrintGetFlagStrings(bitmask.name, bitmask)
482 out += AddGuardHeader(GetExtension(bitmask.name, gen))
483 out += PrintFlags(bitmask, name)
484 out += PrintFlagBits(bitmask)
485 out += AddGuardFooter(GetExtension(bitmask.name, gen))
490 def PrintBitMaskToString(bitmask, name, gen):
491 out = AddGuardHeader(GetExtension(bitmask.name, gen))
492 out += "std::string " + name + \
493 "String(" + name + " value, int width = 0) {\n"
494 out += " std::string out;\n"
495 out += " bool is_first = true;\n"
496 for v in bitmask.options:
497 out += " if (" + str(v.value) + " & value) {\n"
498 out += " if (is_first) { is_first = false; } else { out += \" | \"; }\n"
499 out += " out += \"" + \
500 str(v.name).strip("VK_").strip("_BIT") + "\";\n"
502 out += " return out;\n"
504 out += AddGuardFooter(GetExtension(bitmask.name, gen))
508 def PrintStructure(struct, types_to_gen, structure_names):
509 if len(struct.members) == 0:
512 out += AddGuardHeader(struct)
514 for v in struct.members:
515 if v.arrayLength is not None:
516 if len(v.name) + len(v.arrayLength) + 2 > max_key_len:
517 max_key_len = len(v.name) + len(v.arrayLength) + 2
518 elif v.typeID in predefined_types or v.typeID in struct_blacklist:
519 if len(v.name) > max_key_len:
520 max_key_len = len(v.name)
522 out += "void Dump" + struct.name + \
523 "(Printer &p, std::string name, " + struct.name + " &obj) {\n"
524 if struct.name == "VkPhysicalDeviceLimits":
525 out += " if (p.Type() == OutputType::json)\n"
526 out += " p.ObjectStart(\"limits\");\n"
528 out += " p.SetSubHeader().ObjectStart(name);\n"
529 elif struct.name == "VkPhysicalDeviceSparseProperties":
530 out += " if (p.Type() == OutputType::json)\n"
531 out += " p.ObjectStart(\"sparseProperties\");\n"
533 out += " p.SetSubHeader().ObjectStart(name);\n"
535 out += " ObjectWrapper object{p, name};\n"
537 for v in struct.members:
539 if v.arrayLength is not None:
541 if v.typeID == "char":
542 out += " p.PrintKeyString(\"" + v.name + "\", obj." + \
543 v.name + ", " + str(max_key_len) + ");\n"
545 elif (v.arrayLength == str(16) and v.typeID == "uint8_t"): # VK_UUID_SIZE
546 out += " p.PrintKeyString(\"" + v.name + "\", to_string_16(obj." + \
547 v.name + "), " + str(max_key_len) + ");\n"
548 elif (v.arrayLength == str(8) and v.typeID == "uint8_t"): # VK_LUID_SIZE
549 out += " if (obj.deviceLUIDValid)" # special case
550 out += " p.PrintKeyString(\"" + v.name + "\", to_string_8(obj." + \
551 v.name + "), " + str(max_key_len) + ");\n"
552 elif v.arrayLength.isdigit():
553 out += " { ArrayWrapper arr(p,\"" + v.name + \
554 "\", "+v.arrayLength+");\n"
555 for i in range(0, int(v.arrayLength)):
556 out += " p.PrintElement(obj." + \
557 v.name + "[" + str(i) + "]);\n"
559 else: # dynamic array length based on other member
560 out += " ArrayWrapper arr(p,\"" + v.name + \
561 "\", obj."+v.arrayLength+");\n"
562 out += " for (uint32_t i = 0; i < obj." + \
563 v.arrayLength+"; i++) {\n"
564 if v.typeID in types_to_gen:
565 out += " if (obj." + v.name + " != nullptr) {\n"
566 out += " p.SetElementIndex(i);\n"
567 out += " Dump" + v.typeID + \
568 "(p, \"" + v.name + "\", obj." + v.name + "[i]);\n"
571 out += " p.PrintElement(obj." + v.name + "[i]);\n"
573 elif v.typeID == "VkBool32":
574 out += " p.PrintKeyBool(\"" + v.name + "\", static_cast<bool>(obj." + \
575 v.name + "), " + str(max_key_len) + ");\n"
576 elif v.typeID == "VkConformanceVersion":
577 out += " DumpVkConformanceVersion(p, \"conformanceVersion\", obj." + \
578 v.name + ", " + str(max_key_len) + ");\n"
579 elif v.typeID == "VkDeviceSize":
580 out += " p.PrintKeyValue(\"" + v.name + "\", to_hex_str(p, obj." + \
581 v.name + "), " + str(max_key_len) + ");\n"
582 elif v.typeID in predefined_types:
583 out += " p.PrintKeyValue(\"" + v.name + "\", obj." + \
584 v.name + ", " + str(max_key_len) + ");\n"
585 elif v.name not in ['sType', 'pNext']:
586 # if it is an enum/flag/bitmask, add the calculated width
587 if v.typeID not in structure_names:
588 out += " Dump" + v.typeID + \
589 "(p, \"" + v.name + "\", obj." + \
590 v.name + ", " + str(max_key_len) + ");\n"
592 out += " Dump" + v.typeID + \
593 "(p, \"" + v.name + "\", obj." + v.name + ");\n"
594 if struct.name in ["VkPhysicalDeviceLimits", "VkPhysicalDeviceSparseProperties"]:
595 out += " p.ObjectEnd();\n"
598 out += AddGuardFooter(struct)
602 def PrintStructShort(struct):
604 out += AddGuardHeader(struct)
605 out += "std::ostream &operator<<(std::ostream &o, " + \
606 struct.name + " &obj) {\n"
607 out += " return o << \"(\" << "
610 for v in struct.members:
613 out += "obj." + v.name + " << "
615 out += "\',\' << obj." + v.name + " << "
618 out += AddGuardFooter(struct)
622 def PrintChainBuilders(listName, structures, all_structures):
623 sorted_structures = sorted(
624 all_structures, key=operator.attrgetter('name'))
627 out += " infos." + listName + " = {\n"
628 for s in sorted_structures:
629 if s.name in structures:
630 out += AddGuardHeader(s)
631 if s.sTypeName is not None:
632 out += " {" + s.sTypeName + \
633 ", sizeof(" + s.name + ")},\n"
634 out += AddGuardFooter(s)
639 def PrintChainIterator(listName, structures, all_structures, checkExtLoc, extTypes, aliases, versions):
641 out += "void chain_iterator_" + listName + "(Printer &p, "
642 if checkExtLoc == "device":
644 elif checkExtLoc == "instance":
645 out += "AppInstance &inst"
646 elif checkExtLoc == "both":
647 out += "AppInstance &inst, AppGpu &gpu"
648 out += ", void * place, VulkanVersion version) {\n"
650 out += " while (place) {\n"
651 out += " struct VkStructureHeader *structure = (struct VkStructureHeader *)place;\n"
652 out += " p.SetSubHeader();\n"
653 sorted_structures = sorted(
654 all_structures, key=operator.attrgetter('name'))
655 for s in sorted_structures:
656 if s.sTypeName is None:
661 for k, e in extTypes.items():
662 if k == s.name or (s.name in aliases.keys() and k in aliases[s.name]):
663 if e.extNameStr is not None:
664 extNameStr = e.extNameStr
665 if e.type is not None:
669 oldVersionName = None
671 if s.name in v.names:
672 version = v.minorVersion
673 if s.name in aliases.keys():
674 for alias in aliases[s.name]:
675 oldVersionName = alias
677 if s.name in structures:
678 out += AddGuardHeader(s)
679 out += " if (structure->sType == " + s.sTypeName
680 has_version = version is not None
681 has_extNameStr = extNameStr is not None or s.name in aliases.keys()
683 if has_version or has_extNameStr:
686 if extType == "device":
687 out += "gpu.CheckPhysicalDeviceExtensionIncluded(" + \
689 elif extType == "instance":
690 out += "inst.CheckExtensionEnabled(" + extNameStr + ")"
691 if has_version and extType is not None:
694 out += "version.minor >= " + str(version)
697 out += " " + s.name + "* props = " + \
698 "("+s.name+"*)structure;\n"
700 out += " Dump" + s.name + "(p, "
701 if s.name in aliases.keys() and version is not None:
702 out += "version.minor >= " + version + " ?\"" + \
703 s.name + "\":\"" + oldVersionName + "\""
705 out += "\"" + s.name + "\""
706 out += ", *props);\n"
707 out += " p.AddNewline();\n"
709 out += AddGuardFooter(s)
710 out += " place = structure->pNext;\n"
715 def PrintStructComparisonForwardDecl(structure):
717 out += "bool operator==(const " + structure.name + \
718 " & a, const " + structure.name + " b);\n"
722 def PrintStructComparison(structure):
724 out += "bool operator==(const " + structure.name + \
725 " & a, const " + structure.name + " b) {\n"
728 for m in structure.members:
729 if m.name not in ['sType', 'pNext']:
734 out += "a." + m.name + " == b." + m.name
743 def __init__(self, name, value, bitpos, comment):
745 self.comment = comment
747 if value == 0 or value is None:
748 value = 1 << int(bitpos)
754 'optName': self.name,
755 'optValue': self.value,
756 'optComment': self.comment,
759 def __init__(self, rootNode):
760 self.name = rootNode.get('name')
761 self.type = rootNode.get('type')
764 for child in rootNode:
765 childName = child.get('name')
766 childValue = child.get('value')
767 childBitpos = child.get('bitpos')
768 childComment = child.get('comment')
769 childExtends = child.get('extends')
770 childOffset = child.get('offset')
771 childExtNum = child.get('extnumber')
772 support = child.get('supported')
773 if(support == "disabled"):
776 if childName is None:
778 if (childValue is None and childBitpos is None and childOffset is None):
781 if childExtends is not None and childExtNum is not None and childOffset is not None:
783 extNum = int(childExtNum)
784 extOffset = int(childOffset)
787 childValue = extBase + (extNum - 1) * extBlockSize + extOffset
788 if ('dir' in child.keys()):
789 childValue = -childValue
791 for o in self.options:
792 if o.values()['optName'] == childName:
797 self.options.append(VulkanEnum.Option(
798 childName, childValue, childBitpos, childComment))
803 def __init__(self, rootNode):
804 self.name = rootNode.get('name')
805 self.type = rootNode.get('type')
807 # Read each value that the enum contains
809 for child in rootNode:
810 childName = child.get('name')
811 childValue = child.get('value')
812 childBitpos = child.get('bitpos')
813 childComment = child.get('comment')
814 support = child.get('supported')
815 if childName is None or (childValue is None and childBitpos is None):
817 if(support == "disabled"):
821 for option in self.options:
822 if option.name == childName:
827 self.options.append(VulkanEnum.Option(
828 childName, childValue, childBitpos, childComment))
833 def __init__(self, rootNode):
834 self.name = rootNode.get('name')
835 self.type = rootNode.get('type')
836 self.enum = rootNode.get('requires')
839 class VulkanVariable:
840 def __init__(self, rootNode, constants, parentName):
841 self.name = rootNode.find('name').text
842 # Typename, dereferenced and converted to a useable C++ token
843 self.typeID = rootNode.find('type').text
844 self.baseType = self.typeID
845 self.childType = None
846 self.arrayLength = None
849 for node in rootNode.itertext():
850 comment = rootNode.find('comment')
851 if comment is not None and comment.text == node:
855 typeMatch = re.search('.+?(?=' + self.name + ')', self.text)
856 self.type = typeMatch.string[typeMatch.start():typeMatch.end()]
857 self.type = ' '.join(self.type.split())
858 bracketMatch = re.search('(?<=\\[)[a-zA-Z0-9_]+(?=\\])', self.text)
859 if bracketMatch is not None:
860 matchText = bracketMatch.string[bracketMatch.start(
861 ):bracketMatch.end()]
862 self.childType = self.type
863 self.type += '[' + matchText + ']'
864 if matchText in constants:
865 self.arrayLength = constants[matchText]
867 self.arrayLength = matchText
869 self.lengthMember = False
870 lengthString = rootNode.get('len')
872 if lengthString is not None:
873 lengths = re.split(',', lengthString)
874 lengths = list(filter(('null-terminated').__ne__, lengths))
875 assert(len(lengths) <= 1)
876 if self.arrayLength is None and len(lengths) > 0:
877 self.childType = '*'.join(self.type.split('*')[0:-1])
878 self.arrayLength = lengths[0]
879 self.lengthMember = True
880 if self.arrayLength is not None and self.arrayLength.startswith('latexmath'):
881 code = self.arrayLength[10:len(self.arrayLength)]
882 code = re.sub('\\[', '', code)
883 code = re.sub('\\]', '', code)
884 code = re.sub('\\\\(lceil|rceil)', '', code)
885 code = re.sub('{|}', '', code)
886 code = re.sub('\\\\mathit', '', code)
887 code = re.sub('\\\\over', '/', code)
888 code = re.sub('\\\\textrm', '', code)
889 self.arrayLength = code
891 # Dereference if necessary and handle members of variables
892 if self.arrayLength is not None:
893 self.arrayLength = re.sub('::', '->', self.arrayLength)
894 sections = self.arrayLength.split('->')
895 if sections[-1][0] == 'p' and sections[0][1].isupper():
896 self.arrayLength = '*' + self.arrayLength
899 class VulkanStructure:
900 def __init__(self, name, rootNode, constants, extTypes):
904 self.sTypeName = None
905 self.extendsStruct = rootNode.get('structextends')
907 for node in rootNode.findall('member'):
908 if(node.get('values') is not None):
909 self.sTypeName = node.get('values')
910 self.members.append(VulkanVariable(
911 node, constants, self.name))
913 for k, e in extTypes.items():
915 if e.guard is not None:
919 class VulkanExtension:
920 def __init__(self, rootNode):
921 self.name = rootNode.get('name')
922 self.number = int(rootNode.get('number'))
923 self.type = rootNode.get('type')
924 self.dependency = rootNode.get('requires')
925 self.guard = GetFeatureProtect(rootNode)
926 self.supported = rootNode.get('supported')
927 self.extNameStr = None
930 self.constants = OrderedDict()
931 self.enumValues = OrderedDict()
935 promotedto = rootNode.get('promotedto')
936 if promotedto != None:
937 # get last char of VK_VERSION_1_1 or VK_VERSION_1_2
938 minorVersion = promotedto[-1:]
939 if minorVersion.isdigit():
940 self.version = minorVersion
942 for req in rootNode.findall('require'):
943 for ty in req.findall('type'):
944 self.vktypes.append(ty.get('name'))
946 for func in req.findall('command'):
947 self.vkfuncs.append(func.get('name'))
949 for enum in req.findall('enum'):
950 base = enum.get('extends')
951 name = enum.get('name')
952 value = enum.get('value')
953 bitpos = enum.get('bitpos')
954 offset = enum.get('offset')
955 # gets the VK_XXX_EXTENSION_NAME string
956 if value == "\"" + self.name + "\"":
957 self.extNameStr = name
959 if value is None and bitpos is not None:
960 value = 1 << int(bitpos)
962 if offset is not None:
964 if base is not None and offset is not None:
965 enumValue = 1000000000 + 1000*(self.number - 1) + offset
966 if enum.get('dir') == '-':
967 enumValue = -enumValue
968 self.enumValues[base] = (name, enumValue)
970 self.constants[name] = value
974 def __init__(self, rootNode):
975 self.name = rootNode.get('name')
976 version_str = rootNode.get('number').split('.')
977 self.majorVersion = version_str[0]
978 self.minorVersion = version_str[1]
981 for req in rootNode.findall('require'):
982 for ty in req.findall('type'):
983 self.names.add(ty.get('name'))
984 for func in req.findall('command'):
985 self.names.add(func.get('name'))
986 for enum in req.findall('enum'):
987 self.names.add(enum.get('name'))
988 self.names = sorted(self.names)