scripts: Defer unique_objects processing
Codegen created wrap/unwrap code on the fly as commands were processed
by the XML. Deferred codegen until all the data was complete and
collected.
Change-Id: I295ab59ad5dd24a5321e348cb18f96f2d0eed824
diff --git a/scripts/unique_objects_generator.py b/scripts/unique_objects_generator.py
index 1773c3b..855292e 100644
--- a/scripts/unique_objects_generator.py
+++ b/scripts/unique_objects_generator.py
@@ -163,8 +163,14 @@
self.headerVersion = None
# Internal state - accumulators for different inner block text
self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
- self.structMembers = [] # List of StructMemberData records for all Vulkan structs
+ self.cmdMembers = []
+ self.cmd_feature_protect = [] # Save ifdef's for each command
+ self.cmd_info_data = [] # Save the cmdinfo data for wrapping the handles when processing is complete
+ self.structMembers = [] # List of StructMemberData records for all Vulkan structs
# Named tuples to store struct and command data
+ self.CmdMemberData = namedtuple('CmdMemberData', ['name', 'members'])
+ self.CmdInfoData = namedtuple('CmdInfoData', ['name', 'cmdinfo'])
+ self.CmdExtraProtect = namedtuple('CmdExtraProtect', ['name', 'extra_protect'])
self.CommandParam = namedtuple('CommandParam', ['type', 'name', 'ispointer', 'isconst', 'iscount', 'len', 'extstructs', 'cdecl', 'islocal', 'iscreate', 'isdestroy'])
self.StructMemberData = namedtuple('StructMemberData', ['name', 'members'])
#
@@ -198,6 +204,26 @@
write('namespace unique_objects {', file = self.outFile)
#
def endFile(self):
+
+ # Write out wrapping/unwrapping functions
+ self.WrapCommands()
+
+ # Actually write the interface to the output file.
+ if (self.emit):
+ self.newline()
+ if (self.featureExtraProtect != None):
+ write('#ifdef', self.featureExtraProtect, file=self.outFile)
+ # Write the unique_objects code to the file
+ if (self.sections['command']):
+ if (self.genOpts.protectProto):
+ write(self.genOpts.protectProto,
+ self.genOpts.protectProtoStr, file=self.outFile)
+ write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
+ if (self.featureExtraProtect != None):
+ write('\n#endif //', self.featureExtraProtect, file=self.outFile)
+ else:
+ self.newline()
+
# Write out device extension white list
self.newline()
write('// Layer Device Extension Whitelist', file=self.outFile)
@@ -229,9 +255,7 @@
# Start processing in superclass
OutputGenerator.beginFeature(self, interface, emit)
self.headerVersion = None
- self.sections = dict([(section, []) for section in self.ALL_SECTIONS])
- self.cmdMembers = []
- self.CmdMemberData = namedtuple('CmdMemberData', ['name', 'members'])
+
if self.featureName != 'VK_VERSION_1_0':
white_list_entry = []
if (self.featureExtraProtect != None):
@@ -246,21 +270,6 @@
self.device_extensions += white_list_entry
#
def endFeature(self):
- # Actually write the interface to the output file.
- if (self.emit):
- self.newline()
- if (self.featureExtraProtect != None):
- write('#ifdef', self.featureExtraProtect, file=self.outFile)
- # Write the unique_objects code to the file
- if (self.sections['command']):
- if (self.genOpts.protectProto):
- write(self.genOpts.protectProto,
- self.genOpts.protectProtoStr, file=self.outFile)
- write('\n'.join(self.sections['command']), end=u'', file=self.outFile)
- if (self.featureExtraProtect != None):
- write('\n#endif //', self.featureExtraProtect, file=self.outFile)
- else:
- self.newline()
# Finish processing in superclass
OutputGenerator.endFeature(self)
#
@@ -526,7 +535,7 @@
post_call_code += '%sdelete[] local_%s;\n' % (indent, ndo_name)
else:
if top_level == True:
- if (destroy_func == False) or (destroy_array == True): #### LUGMAL This line needs to be skipped for destroy_ndo and not destroy_array
+ if (destroy_func == False) or (destroy_array == True):
pre_call_code += '%s %s = (%s)dev_data->unique_id_mapping[reinterpret_cast<uint64_t &>(%s)];\n' % (indent, ndo_name, ndo_type, ndo_name)
else:
# Make temp copy of this var with the 'local' removed. It may be better to not pass in 'local_'
@@ -660,15 +669,7 @@
#
# Capture command parameter info needed to wrap NDOs as well as handling some boilerplate code
def genCmd(self, cmdinfo, cmdname):
- if cmdname in self.interface_functions:
- return
- if cmdname in self.no_autogen_list:
- decls = self.makeCDecls(cmdinfo.elem)
- self.appendSection('command', '')
- self.appendSection('command', '// Declare only')
- self.appendSection('command', decls[0])
- self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (cmdname,cmdname[2:]) ]
- return
+
# Add struct-member type information to command parameter information
OutputGenerator.genCmd(self, cmdinfo, cmdname)
members = cmdinfo.elem.findall('.//param')
@@ -717,63 +718,87 @@
iscreate=iscreate,
isdestroy=isdestroy))
self.cmdMembers.append(self.CmdMemberData(name=cmdname, members=membersInfo))
- # Generate NDO wrapping/unwrapping code for all parameters
- (api_decls, api_pre, api_post) = self.generate_wrapping_code(cmdinfo.elem)
- # If API doesn't contain an NDO's, don't fool with it
- if not api_decls and not api_pre and not api_post:
- return
- # Record that the function will be intercepted
- if (self.featureExtraProtect != None):
- self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
- self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (cmdname,cmdname[2:]) ]
- if (self.featureExtraProtect != None):
- self.intercepts += [ '#endif' ]
- decls = self.makeCDecls(cmdinfo.elem)
- self.appendSection('command', '')
- self.appendSection('command', decls[0][:-1])
- self.appendSection('command', '{')
- # Setup common to call wrappers, first parameter is always dispatchable
- dispatchable_type = cmdinfo.elem.find('param/type').text
- dispatchable_name = cmdinfo.elem.find('param/name').text
- # Generate local instance/pdev/device data lookup
- self.appendSection('command', ' layer_data *dev_data = GetLayerDataPtr(get_dispatch_key('+dispatchable_name+'), layer_data_map);')
- # Handle return values, if any
- resulttype = cmdinfo.elem.find('proto/type')
- if (resulttype != None and resulttype.text == 'void'):
- resulttype = None
- if (resulttype != None):
- assignresult = resulttype.text + ' result = '
- else:
- assignresult = ''
- # Pre-pend declarations and pre-api-call codegen
- if api_decls:
- self.appendSection('command', "\n".join(str(api_decls).rstrip().split("\n")))
- if api_pre:
- self.appendSection('command', "\n".join(str(api_pre).rstrip().split("\n")))
- # Generate the API call itself
- # Gather the parameter items
- params = cmdinfo.elem.findall('param/name')
- # Pull out the text for each of the parameters, separate them by commas in a list
- paramstext = ', '.join([str(param.text) for param in params])
- # If any of these paramters has been replaced by a local var, fix up the list
+ self.cmd_info_data.append(self.CmdInfoData(name=cmdname, cmdinfo=cmdinfo))
+ self.cmd_feature_protect.append(self.CmdExtraProtect(name=cmdname, extra_protect=self.featureExtraProtect))
+ #
+ # Create code to wrap NDOs as well as handling some boilerplate code
+ def WrapCommands(self):
cmd_member_dict = dict(self.cmdMembers)
- params = cmd_member_dict[cmdname]
- for param in params:
- if param.islocal == True:
- if param.ispointer == True:
- paramstext = paramstext.replace(param.name, '(%s %s*)local_%s' % ('const', param.type, param.name))
- else:
- paramstext = paramstext.replace(param.name, '(%s %s)local_%s' % ('const', param.type, param.name))
- # Use correct dispatch table
- if dispatchable_type in ["VkPhysicalDevice", "VkInstance"]:
- API = cmdinfo.elem.attrib.get('name').replace('vk','dev_data->instance_dispatch_table->',1)
- else:
- API = cmdinfo.elem.attrib.get('name').replace('vk','dev_data->device_dispatch_table->',1)
- # Put all this together for the final down-chain call
- self.appendSection('command', ' ' + assignresult + API + '(' + paramstext + ');')
- # And add the post-API-call codegen
- self.appendSection('command', "\n".join(str(api_post).rstrip().split("\n")))
- # Handle the return result variable, if any
- if (resulttype != None):
- self.appendSection('command', ' return result;')
- self.appendSection('command', '}')
+ cmd_info_dict = dict(self.cmd_info_data)
+ cmd_protect_dict = dict(self.cmd_feature_protect)
+
+ for api_call in self.cmdMembers:
+ cmdname = api_call.name
+ cmdinfo = cmd_info_dict[api_call.name]
+ if cmdname in self.interface_functions:
+ continue
+ if cmdname in self.no_autogen_list:
+ decls = self.makeCDecls(cmdinfo.elem)
+ self.appendSection('command', '')
+ self.appendSection('command', '// Declare only')
+ self.appendSection('command', decls[0])
+ self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (cmdname,cmdname[2:]) ]
+ continue
+ # Generate NDO wrapping/unwrapping code for all parameters
+ (api_decls, api_pre, api_post) = self.generate_wrapping_code(cmdinfo.elem)
+ # If API doesn't contain an NDO's, don't fool with it
+ if not api_decls and not api_pre and not api_post:
+ continue
+ feature_extra_protect = cmd_protect_dict[api_call.name]
+ if (feature_extra_protect != None):
+ self.appendSection('command', '')
+ self.appendSection('command', '#ifdef '+ feature_extra_protect)
+ self.intercepts += [ '#ifdef %s' % feature_extra_protect ]
+ # Add intercept to procmap
+ self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (cmdname,cmdname[2:]) ]
+ decls = self.makeCDecls(cmdinfo.elem)
+ self.appendSection('command', '')
+ self.appendSection('command', decls[0][:-1])
+ self.appendSection('command', '{')
+ # Setup common to call wrappers, first parameter is always dispatchable
+ dispatchable_type = cmdinfo.elem.find('param/type').text
+ dispatchable_name = cmdinfo.elem.find('param/name').text
+ # Generate local instance/pdev/device data lookup
+ self.appendSection('command', ' layer_data *dev_data = GetLayerDataPtr(get_dispatch_key('+dispatchable_name+'), layer_data_map);')
+ # Handle return values, if any
+ resulttype = cmdinfo.elem.find('proto/type')
+ if (resulttype != None and resulttype.text == 'void'):
+ resulttype = None
+ if (resulttype != None):
+ assignresult = resulttype.text + ' result = '
+ else:
+ assignresult = ''
+ # Pre-pend declarations and pre-api-call codegen
+ if api_decls:
+ self.appendSection('command', "\n".join(str(api_decls).rstrip().split("\n")))
+ if api_pre:
+ self.appendSection('command', "\n".join(str(api_pre).rstrip().split("\n")))
+ # Generate the API call itself
+ # Gather the parameter items
+ params = cmdinfo.elem.findall('param/name')
+ # Pull out the text for each of the parameters, separate them by commas in a list
+ paramstext = ', '.join([str(param.text) for param in params])
+ # If any of these paramters has been replaced by a local var, fix up the list
+ params = cmd_member_dict[cmdname]
+ for param in params:
+ if param.islocal == True:
+ if param.ispointer == True:
+ paramstext = paramstext.replace(param.name, '(%s %s*)local_%s' % ('const', param.type, param.name))
+ else:
+ paramstext = paramstext.replace(param.name, '(%s %s)local_%s' % ('const', param.type, param.name))
+ # Use correct dispatch table
+ if dispatchable_type in ["VkPhysicalDevice", "VkInstance"]:
+ API = cmdinfo.elem.attrib.get('name').replace('vk','dev_data->instance_dispatch_table->',1)
+ else:
+ API = cmdinfo.elem.attrib.get('name').replace('vk','dev_data->device_dispatch_table->',1)
+ # Put all this together for the final down-chain call
+ self.appendSection('command', ' ' + assignresult + API + '(' + paramstext + ');')
+ # And add the post-API-call codegen
+ self.appendSection('command', "\n".join(str(api_post).rstrip().split("\n")))
+ # Handle the return result variable, if any
+ if (resulttype != None):
+ self.appendSection('command', ' return result;')
+ self.appendSection('command', '}')
+ if (feature_extra_protect != None):
+ self.appendSection('command', '#endif // '+ feature_extra_protect)
+ self.intercepts += [ '#endif' ]