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, conventions, filename, directory, apiname, profile,
144 versions, emitversions, defaultExtensions,
145 addExtensions, removeExtensions, emitExtensions, sortProcedure)
147 self.prefixText = prefixText
148 self.genFuncPointers = genFuncPointers
149 self.protectFile = protectFile
150 self.protectFeature = protectFeature
151 self.protectProto = protectProto
152 self.protectProtoStr = protectProtoStr
153 self.apicall = apicall
154 self.apientry = apientry
155 self.apientryp = apientryp
156 self.indentFuncProto = indentFuncProto
157 self.indentFuncPointer = indentFuncPointer
158 self.alignFuncParam = alignFuncParam
160 # VulkanInfoGenerator - subclass of OutputGenerator.
161 # Generates a vulkan info output helper function
164 class VulkanInfoGenerator(OutputGenerator):
169 diagFile=sys.stdout):
170 OutputGenerator.__init__(self, errFile, warnFile, diagFile)
172 self.constants = OrderedDict()
174 self.types_to_gen = set()
176 self.extension_sets = OrderedDict()
177 for ext_cat in EXTENSION_CATEGORIES.keys():
178 self.extension_sets[ext_cat] = set()
183 self.all_structures = []
184 self.aliases = OrderedDict()
186 self.extFuncs = OrderedDict()
187 self.extTypes = OrderedDict()
189 self.vendor_abbreviations = []
190 self.vulkan_versions = []
192 def beginFile(self, genOpts):
193 gen.OutputGenerator.beginFile(self, genOpts)
195 for node in self.registry.reg.findall('enums'):
196 if node.get('name') == 'API Constants':
197 for item in node.findall('enum'):
198 self.constants[item.get('name')] = item.get('value')
200 for node in self.registry.reg.find('extensions').findall('extension'):
201 ext = VulkanExtension(node)
202 for item in ext.vktypes:
203 self.extTypes[item] = ext
204 for item in ext.vkfuncs:
205 self.extFuncs[item] = ext
207 # need list of venders to blacklist vendor extensions
208 for tag in self.registry.reg.find('tags'):
209 if tag.get("name") not in ["KHR", "EXT"]:
210 self.vendor_abbreviations.append("_" + tag.get('name'))
212 for ver in self.registry.reg.findall('feature'):
213 self.vulkan_versions.append(VulkanVersion(ver))
216 # gather the types that are needed to generate
218 for s in enums_to_gen:
221 for f in flags_to_gen:
225 GatherTypesToGen(self.all_structures, structures_to_gen))
226 for key in EXTENSION_CATEGORIES.keys():
228 GatherTypesToGen(self.all_structures, self.extension_sets[key]))
229 types_to_gen = sorted(types_to_gen)
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)
235 names_of_structures_to_gen = sorted(names_of_structures_to_gen)
237 structs_to_comp = set()
238 for s in struct_comparisons_to_gen:
239 structs_to_comp.add(s)
240 structs_to_comp.update(
241 GatherTypesToGen(self.all_structures, struct_comparisons_to_gen))
243 for key, value in self.extension_sets.items():
244 self.extension_sets[key] = sorted(value)
246 alias_versions = OrderedDict()
247 for version in self.vulkan_versions:
248 for aliased_type, aliases in self.aliases.items():
249 for alias in aliases:
250 if alias in version.names:
251 alias_versions[alias] = version.minorVersion
253 self.enums = sorted(self.enums, key=operator.attrgetter('name'))
254 self.flags = sorted(self.flags, key=operator.attrgetter('name'))
255 self.bitmasks = sorted(self.bitmasks, key=operator.attrgetter('name'))
256 self.all_structures = sorted(self.all_structures, key=operator.attrgetter('name'))
258 # print the types gathered
260 out += license_header + "\n"
261 out += "#include \"vulkaninfo.h\"\n"
262 out += "#include \"outputprinter.h\"\n"
263 out += custom_formaters
265 for enum in (e for e in self.enums if e.name in types_to_gen):
266 out += PrintEnumToString(enum, self)
267 out += PrintEnum(enum, self)
269 for flag in self.flags:
270 if flag.name in types_to_gen:
271 for bitmask in (b for b in self.bitmasks if b.name == flag.enum):
272 out += PrintBitMask(bitmask, flag.name, self)
274 if flag.name in flags_strings_to_gen:
275 for bitmask in (b for b in self.bitmasks if b.name == flag.enum):
276 out += PrintBitMaskToString(bitmask, flag.name, self)
278 for s in (x for x in self.all_structures if x.name in types_to_gen and x.name not in struct_blacklist):
279 out += PrintStructure(s, types_to_gen, names_of_structures_to_gen)
281 out += "pNextChainInfos get_chain_infos() {\n"
282 out += " pNextChainInfos infos;\n"
283 for key in EXTENSION_CATEGORIES.keys():
284 out += PrintChainBuilders(key,
285 self.extension_sets[key], self.all_structures)
286 out += " return infos;\n}\n"
288 for key, value in EXTENSION_CATEGORIES.items():
289 out += PrintChainIterator(key,
290 self.extension_sets[key], self.all_structures, value.get('type'), self.extTypes, self.aliases, self.vulkan_versions)
292 for s in (x for x in self.all_structures if x.name in structs_to_comp):
293 out += PrintStructComparisonForwardDecl(s)
294 for s in (x for x in self.all_structures if x.name in structs_to_comp):
295 out += PrintStructComparison(s)
296 for s in (x for x in self.all_structures if x.name in struct_short_versions_to_gen):
297 out += PrintStructShort(s)
299 gen.write(out, file=self.outFile)
301 gen.OutputGenerator.endFile(self)
303 def genCmd(self, cmd, name, alias):
304 gen.OutputGenerator.genCmd(self, cmd, name, alias)
306 # These are actually constants
307 def genEnum(self, enuminfo, name, alias):
308 gen.OutputGenerator.genEnum(self, enuminfo, name, alias)
310 # These are actually enums
311 def genGroup(self, groupinfo, groupName, alias):
312 gen.OutputGenerator.genGroup(self, groupinfo, groupName, alias)
314 if alias is not None:
315 if alias in self.aliases.keys():
316 self.aliases[alias].append(groupName)
318 self.aliases[alias] = [groupName, ]
321 if groupinfo.elem.get('type') == 'bitmask':
322 self.bitmasks.append(VulkanBitmask(groupinfo.elem))
323 elif groupinfo.elem.get('type') == 'enum':
324 self.enums.append(VulkanEnum(groupinfo.elem))
326 def genType(self, typeinfo, name, alias):
327 gen.OutputGenerator.genType(self, typeinfo, name, alias)
329 if alias is not None:
330 if alias in self.aliases.keys():
331 self.aliases[alias].append(name)
333 self.aliases[alias] = [name, ]
336 if typeinfo.elem.get('category') == 'bitmask':
337 self.flags.append(VulkanFlags(typeinfo.elem))
339 if typeinfo.elem.get('category') == 'struct':
340 self.all_structures.append(VulkanStructure(
341 name, typeinfo.elem, self.constants, self.extTypes))
343 for vendor in self.vendor_abbreviations:
344 for node in typeinfo.elem.findall('member'):
345 if(node.get('values') is not None):
346 if(node.get('values').find(vendor)) != -1:
349 for key, value in EXTENSION_CATEGORIES.items():
350 if typeinfo.elem.get('structextends') == value.get('extends'):
351 self.extension_sets[key].add(name)
354 def GatherTypesToGen(structure_list, structures):
356 added_stuff = True # repeat until no new types are added
357 while added_stuff == True:
359 for s in (x for x in structure_list if x.name in structures):
362 if len(types) != size:
365 if m.typeID not in predefined_types and m.name not in ['sType', 'pNext']:
367 types = sorted(types)
371 def GetExtension(name, generator):
372 if name in generator.extFuncs:
373 return generator.extFuncs[name]
374 elif name in generator.extTypes:
375 return generator.extTypes[name]
380 def AddGuardHeader(obj):
381 if obj is not None and obj.guard is not None:
382 return "#ifdef {}\n".format(obj.guard)
387 def AddGuardFooter(obj):
388 if obj is not None and obj.guard is not None:
389 return "#endif // {}\n".format(obj.guard)
394 def PrintEnumToString(enum, gen):
396 out += AddGuardHeader(GetExtension(enum.name, gen))
398 out += "static const char *" + enum.name + \
399 "String(" + enum.name + " value) {\n"
400 out += " switch (value) {\n"
401 for v in enum.options:
402 out += " case (" + str(v.value) + \
403 "): return \"" + v.name[3:] + "\";\n"
404 out += " default: return \"UNKNOWN_" + enum.name + "\";\n"
406 out += AddGuardFooter(GetExtension(enum.name, gen))
410 def PrintEnum(enum, gen):
412 out += AddGuardHeader(GetExtension(enum.name, gen))
413 out += "void Dump" + enum.name + \
414 "(Printer &p, std::string name, " + \
415 enum.name + " value, int width = 0) {\n"
416 out += " if (p.Type() == OutputType::json) {\n"
417 out += " p.PrintKeyValue(name, value, width);\n"
419 out += " p.PrintKeyString(name, " + \
420 enum.name + "String(value), width);\n }\n"
422 out += AddGuardFooter(GetExtension(enum.name, gen))
426 def PrintGetFlagStrings(name, bitmask):
428 out += "std::vector<const char *>" + name + \
429 "GetStrings(" + name + " value) {\n"
431 out += " std::vector<const char *> strings;\n"
432 out += " if (value == 0) strings.push_back(\"None\");\n"
433 for v in bitmask.options:
434 val = v.value if isinstance(v.value, str) else str(hex(v.value))
435 out += " if (" + val + " & value) strings.push_back(\"" + \
436 str(v.name[3:]) + "\");\n"
437 out += " return strings;\n}\n"
441 def PrintFlags(bitmask, name):
442 out = "void Dump" + name + \
443 "(Printer &p, std::string name, " + name + " value, int width = 0) {\n"
444 out += " if (p.Type() == OutputType::json) { p.PrintKeyValue(name, value); return; }\n"
445 out += " auto strings = " + bitmask.name + \
446 "GetStrings(static_cast<" + bitmask.name + ">(value));\n"
447 out += " if (static_cast<" + bitmask.name + ">(value) == 0) {\n"
448 out += " ArrayWrapper arr(p, name, 0);\n"
449 out += " p.SetAsType().PrintString(\"None\");\n"
452 out += " ArrayWrapper arr(p, name, strings.size());\n"
453 out += " for(auto& str : strings){\n"
454 out += " p.SetAsType().PrintString(str);\n"
460 def PrintFlagBits(bitmask):
461 out = "void Dump" + bitmask.name + \
462 "(Printer &p, std::string name, " + \
463 bitmask.name + " value, int width = 0) {\n"
464 out += " auto strings = " + bitmask.name + "GetStrings(value);\n"
465 out += " p.PrintKeyString(name, strings.at(0), width);\n"
470 def PrintBitMask(bitmask, name, gen):
471 out = PrintGetFlagStrings(bitmask.name, bitmask)
472 out += AddGuardHeader(GetExtension(bitmask.name, gen))
473 out += PrintFlags(bitmask, name)
474 out += PrintFlagBits(bitmask)
475 out += AddGuardFooter(GetExtension(bitmask.name, gen))
480 def PrintBitMaskToString(bitmask, name, gen):
481 out = AddGuardHeader(GetExtension(bitmask.name, gen))
482 out += "std::string " + name + \
483 "String(" + name + " value, int width = 0) {\n"
484 out += " std::string out;\n"
485 out += " bool is_first = true;\n"
486 for v in bitmask.options:
487 out += " if (" + str(v.value) + " & value) {\n"
488 out += " if (is_first) { is_first = false; } else { out += \" | \"; }\n"
489 out += " out += \"" + \
490 str(v.name).strip("VK_").strip("_BIT") + "\";\n"
492 out += " return out;\n"
494 out += AddGuardFooter(GetExtension(bitmask.name, gen))
498 def PrintStructure(struct, types_to_gen, structure_names):
499 if len(struct.members) == 0:
502 out += AddGuardHeader(struct)
504 for v in struct.members:
505 if v.arrayLength is not None:
506 if len(v.name) + len(v.arrayLength) + 2 > max_key_len:
507 max_key_len = len(v.name) + len(v.arrayLength) + 2
508 elif v.typeID in predefined_types or v.typeID in struct_blacklist:
509 if len(v.name) > max_key_len:
510 max_key_len = len(v.name)
512 out += "void Dump" + struct.name + \
513 "(Printer &p, std::string name, " + struct.name + " &obj) {\n"
514 if struct.name == "VkPhysicalDeviceLimits":
515 out += " if (p.Type() == OutputType::json)\n"
516 out += " p.ObjectStart(\"limits\");\n"
518 out += " p.SetSubHeader().ObjectStart(name);\n"
519 elif struct.name == "VkPhysicalDeviceSparseProperties":
520 out += " if (p.Type() == OutputType::json)\n"
521 out += " p.ObjectStart(\"sparseProperties\");\n"
523 out += " p.SetSubHeader().ObjectStart(name);\n"
525 out += " ObjectWrapper object{p, name};\n"
527 for v in struct.members:
529 if v.arrayLength is not None:
531 if v.typeID == "char":
532 out += " p.PrintKeyString(\"" + v.name + "\", obj." + \
533 v.name + ", " + str(max_key_len) + ");\n"
535 elif (v.arrayLength == str(16) and v.typeID == "uint8_t"): # VK_UUID_SIZE
536 out += " p.PrintKeyString(\"" + v.name + "\", to_string_16(obj." + \
537 v.name + "), " + str(max_key_len) + ");\n"
538 elif (v.arrayLength == str(8) and v.typeID == "uint8_t"): # VK_LUID_SIZE
539 out += " if (obj.deviceLUIDValid)" # special case
540 out += " p.PrintKeyString(\"" + v.name + "\", to_string_8(obj." + \
541 v.name + "), " + str(max_key_len) + ");\n"
542 elif v.arrayLength.isdigit():
543 out += " { ArrayWrapper arr(p,\"" + v.name + \
544 "\", "+v.arrayLength+");\n"
545 for i in range(0, int(v.arrayLength)):
546 out += " p.PrintElement(obj." + \
547 v.name + "[" + str(i) + "]);\n"
549 else: # dynamic array length based on other member
550 out += " ArrayWrapper arr(p,\"" + v.name + \
551 "\", obj."+v.arrayLength+");\n"
552 out += " for (uint32_t i = 0; i < obj." + \
553 v.arrayLength+"; i++) {\n"
554 if v.typeID in types_to_gen:
555 out += " if (obj." + v.name + " != nullptr) {\n"
556 out += " p.SetElementIndex(i);\n"
557 out += " Dump" + v.typeID + \
558 "(p, \"" + v.name + "\", obj." + v.name + "[i]);\n"
561 out += " p.PrintElement(obj." + v.name + "[i]);\n"
563 elif v.typeID == "VkBool32":
564 out += " p.PrintKeyBool(\"" + v.name + "\", static_cast<bool>(obj." + \
565 v.name + "), " + str(max_key_len) + ");\n"
566 elif v.typeID == "VkConformanceVersion":
567 out += " DumpVkConformanceVersion(p, \"conformanceVersion\", obj." + \
568 v.name + ", " + str(max_key_len) + ");\n"
569 elif v.typeID == "VkDeviceSize":
570 out += " p.PrintKeyValue(\"" + v.name + "\", to_hex_str(p, obj." + \
571 v.name + "), " + str(max_key_len) + ");\n"
572 elif v.typeID in predefined_types:
573 out += " p.PrintKeyValue(\"" + v.name + "\", obj." + \
574 v.name + ", " + str(max_key_len) + ");\n"
575 elif v.name not in ['sType', 'pNext']:
576 # if it is an enum/flag/bitmask, add the calculated width
577 if v.typeID not in structure_names:
578 out += " Dump" + v.typeID + \
579 "(p, \"" + v.name + "\", obj." + \
580 v.name + ", " + str(max_key_len) + ");\n"
582 out += " Dump" + v.typeID + \
583 "(p, \"" + v.name + "\", obj." + v.name + ");\n"
584 if struct.name in ["VkPhysicalDeviceLimits", "VkPhysicalDeviceSparseProperties"]:
585 out += " p.ObjectEnd();\n"
588 out += AddGuardFooter(struct)
592 def PrintStructShort(struct):
594 out += AddGuardHeader(struct)
595 out += "std::ostream &operator<<(std::ostream &o, " + \
596 struct.name + " &obj) {\n"
597 out += " return o << \"(\" << "
600 for v in struct.members:
603 out += "obj." + v.name + " << "
605 out += "\',\' << obj." + v.name + " << "
608 out += AddGuardFooter(struct)
612 def PrintChainBuilders(listName, structures, all_structures):
613 sorted_structures = sorted(
614 all_structures, key=operator.attrgetter('name'))
617 out += " infos." + listName + " = {\n"
618 for s in sorted_structures:
619 if s.name in structures:
620 out += AddGuardHeader(s)
621 if s.sTypeName is not None:
622 out += " {" + s.sTypeName + \
623 ", sizeof(" + s.name + ")},\n"
624 out += AddGuardFooter(s)
629 def PrintChainIterator(listName, structures, all_structures, checkExtLoc, extTypes, aliases, versions):
631 out += "void chain_iterator_" + listName + "(Printer &p, "
632 if checkExtLoc == "device":
634 elif checkExtLoc == "instance":
635 out += "AppInstance &inst"
636 elif checkExtLoc == "both":
637 out += "AppInstance &inst, AppGpu &gpu"
638 out += ", void * place, VulkanVersion version) {\n"
640 out += " while (place) {\n"
641 out += " struct VkStructureHeader *structure = (struct VkStructureHeader *)place;\n"
642 out += " p.SetSubHeader();\n"
643 sorted_structures = sorted(
644 all_structures, key=operator.attrgetter('name'))
645 for s in sorted_structures:
646 if s.sTypeName is None:
651 for k, e in extTypes.items():
652 if k == s.name or (s.name in aliases.keys() and k in aliases[s.name]):
653 if e.extNameStr is not None:
654 extNameStr = e.extNameStr
655 if e.type is not None:
659 oldVersionName = None
661 if s.name in v.names:
662 version = v.minorVersion
663 if s.name in aliases.keys():
664 for alias in aliases[s.name]:
665 oldVersionName = alias
667 if s.name in structures:
668 out += AddGuardHeader(s)
669 out += " if (structure->sType == " + s.sTypeName
670 has_version = version is not None
671 has_extNameStr = extNameStr is not None or s.name in aliases.keys()
673 if has_version or has_extNameStr:
676 if extType == "device":
677 out += "gpu.CheckPhysicalDeviceExtensionIncluded(" + \
679 elif extType == "instance":
680 out += "inst.CheckExtensionEnabled(" + extNameStr + ")"
681 if has_version and extType is not None:
684 out += "version.minor >= " + str(version)
687 out += " " + s.name + "* props = " + \
688 "("+s.name+"*)structure;\n"
690 out += " Dump" + s.name + "(p, "
691 if s.name in aliases.keys() and version is not None:
692 out += "version.minor >= " + version + " ?\"" + \
693 s.name + "\":\"" + oldVersionName + "\""
695 out += "\"" + s.name + "\""
696 out += ", *props);\n"
697 out += " p.AddNewline();\n"
699 out += AddGuardFooter(s)
700 out += " place = structure->pNext;\n"
705 def PrintStructComparisonForwardDecl(structure):
707 out += "bool operator==(const " + structure.name + \
708 " & a, const " + structure.name + " b);\n"
712 def PrintStructComparison(structure):
714 out += "bool operator==(const " + structure.name + \
715 " & a, const " + structure.name + " b) {\n"
718 for m in structure.members:
719 if m.name not in ['sType', 'pNext']:
724 out += "a." + m.name + " == b." + m.name
733 def __init__(self, name, value, bitpos, comment):
735 self.comment = comment
737 if value == 0 or value is None:
738 value = 1 << int(bitpos)
744 'optName': self.name,
745 'optValue': self.value,
746 'optComment': self.comment,
749 def __init__(self, rootNode):
750 self.name = rootNode.get('name')
751 self.type = rootNode.get('type')
754 for child in rootNode:
755 childName = child.get('name')
756 childValue = child.get('value')
757 childBitpos = child.get('bitpos')
758 childComment = child.get('comment')
759 childExtends = child.get('extends')
760 childOffset = child.get('offset')
761 childExtNum = child.get('extnumber')
762 support = child.get('supported')
763 if(support == "disabled"):
766 if childName is None:
768 if (childValue is None and childBitpos is None and childOffset is None):
771 if childExtends is not None and childExtNum is not None and childOffset is not None:
773 extNum = int(childExtNum)
774 extOffset = int(childOffset)
777 childValue = extBase + (extNum - 1) * extBlockSize + extOffset
778 if ('dir' in child.keys()):
779 childValue = -childValue
781 for o in self.options:
782 if o.values()['optName'] == childName:
787 self.options.append(VulkanEnum.Option(
788 childName, childValue, childBitpos, childComment))
793 def __init__(self, rootNode):
794 self.name = rootNode.get('name')
795 self.type = rootNode.get('type')
797 # Read each value that the enum contains
799 for child in rootNode:
800 childName = child.get('name')
801 childValue = child.get('value')
802 childBitpos = child.get('bitpos')
803 childComment = child.get('comment')
804 support = child.get('supported')
805 if childName is None or (childValue is None and childBitpos is None):
807 if(support == "disabled"):
811 for option in self.options:
812 if option.name == childName:
817 self.options.append(VulkanEnum.Option(
818 childName, childValue, childBitpos, childComment))
823 def __init__(self, rootNode):
824 self.name = rootNode.get('name')
825 self.type = rootNode.get('type')
826 self.enum = rootNode.get('requires')
829 class VulkanVariable:
830 def __init__(self, rootNode, constants, parentName):
831 self.name = rootNode.find('name').text
832 # Typename, dereferenced and converted to a useable C++ token
833 self.typeID = rootNode.find('type').text
834 self.baseType = self.typeID
835 self.childType = None
836 self.arrayLength = None
839 for node in rootNode.itertext():
840 comment = rootNode.find('comment')
841 if comment is not None and comment.text == node:
845 typeMatch = re.search('.+?(?=' + self.name + ')', self.text)
846 self.type = typeMatch.string[typeMatch.start():typeMatch.end()]
847 self.type = ' '.join(self.type.split())
848 bracketMatch = re.search('(?<=\\[)[a-zA-Z0-9_]+(?=\\])', self.text)
849 if bracketMatch is not None:
850 matchText = bracketMatch.string[bracketMatch.start(
851 ):bracketMatch.end()]
852 self.childType = self.type
853 self.type += '[' + matchText + ']'
854 if matchText in constants:
855 self.arrayLength = constants[matchText]
857 self.arrayLength = matchText
859 self.lengthMember = False
860 lengthString = rootNode.get('len')
862 if lengthString is not None:
863 lengths = re.split(',', lengthString)
864 lengths = list(filter(('null-terminated').__ne__, lengths))
865 assert(len(lengths) <= 1)
866 if self.arrayLength is None and len(lengths) > 0:
867 self.childType = '*'.join(self.type.split('*')[0:-1])
868 self.arrayLength = lengths[0]
869 self.lengthMember = True
870 if self.arrayLength is not None and self.arrayLength.startswith('latexmath'):
871 code = self.arrayLength[10:len(self.arrayLength)]
872 code = re.sub('\\[', '', code)
873 code = re.sub('\\]', '', code)
874 code = re.sub('\\\\(lceil|rceil)', '', code)
875 code = re.sub('{|}', '', code)
876 code = re.sub('\\\\mathit', '', code)
877 code = re.sub('\\\\over', '/', code)
878 code = re.sub('\\\\textrm', '', code)
879 self.arrayLength = code
881 # Dereference if necessary and handle members of variables
882 if self.arrayLength is not None:
883 self.arrayLength = re.sub('::', '->', self.arrayLength)
884 sections = self.arrayLength.split('->')
885 if sections[-1][0] == 'p' and sections[0][1].isupper():
886 self.arrayLength = '*' + self.arrayLength
889 class VulkanStructure:
890 def __init__(self, name, rootNode, constants, extTypes):
894 self.sTypeName = None
895 self.extendsStruct = rootNode.get('structextends')
897 for node in rootNode.findall('member'):
898 if(node.get('values') is not None):
899 self.sTypeName = node.get('values')
900 self.members.append(VulkanVariable(
901 node, constants, self.name))
903 for k, e in extTypes.items():
905 if e.guard is not None:
909 class VulkanExtension:
910 def __init__(self, rootNode):
911 self.name = rootNode.get('name')
912 self.number = int(rootNode.get('number'))
913 self.type = rootNode.get('type')
914 self.dependency = rootNode.get('requires')
915 self.guard = GetFeatureProtect(rootNode)
916 self.supported = rootNode.get('supported')
917 self.extNameStr = None
920 self.constants = OrderedDict()
921 self.enumValues = OrderedDict()
925 promotedto = rootNode.get('promotedto')
926 if promotedto != None:
927 # get last char of VK_VERSION_1_1 or VK_VERSION_1_2
928 minorVersion = promotedto[-1:]
929 if minorVersion.isdigit():
930 self.version = minorVersion
932 for req in rootNode.findall('require'):
933 for ty in req.findall('type'):
934 self.vktypes.append(ty.get('name'))
936 for func in req.findall('command'):
937 self.vkfuncs.append(func.get('name'))
939 for enum in req.findall('enum'):
940 base = enum.get('extends')
941 name = enum.get('name')
942 value = enum.get('value')
943 bitpos = enum.get('bitpos')
944 offset = enum.get('offset')
945 # gets the VK_XXX_EXTENSION_NAME string
946 if value == "\"" + self.name + "\"":
947 self.extNameStr = name
949 if value is None and bitpos is not None:
950 value = 1 << int(bitpos)
952 if offset is not None:
954 if base is not None and offset is not None:
955 enumValue = 1000000000 + 1000*(self.number - 1) + offset
956 if enum.get('dir') == '-':
957 enumValue = -enumValue
958 self.enumValues[base] = (name, enumValue)
960 self.constants[name] = value
964 def __init__(self, rootNode):
965 self.name = rootNode.get('name')
966 version_str = rootNode.get('number').split('.')
967 self.majorVersion = version_str[0]
968 self.minorVersion = version_str[1]
971 for req in rootNode.findall('require'):
972 for ty in req.findall('type'):
973 self.names.add(ty.get('name'))
974 for func in req.findall('command'):
975 self.names.add(func.get('name'))
976 for enum in req.findall('enum'):
977 self.names.add(enum.get('name'))
978 self.names = sorted(self.names)