scripts: Add pnext chain routines to safe_struct
Change-Id: Id19f42ff8d731d2bd1cfd25a08b8addc61f133dc
diff --git a/scripts/helper_file_generator.py b/scripts/helper_file_generator.py
index 225c066..7893993 100644
--- a/scripts/helper_file_generator.py
+++ b/scripts/helper_file_generator.py
@@ -88,6 +88,8 @@
self.core_object_types = [] # Handy copy of core_object_type enum data
self.device_extension_info = dict() # Dict of device extension name defines and ifdef values
self.instance_extension_info = dict() # Dict of instance extension name defines and ifdef values
+ self.structextends_list = [] # List of structs which extend another struct via pNext
+
# Named tuples to store struct and command data
self.StructType = namedtuple('StructType', ['name', 'value'])
@@ -348,6 +350,7 @@
self.structTypes[typeName] = self.StructType(name=name, value=value)
# Store pointer/array/string info
isstaticarray = self.paramIsStaticArray(member)
+ structextends = False
membersInfo.append(self.CommandParam(type=type,
name=name,
ispointer=self.paramIsPointer(member),
@@ -357,6 +360,9 @@
len=self.getLen(member),
extstructs=self.registry.validextensionstructs[typeName] if name == 'pNext' else None,
cdecl=cdecl))
+ # If this struct extends another, keep its name in list for further processing
+ if typeinfo.elem.attrib.get('structextends') is not None:
+ self.structextends_list.append(typeName)
self.structMembers.append(self.StructMemberData(name=typeName, members=membersInfo, ifdef_protect=self.featureExtraProtect))
#
# Enum_string_header: Create a routine to convert an enumerated value into a string
@@ -876,6 +882,70 @@
return object_types_header
#
+ # Generate pNext handling function
+ def build_pnext_chain_processing_func(self):
+ # Construct helper functions to build and free pNext extension chains
+ build_pnext_proc = '\n\n'
+ build_pnext_proc += 'void *SafePnextCopy(const void *pNext) {\n'
+ build_pnext_proc += ' void *cur_pnext = const_cast<void *>(pNext);\n'
+ build_pnext_proc += ' void *cur_ext_struct = NULL;\n\n'
+ build_pnext_proc += ' if (cur_pnext == nullptr) {\n'
+ build_pnext_proc += ' return nullptr;\n'
+ build_pnext_proc += ' } else {\n'
+ build_pnext_proc += ' VkBaseOutStructure *header = reinterpret_cast<VkBaseOutStructure *>(cur_pnext);\n\n'
+ build_pnext_proc += ' switch (header->sType) {\n'
+
+ free_pnext_proc = '\n\n'
+ free_pnext_proc += '// Free a pNext extension chain\n'
+ free_pnext_proc += 'void FreePnextChain(void *head) {\n'
+ free_pnext_proc += ' VkBaseOutStructure *curr_ptr = reinterpret_cast<VkBaseOutStructure *>(head);\n'
+ free_pnext_proc += ' while (curr_ptr) {\n'
+ free_pnext_proc += ' VkBaseOutStructure *header = curr_ptr;\n'
+ free_pnext_proc += ' curr_ptr = reinterpret_cast<VkBaseOutStructure *>(header->pNext);\n\n'
+ free_pnext_proc += ' switch (header->sType) {\n';
+
+ for item in self.structextends_list:
+ member_index = next((i for i, v in enumerate(self.structMembers) if v[0] == item), None)
+ if member_index is None:
+ continue
+ struct_info = self.structMembers[member_index][1]
+ feature_protect = self.structMembers[member_index][2]
+
+ if feature_protect is not None:
+ build_pnext_proc += '#ifdef %s\n' % feature_protect
+ free_pnext_proc += '#ifdef %s\n' % feature_protect
+ build_pnext_proc += ' case %s: {\n' % self.structTypes[item].value
+ build_pnext_proc += ' safe_%s *safe_struct = new safe_%s;\n' % (item, item)
+ build_pnext_proc += ' safe_struct->initialize(reinterpret_cast<const %s *>(cur_pnext));\n' % item
+ build_pnext_proc += ' cur_ext_struct = reinterpret_cast<void *>(safe_struct);\n'
+ build_pnext_proc += ' } break;\n'
+
+ free_pnext_proc += ' case %s:\n' % self.structTypes[item].value
+ free_pnext_proc += ' delete reinterpret_cast<safe_%s *>(header);\n' % item
+ free_pnext_proc += ' break;\n'
+
+ if feature_protect is not None:
+ build_pnext_proc += '#endif // %s\n' % feature_protect
+ free_pnext_proc += '#endif // %s\n' % feature_protect
+ build_pnext_proc += '\n'
+ free_pnext_proc += '\n'
+
+ build_pnext_proc += ' default:\n'
+ build_pnext_proc += ' break;\n'
+ build_pnext_proc += ' }\n'
+ build_pnext_proc += ' }\n'
+ build_pnext_proc += ' return cur_ext_struct;\n'
+ build_pnext_proc += '}\n\n'
+
+ free_pnext_proc += ' default:\n'
+ free_pnext_proc += ' assert(0);\n'
+ free_pnext_proc += ' }\n'
+ free_pnext_proc += ' }\n'
+ free_pnext_proc += '}\n'
+
+ pnext_procs = build_pnext_proc + free_pnext_proc
+ return pnext_procs
+ #
# Determine if a structure needs a safe_struct helper function
# That is, it has an sType or one of its members is a pointer
def NeedSafeStruct(self, structure):
@@ -892,9 +962,12 @@
def GenerateSafeStructHelperSource(self):
safe_struct_helper_source = '\n'
safe_struct_helper_source += '#include "vk_safe_struct.h"\n'
+ safe_struct_helper_source += '#include <assert.h>\n'
safe_struct_helper_source += '#include <string.h>\n'
safe_struct_helper_source += '\n'
safe_struct_helper_source += self.GenerateSafeStructSource()
+ safe_struct_helper_source += self.build_pnext_chain_processing_func()
+
return safe_struct_helper_source
#
# safe_struct source -- create bodies of safe struct helper functions