def outputLoaderMapDefines(self): map_defines = '// Unordered maps to lookup the instance for a given object type\n' for handle in self.api_handles: base_handle_name = undecorate(handle.name) if handle.protect_value: map_defines += '#if %s\n' % handle.protect_string map_defines += 'HandleLoaderMap<%s> g_%s_map;\n' % ( handle.name, base_handle_name) if handle.protect_value: map_defines += '#endif // %s\n' % handle.protect_string map_defines += '\n' map_defines += '// Function used to clean up any residual map values that point to an instance prior to that\n' map_defines += '// instance being deleted.\n' map_defines += 'void LoaderCleanUpMapsForInstance(LoaderInstance *instance) {\n' for handle in self.api_handles: if handle.protect_value: map_defines += '#if %s\n' % handle.protect_string base_handle_name = undecorate(handle.name) map_defines += ' g_%s_map.RemoveHandlesForLoader(*instance);\n' % base_handle_name if handle.protect_value: map_defines += '#endif // %s\n' % handle.protect_string map_defines += '}\n\n' return map_defines
def outputLoaderGeneratedFuncs(self): generated_funcs = '\n// Automatically generated instance trampolines and terminators\n' for cur_cmd in self.core_commands: if cur_cmd.name in MANUAL_LOADER_FUNCS: continue # Remove 'xr' from proto name base_name = cur_cmd.name[2:] has_return = False if cur_cmd.is_create_connect or cur_cmd.is_destroy_disconnect: has_return = True elif cur_cmd.return_type is not None: has_return = True tramp_variable_defines = '' tramp_param_replace = [] base_handle_name = '' for count, param in enumerate(cur_cmd.params): param_cdecl = param.cdecl is_const = False const_check = param_cdecl.strip() if const_check[:5].lower() == "const": is_const = True pointer_count = self.paramPointerCount( param.cdecl, param.type, param.name) array_dimen = self.paramArrayDimension( param.cdecl, param.type, param.name) static_array_sizes = [] if param.is_static_array: static_array_sizes = param.static_array_sizes cmd_tramp_param_name = param.name cmd_tramp_is_handle = param.is_handle if count == 0: if param.is_handle: base_handle_name = undecorate(param.type) first_handle_name = self.getFirstHandleName(param) tramp_variable_defines += ' LoaderInstance* loader_instance;\n' tramp_variable_defines += ' XrResult result = ActiveLoaderInstance::Get(&loader_instance, "%s");\n' % (cur_cmd.name) tramp_variable_defines += ' if (XR_SUCCEEDED(result)) {\n' # These should be mutually exclusive - verify it. assert((not cur_cmd.is_destroy_disconnect) or (pointer_count == 0)) else: tramp_variable_defines += self.printCodeGenErrorMessage( 'Command %s does not have an OpenXR Object handle as the first parameter.' % cur_cmd.name) tramp_param_replace.append( self.MemberOrParam(type=param.type, name=cmd_tramp_param_name, is_const=is_const, is_handle=cmd_tramp_is_handle, is_bool=param.is_bool, is_optional=param.is_optional, no_auto_validity=param.no_auto_validity, is_array=param.is_array, is_static_array=param.is_static_array, static_array_sizes=static_array_sizes, array_dimen=array_dimen, array_count_var=param.array_count_var, array_length_for=param.array_length_for, pointer_count=pointer_count, pointer_count_var=param.pointer_count_var, is_null_terminated=param.is_null_terminated, valid_extension_structs=None, cdecl=param.cdecl, values=param.values)) count = count + 1 if cur_cmd.protect_value: generated_funcs += '#if %s\n' % cur_cmd.protect_string decl = self.getProto(cur_cmd).replace(";", " XRLOADER_ABI_TRY {\n") generated_funcs += decl generated_funcs += tramp_variable_defines if has_return: generated_funcs += ' result = ' else: generated_funcs += ' ' generated_funcs += 'loader_instance->DispatchTable()->' generated_funcs += base_name generated_funcs += '(' count = 0 for param in tramp_param_replace: if count > 0: generated_funcs += ', ' generated_funcs += param.name count = count + 1 generated_funcs += ');\n' generated_funcs += ' }\n' if has_return: generated_funcs += ' return result;\n' generated_funcs += '}\nXRLOADER_ABI_CATCH_FALLBACK\n' if cur_cmd.protect_value: generated_funcs += '#endif // %s\n' % cur_cmd.protect_string generated_funcs += '\n' return generated_funcs
def outputLoaderGeneratedFuncs(self): cur_extension_name = '' generated_funcs = '\n// Automatically generated instance trampolines and terminators\n' count = 0 for x in range(0, 2): if x == 0: commands = self.core_commands else: commands = self.ext_commands for cur_cmd in commands: if cur_cmd.ext_name != cur_extension_name: if self.isCoreExtensionName(cur_cmd.ext_name): generated_funcs += '\n// ---- Core %s commands\n' % cur_cmd.ext_name[11:].replace( "_", ".") else: generated_funcs += '\n// ---- %s extension commands\n' % cur_cmd.ext_name cur_extension_name = cur_cmd.ext_name if cur_cmd.name in MANUAL_LOADER_FUNCS: continue # Remove 'xr' from proto name base_name = cur_cmd.name[2:] just_return_call = False has_return = False if cur_cmd.is_create_connect or cur_cmd.is_destroy_disconnect: has_return = True elif cur_cmd.return_type is not None: has_return = True just_return_call = True tramp_variable_defines = '' tramp_param_replace = [] func_follow_up = '' base_handle_name = '' for count, param in enumerate(cur_cmd.params): param_cdecl = param.cdecl is_const = False const_check = param_cdecl.strip() if const_check[:5].lower() == "const": is_const = True pointer_count = self.paramPointerCount( param.cdecl, param.type, param.name) array_dimen = self.paramArrayDimension( param.cdecl, param.type, param.name) static_array_sizes = [] if param.is_static_array: static_array_sizes = param.static_array_sizes cmd_tramp_param_name = param.name cmd_tramp_is_handle = param.is_handle if count == 0: if param.is_handle: base_handle_name = undecorate(param.type) first_handle_name = self.getFirstHandleName(param) if pointer_count == 1 and param.pointer_count_var is not None: if not param.is_optional: # Check we have at least 1 in the array. tramp_variable_defines += ' if (0 == %s) {\n' % param.pointer_count_var tramp_variable_defines += generateErrorMessage( 3, [cur_cmd.name, param.pointer_count_var, 'parameter'], cur_cmd, '"%s is 0, but %s is not optional"' % (param.pointer_count_var, param.name), [(first_handle_name, self.genXrObjectType(param.type))] ) tramp_variable_defines += ' }\n' tramp_variable_defines += ' LoaderInstance *loader_instance = g_%s_map.Get(%s);\n' % ( base_handle_name, first_handle_name) if cur_cmd.is_destroy_disconnect: tramp_variable_defines += ' // Destroy the mapping entry for this item if it was valid.\n' tramp_variable_defines += ' if (nullptr != loader_instance) {\n' tramp_variable_defines += ' g_%s_map.Erase(%s);\n' % ( base_handle_name, first_handle_name) tramp_variable_defines += ' }\n' # These should be mutually exclusive - verify it. assert((not cur_cmd.is_destroy_disconnect) or (pointer_count == 0)) if pointer_count == 1: # NOTE - @ 10-June-2019 this stanza is never exercised in loader code-gen. Consider whether necessary. DJH tramp_variable_defines += ' for (uint32_t i = 1; i < %s; ++i) {\n' % param.pointer_count_var tramp_variable_defines += ' LoaderInstance *elt_loader_instance = g_%s_map.Get(%s[i]);\n' % ( base_handle_name, param.name) tramp_variable_defines += ' if (elt_loader_instance == nullptr || elt_loader_instance != loader_instance) {\n' tramp_variable_defines += ' auto elt_name = "%s[" + std::to_string(i) + "]";\n' % param.name tramp_variable_defines += ' if (elt_loader_instance == nullptr) {\n' tramp_variable_defines += generateErrorMessage( ' ', [cur_cmd.name, param.name, 'parameter'], cur_cmd, 'elt_name + " is not a valid %s"' % (param.name), [(first_handle_name + '[i]', self.genXrObjectType(param.type))] ) tramp_variable_defines += ' } else {\n' tramp_variable_defines += generateErrorMessage( ' ', [cur_cmd.name, param.name, 'parameter'], cur_cmd, '"%s[" + std::to_string(i) + "] belongs to a different instance than %s[0]"' % (param.name, param.name), [(first_handle_name + '[i]', self.genXrObjectType(param.type))] ) tramp_variable_defines += ' }\n' if has_return: tramp_variable_defines += ' return XR_ERROR_HANDLE_INVALID;\n' tramp_variable_defines += ' }\n' tramp_variable_defines += ' }\n' tramp_variable_defines += ' if (nullptr == loader_instance) {\n' tramp_variable_defines += generateErrorMessage( ' ', [cur_cmd.name, param.name, 'parameter'], cur_cmd, '"%s is not a valid %s"' % (first_handle_name, param.type), [(first_handle_name, self.genXrObjectType(param.type))] ) if has_return: tramp_variable_defines += ' return XR_ERROR_HANDLE_INVALID;\n' tramp_variable_defines += ' }\n' else: tramp_variable_defines += self.printCodeGenErrorMessage( 'Command %s does not have an OpenXR Object handle as the first parameter.' % cur_cmd.name) tramp_variable_defines += ' const std::unique_ptr<XrGeneratedDispatchTable>& dispatch_table = loader_instance->DispatchTable();\n' tramp_param_replace.append( self.MemberOrParam(type=param.type, name=cmd_tramp_param_name, is_const=is_const, is_handle=cmd_tramp_is_handle, is_bool=param.is_bool, is_optional=param.is_optional, no_auto_validity=param.no_auto_validity, is_array=param.is_array, is_static_array=param.is_static_array, static_array_sizes=static_array_sizes, array_dimen=array_dimen, array_count_var=param.array_count_var, array_length_for=param.array_length_for, pointer_count=pointer_count, pointer_count_var=param.pointer_count_var, is_null_terminated=param.is_null_terminated, valid_extension_structs=None, cdecl=param.cdecl, values=param.values)) if count == len(cur_cmd.params) - 1: if param.is_handle: base_handle_name = undecorate(param.type) if cur_cmd.is_create_connect: func_follow_up += ' if (XR_SUCCESS == result && nullptr != %s) {\n' % param.name func_follow_up += ' XrResult insert_result = g_%s_map.Insert(*%s, *loader_instance);\n' % ( base_handle_name, param.name) func_follow_up += ' if (XR_FAILED(insert_result)) {\n' func_follow_up += ' LoaderLogger::LogErrorMessage(\n' func_follow_up += ' "%s",\n' % cur_cmd.name func_follow_up += ' "Failed inserting new %s into map: may be null or not unique");\n' % base_handle_name func_follow_up += ' }\n' func_follow_up += ' }\n' count = count + 1 if has_return and not just_return_call: return_prefix = ' ' return_prefix += cur_cmd.return_type.text return_prefix += ' result' if cur_cmd.return_type.text == 'XrResult': return_prefix += ' = XR_SUCCESS;\n' else: return_prefix += ';\n' tramp_variable_defines += return_prefix if cur_cmd.protect_value: generated_funcs += '#if %s\n' % cur_cmd.protect_string decl = self.getProto(cur_cmd).replace(";", " XRLOADER_ABI_TRY {\n") generated_funcs += decl generated_funcs += tramp_variable_defines # If this is not core, but an extension, check to make sure the extension is enabled. if x == 1: generated_funcs += ' if (!loader_instance->ExtensionIsEnabled("%s")) {\n' % ( cur_cmd.ext_name) generated_funcs += ' LoaderLogger::LogValidationErrorMessage("VUID-%s-extension-notenabled",\n' % cur_cmd.name generated_funcs += ' "%s",\n' % cur_cmd.name generated_funcs += ' "The %s extension has not been enabled prior to calling %s");\n' % ( cur_cmd.ext_name, cur_cmd.name) if has_return: generated_funcs += ' return XR_ERROR_FUNCTION_UNSUPPORTED;\n' else: generated_funcs += ' return;\n' generated_funcs += ' }\n\n' if has_return: if just_return_call: generated_funcs += ' return ' else: generated_funcs += ' result = ' else: generated_funcs += ' ' generated_funcs += 'dispatch_table->' generated_funcs += base_name generated_funcs += '(' count = 0 for param in tramp_param_replace: if count > 0: generated_funcs += ', ' generated_funcs += param.name count = count + 1 generated_funcs += ');\n' generated_funcs += func_follow_up if has_return and not just_return_call: generated_funcs += ' return result;\n' generated_funcs += '}\nXRLOADER_ABI_CATCH_FALLBACK\n\n' # If this is a function that needs a terminator, provide the call to it, not the runtime. # Only a few items need a terminator. Usually something we want to be able to return information # to the API layers and act as an interceptor prior to the runtime. if cur_cmd.name in NEEDS_TERMINATOR: # Not currently used. raise NotImplementedError term_decl = cur_cmd.cdecl.replace(";", " {\n") term_decl = term_decl.replace(" xr", " LoaderGenTermXr") generated_funcs += term_decl loader_override_func = False if cur_cmd.ext_name in EXTENSIONS_LOADER_IMPLEMENTS or loader_override_func: generated_funcs += ' if (nullptr != dispatch_table->%s) {\n' % base_name if has_return: if just_return_call: generated_funcs += ' return ' else: generated_funcs += ' result = ' else: generated_funcs += ' ' generated_funcs += 'dispatch_table->' generated_funcs += base_name generated_funcs += '(' count = 0 for param in cur_cmd.params: if count > 0: generated_funcs += ', ' generated_funcs += param.name count = count + 1 generated_funcs += ');\n' if cur_cmd.ext_name in EXTENSIONS_LOADER_IMPLEMENTS or loader_override_func: generated_funcs += ' }\n' if has_return and not just_return_call: generated_funcs += ' return result;\n' generated_funcs += '}\n' if cur_cmd.protect_value: generated_funcs += '#endif // %s\n' % cur_cmd.protect_string generated_funcs += '\n' return generated_funcs