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
Ejemplo n.º 2
0
    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