diff options
Diffstat (limited to 'extern/openxr/src/loader/loader_core.cpp')
-rw-r--r-- | extern/openxr/src/loader/loader_core.cpp | 650 |
1 files changed, 650 insertions, 0 deletions
diff --git a/extern/openxr/src/loader/loader_core.cpp b/extern/openxr/src/loader/loader_core.cpp new file mode 100644 index 00000000000..50866740a5c --- /dev/null +++ b/extern/openxr/src/loader/loader_core.cpp @@ -0,0 +1,650 @@ +// Copyright (c) 2017-2019 The Khronos Group Inc. +// Copyright (c) 2017-2019 Valve Corporation +// Copyright (c) 2017-2019 LunarG, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Author: Mark Young <marky@lunarg.com> +// + +#ifdef XR_OS_WINDOWS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "api_layer_interface.hpp" +#include "exception_handling.hpp" +#include "hex_and_handles.h" +#include "loader_instance.hpp" +#include "loader_logger_recorders.hpp" +#include "loader_logger.hpp" +#include "loader_platform.hpp" +#include "runtime_interface.hpp" +#include "xr_generated_dispatch_table.h" +#include "xr_generated_loader.hpp" + +#include <openxr/openxr.h> + +#include <cstring> +#include <memory> +#include <mutex> +#include <sstream> +#include <string> +#include <utility> +#include <vector> + +// Flag to cause the one time to init to only occur one time. +std::once_flag g_one_time_init_flag; + +// Global lock to prevent reading JSON manifest files at the same time. +static std::mutex g_loader_json_mutex; + +// Global lock to prevent simultaneous instance creation/destruction +static std::mutex g_loader_instance_mutex; + +// Utility template function meant to validate if a fixed size string contains +// a null-terminator. +template <size_t max_length> +inline bool IsMissingNullTerminator(const char (&str)[max_length]) { + for (size_t index = 0; index < max_length; ++index) { + if (str[index] == '\0') { + return false; + } + } + return true; +} + +extern "C" { + +// ---- Core 1.0 manual loader trampoline functions + +LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput, + uint32_t *propertyCountOutput, + XrApiLayerProperties *properties) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrEnumerateApiLayerProperties", "Entering loader trampoline"); + + // Make sure only one thread is attempting to read the JSON files at a time. + std::unique_lock<std::mutex> json_lock(g_loader_json_mutex); + + XrResult result = ApiLayerInterface::GetApiLayerProperties("xrEnumerateApiLayerProperties", propertyCapacityInput, + propertyCountOutput, properties); + if (XR_SUCCESS != result) { + LoaderLogger::LogErrorMessage("xrEnumerateApiLayerProperties", "Failed ApiLayerInterface::GetApiLayerProperties"); + } + + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL +xrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput, + XrExtensionProperties *properties) XRLOADER_ABI_TRY { + bool just_layer_properties = false; + LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Entering loader trampoline"); + + if (nullptr != layerName && 0 != strlen(layerName)) { + // Application is only interested in layer's properties, not all of them. + just_layer_properties = true; + } + + std::vector<XrExtensionProperties> extension_properties = {}; + XrResult result; + + { + // Make sure only one thread is attempting to read the JSON files at a time. + std::unique_lock<std::mutex> json_lock(g_loader_json_mutex); + + // Get the layer extension properties + result = ApiLayerInterface::GetInstanceExtensionProperties("xrEnumerateInstanceExtensionProperties", layerName, + extension_properties); + if (XR_SUCCESS == result && !just_layer_properties) { + // If not specific to a layer, get the runtime extension properties + result = RuntimeInterface::LoadRuntime("xrEnumerateInstanceExtensionProperties"); + if (XR_SUCCESS == result) { + RuntimeInterface::GetRuntime().GetInstanceExtensionProperties(extension_properties); + RuntimeInterface::UnloadRuntime("xrEnumerateInstanceExtensionProperties"); + } else { + LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties", + "Failed to find default runtime with RuntimeInterface::LoadRuntime()"); + } + } + } + + if (XR_SUCCESS != result) { + LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties", "Failed querying extension properties"); + return result; + } + + // If this is not in reference to a specific layer, then add the loader-specific extension properties as well. + // These are extensions that the loader directly supports. + if (!just_layer_properties) { + auto loader_extension_props = LoaderInstance::LoaderSpecificExtensions(); + for (XrExtensionProperties &loader_prop : loader_extension_props) { + bool found_prop = false; + for (XrExtensionProperties &existing_prop : extension_properties) { + if (0 == strcmp(existing_prop.extensionName, loader_prop.extensionName)) { + found_prop = true; + // Use the loader version if it is newer + if (existing_prop.extensionVersion < loader_prop.extensionVersion) { + existing_prop.extensionVersion = loader_prop.extensionVersion; + } + break; + } + } + // Only add extensions not supported by the loader + if (!found_prop) { + extension_properties.push_back(loader_prop); + } + } + } + + auto num_extension_properties = static_cast<uint32_t>(extension_properties.size()); + if (propertyCapacityInput == 0) { + if (nullptr == propertyCountOutput) { + return XR_ERROR_VALIDATION_FAILURE; + } + *propertyCountOutput = num_extension_properties; + } else if (nullptr != properties) { + if (propertyCapacityInput < num_extension_properties) { + *propertyCountOutput = num_extension_properties; + LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter", + "xrEnumerateInstanceExtensionProperties", "insufficient space in array"); + return XR_ERROR_SIZE_INSUFFICIENT; + } + + uint32_t num_to_copy = num_extension_properties; + // Determine how many extension properties we can copy over + if (propertyCapacityInput < num_to_copy) { + num_to_copy = propertyCapacityInput; + } + bool properties_valid = true; + for (uint32_t prop = 0; prop < propertyCapacityInput && prop < extension_properties.size(); ++prop) { + if (XR_TYPE_EXTENSION_PROPERTIES != properties[prop].type) { + properties_valid = false; + LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-type-type", + "xrEnumerateInstanceExtensionProperties", "unknown type in properties"); + } + if (nullptr != properties[prop].next) { + LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-next-next", + "xrEnumerateInstanceExtensionProperties", "expected NULL"); + properties_valid = false; + } + if (properties_valid) { + properties[prop] = extension_properties[prop]; + } + } + if (!properties_valid) { + LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-properties-parameter", + "xrEnumerateInstanceExtensionProperties", "invalid properties"); + return XR_ERROR_VALIDATION_FAILURE; + } + if (nullptr != propertyCountOutput) { + *propertyCountOutput = num_to_copy; + } + } + LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Completed loader trampoline"); + return XR_SUCCESS; +} +XRLOADER_ABI_CATCH_FALLBACK + +LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *info, + XrInstance *instance) XRLOADER_ABI_TRY { + bool runtime_loaded = false; + + LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader trampoline"); + if (nullptr == info) { + LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance", "must be non-NULL"); + return XR_ERROR_VALIDATION_FAILURE; + } + // If application requested OpenXR API version is higher than the loader version, then we need to throw + // an error. + uint16_t app_major = XR_VERSION_MAJOR(info->applicationInfo.apiVersion); // NOLINT + uint16_t app_minor = XR_VERSION_MINOR(info->applicationInfo.apiVersion); // NOLINT + uint16_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION); // NOLINT + uint16_t loader_minor = XR_VERSION_MINOR(XR_CURRENT_API_VERSION); // NOLINT + if (app_major > loader_major || (app_major == loader_major && app_minor > loader_minor)) { + std::ostringstream oss; + oss << "xrCreateInstance called with invalid API version " << app_major << "." << app_minor + << ". Max supported version is " << loader_major << "." << loader_minor; + LoaderLogger::LogErrorMessage("xrCreateInstance", oss.str()); + return XR_ERROR_API_VERSION_UNSUPPORTED; + } + + if (nullptr == instance) { + LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-instance-parameter", "xrCreateInstance", "must be non-NULL"); + return XR_ERROR_VALIDATION_FAILURE; + } + + std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces; + + // Make sure only one thread is attempting to read the JSON files and use the instance. + XrResult result; + { + std::unique_lock<std::mutex> json_lock(g_loader_json_mutex); + // Load the available runtime + result = RuntimeInterface::LoadRuntime("xrCreateInstance"); + if (XR_SUCCESS != result) { + LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading runtime information"); + } else { + runtime_loaded = true; + // Load the appropriate layers + result = ApiLayerInterface::LoadApiLayers("xrCreateInstance", info->enabledApiLayerCount, info->enabledApiLayerNames, + api_layer_interfaces); + if (XR_SUCCESS != result) { + LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading layer information"); + } + } + } + + if (XR_FAILED(result)) { + if (runtime_loaded) { + RuntimeInterface::UnloadRuntime("xrCreateInstance"); + } + return result; + } + + std::unique_lock<std::mutex> instance_lock(g_loader_instance_mutex); + + // Create the loader instance (only send down first runtime interface) + XrInstance created_instance = XR_NULL_HANDLE; + result = LoaderInstance::CreateInstance(std::move(api_layer_interfaces), info, &created_instance); + + if (XR_SUCCEEDED(result)) { + *instance = created_instance; + + LoaderInstance *loader_instance = g_instance_map.Get(created_instance); + + // Create a debug utils messenger if the create structure is in the "next" chain + const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next); + const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr; + while (next_header != nullptr) { + if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) { + LoaderLogger::LogInfoMessage("xrCreateInstance", "Found XrDebugUtilsMessengerCreateInfoEXT in \'next\' chain."); + dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header); + XrDebugUtilsMessengerEXT messenger; + result = xrCreateDebugUtilsMessengerEXT(*instance, dbg_utils_create_info, &messenger); + if (XR_SUCCESS != result) { + return XR_ERROR_VALIDATION_FAILURE; + } + loader_instance->SetDefaultDebugUtilsMessenger(messenger); + break; + } + next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next); + } + } + + LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader trampoline"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader trampoline"); + // Runtimes may detect XR_NULL_HANDLE provided as a required handle parameter and return XR_ERROR_HANDLE_INVALID. - 2.9 + if (XR_NULL_HANDLE == instance) { + return XR_ERROR_HANDLE_INVALID; + } + + LoaderInstance *const loader_instance = g_instance_map.Get(instance); + if (loader_instance == nullptr) { + LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyInstance-instance-parameter", "xrDestroyInstance", + "invalid instance"); + return XR_ERROR_HANDLE_INVALID; + } + + const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + + // If we allocated a default debug utils messenger, free it + XrDebugUtilsMessengerEXT messenger = loader_instance->DefaultDebugUtilsMessenger(); + if (messenger != XR_NULL_HANDLE) { + xrDestroyDebugUtilsMessengerEXT(messenger); + } + + // Now destroy the instance + if (XR_SUCCESS != dispatch_table->DestroyInstance(instance)) { + LoaderLogger::LogErrorMessage("xrDestroyInstance", "Unknown error occurred calling down chain"); + } + + // Cleanup any map entries that may still be using this instance + LoaderCleanUpMapsForInstance(loader_instance); + + // Lock the instance create/destroy mutex + std::unique_lock<std::mutex> loader_instance_lock(g_loader_instance_mutex); + delete loader_instance; + LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader trampoline"); + + // Finally, unload the runtime if necessary + RuntimeInterface::UnloadRuntime("xrDestroyInstance"); + + return XR_SUCCESS; +} +XRLOADER_ABI_CATCH_FALLBACK + +// ---- Core 1.0 manual loader terminator functions + +// Validate that the applicationInfo structure in the XrInstanceCreateInfo is valid. +static XrResult ValidateApplicationInfo(LoaderInstance *loader_instance, const XrApplicationInfo &info) { + if (IsMissingNullTerminator<XR_MAX_APPLICATION_NAME_SIZE>(info.applicationName)) { + LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-applicationName-parameter", "xrCreateInstance", + "application name missing NULL terminator."); + return XR_ERROR_NAME_INVALID; + } + if (IsMissingNullTerminator<XR_MAX_ENGINE_NAME_SIZE>(info.engineName)) { + LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-engineName-parameter", "xrCreateInstance", + "engine name missing NULL terminator."); + return XR_ERROR_NAME_INVALID; + } + if (strlen(info.applicationName) == 0) { + LoaderLogger::LogErrorMessage("xrCreateInstance", + "VUID-XrApplicationInfo-engineName-parameter: application name can not be empty."); + return XR_ERROR_NAME_INVALID; + } + return XR_SUCCESS; +} + +// Validate that the XrInstanceCreateInfo is valid +static XrResult ValidateInstanceCreateInfo(LoaderInstance *loader_instance, const XrInstanceCreateInfo *info) { + // Should have a valid 'type' + if (XR_TYPE_INSTANCE_CREATE_INFO != info->type) { + LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-type-type", "xrCreateInstance", + "expected XR_TYPE_INSTANCE_CREATE_INFO."); + return XR_ERROR_VALIDATION_FAILURE; + } + // Flags must be 0 + if (0 != info->createFlags) { + LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-createFlags-zerobitmask", "xrCreateInstance", + "flags must be 0."); + return XR_ERROR_VALIDATION_FAILURE; + } + // ApplicationInfo struct must be valid + XrResult result = ValidateApplicationInfo(loader_instance, info->applicationInfo); + if (XR_SUCCESS != result) { + LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-applicationInfo-parameter", "xrCreateInstance", + "info->applicationInfo is not valid."); + return result; + } + // VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter already tested in LoadApiLayers() + if ((info->enabledExtensionCount != 0u) && nullptr == info->enabledExtensionNames) { + LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter", "xrCreateInstance", + "enabledExtensionCount is non-0 but array is NULL"); + return XR_ERROR_VALIDATION_FAILURE; + } + return XR_SUCCESS; +} + +XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *info, XrInstance *instance) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader terminator"); + LoaderInstance *loader_instance = reinterpret_cast<LoaderInstance *>(*instance); + XrResult result = ValidateInstanceCreateInfo(loader_instance, info); + if (XR_SUCCESS != result) { + LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance", + "something wrong with XrInstanceCreateInfo contents"); + return result; + } + result = RuntimeInterface::GetRuntime().CreateInstance(info, instance); + loader_instance->SetRuntimeInstance(*instance); + LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader terminator"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *info, + const struct XrApiLayerCreateInfo * /*apiLayerInfo*/, + XrInstance *instance) { + return LoaderXrTermCreateInstance(info, instance); +} + +XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY { + XrResult result; + LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader terminator"); + result = RuntimeInterface::GetRuntime().DestroyInstance(instance); + LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader terminator"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +// ---- Extension manual loader trampoline functions + +XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(XrInstance instance, + const XrDebugUtilsMessengerCreateInfoEXT *createInfo, + XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader trampoline"); + + LoaderInstance *loader_instance = g_instance_map.Get(instance); + if (loader_instance == nullptr) { + LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-instance-parameter", + "xrCreateDebugUtilsMessengerEXT", "invalid instance"); + return XR_ERROR_HANDLE_INVALID; + } + + if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + std::string error_str = "The "; + error_str += XR_EXT_DEBUG_UTILS_EXTENSION_NAME; + error_str += " extension has not been enabled prior to calling xrCreateDebugUtilsMessengerEXT"; + LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-extension-notenabled", + "xrCreateDebugUtilsMessengerEXT", error_str); + return XR_ERROR_FUNCTION_UNSUPPORTED; + } + + const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + XrResult result = XR_SUCCESS; + result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger); + if (XR_SUCCESS == result && nullptr != messenger) { + result = g_debugutilsmessengerext_map.Insert(*messenger, *loader_instance); + if (XR_FAILED(result)) { + LoaderLogger::LogErrorMessage("xrCreateDebugUtilsMessengerEXT", + "Failed inserting new messenger into map: may be null or not unique"); + return result; + } + } + LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader trampoline"); + return result; +} +XRLOADER_ABI_CATCH_BAD_ALLOC_OOM XRLOADER_ABI_CATCH_FALLBACK + + XRAPI_ATTR XrResult XRAPI_CALL + xrDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY { + // TODO: get instance from messenger in loader + // Also, is the loader really doing all this every call? + LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader trampoline"); + + if (XR_NULL_HANDLE == messenger) { + return XR_SUCCESS; + } + + LoaderInstance *loader_instance = g_debugutilsmessengerext_map.Get(messenger); + if (loader_instance == nullptr) { + LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyDebugUtilsMessengerEXT-messenger-parameter", + "xrDestroyDebugUtilsMessengerEXT", "invalid messenger"); + + return XR_ERROR_HANDLE_INVALID; + } + + if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + std::string error_str = "The "; + error_str += XR_EXT_DEBUG_UTILS_EXTENSION_NAME; + error_str += " extension has not been enabled prior to calling xrDestroyDebugUtilsMessengerEXT"; + LoaderLogger::LogValidationErrorMessage("VUID-xrDestroyDebugUtilsMessengerEXT-extension-notenabled", + "xrDestroyDebugUtilsMessengerEXT", error_str); + return XR_ERROR_FUNCTION_UNSUPPORTED; + } + + const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + XrResult result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger); + LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader trampoline"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +// ---- Extension manual loader terminator functions + +XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance instance, + const XrDebugUtilsMessengerCreateInfoEXT *createInfo, + XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader terminator"); + if (nullptr == messenger) { + LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-messenger-parameter", + "xrCreateDebugUtilsMessengerEXT", "invalid messenger pointer"); + return XR_ERROR_VALIDATION_FAILURE; + } + const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance); + XrResult result = XR_SUCCESS; + // This extension is supported entirely by the loader which means the runtime may or may not support it. + if (nullptr != dispatch_table->CreateDebugUtilsMessengerEXT) { + result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger); + } else { + // Just allocate a character so we have a unique value + char *temp_mess_ptr = new char; + *messenger = reinterpret_cast<XrDebugUtilsMessengerEXT>(temp_mess_ptr); + } + if (XR_SUCCESS == result) { + LoaderLogger::GetInstance().AddLogRecorder(MakeDebugUtilsLoaderLogRecorder(createInfo, *messenger)); + RuntimeInterface::GetRuntime().TrackDebugMessenger(instance, *messenger); + } + LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader terminator"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader terminator"); + const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger); + XrResult result = XR_SUCCESS; + LoaderLogger::GetInstance().RemoveLogRecorder(MakeHandleGeneric(messenger)); + RuntimeInterface::GetRuntime().ForgetDebugMessenger(messenger); + // This extension is supported entirely by the loader which means the runtime may or may not support it. + if (nullptr != dispatch_table->DestroyDebugUtilsMessengerEXT) { + result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger); + } else { + // Delete the character we would've created + delete (reinterpret_cast<char *>(MakeHandleGeneric(messenger))); + } + LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader terminator"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT( + XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes, + const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Entering loader terminator"); + const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance); + XrResult result = XR_SUCCESS; + if (nullptr != dispatch_table->SubmitDebugUtilsMessageEXT) { + result = dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData); + } else { + // Only log the message from the loader if the runtime doesn't support this extension. If we did, + // then the user would receive multiple instances of the same message. + LoaderLogger::GetInstance().LogDebugUtilsMessage(messageSeverity, messageTypes, callbackData); + } + LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Completed loader terminator"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +XRAPI_ATTR XrResult XRAPI_CALL +LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY { + LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Entering loader terminator"); + const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance); + XrResult result = XR_SUCCESS; + if (nullptr != dispatch_table->SetDebugUtilsObjectNameEXT) { + result = dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo); + } + LoaderLogger::GetInstance().AddObjectName(nameInfo->objectHandle, nameInfo->objectType, nameInfo->objectName); + LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Completed loader terminator"); + return result; +} +XRLOADER_ABI_CATCH_FALLBACK + +XRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(XrSession session, + const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY { + LoaderInstance *loader_instance = g_session_map.Get(session); + if (nullptr == loader_instance) { + LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-session-parameter", + "xrSessionBeginDebugUtilsLabelRegionEXT", "session is not a valid XrSession", + {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}}); + return XR_ERROR_HANDLE_INVALID; + } + if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + LoaderLogger::LogValidationErrorMessage("TBD", "xrSessionBeginDebugUtilsLabelRegionEXT", + "Extension entrypoint called without enabling appropriate extension", + {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}}); + return XR_ERROR_FUNCTION_UNSUPPORTED; + } + if (nullptr == labelInfo) { + LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter", + "xrSessionBeginDebugUtilsLabelRegionEXT", "labelInfo must be non-NULL", + {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}}); + return XR_ERROR_VALIDATION_FAILURE; + } + + LoaderLogger::GetInstance().BeginLabelRegion(session, labelInfo); + const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) { + return dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo); + } + return XR_SUCCESS; +} +XRLOADER_ABI_CATCH_FALLBACK + +XRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(XrSession session) XRLOADER_ABI_TRY { + LoaderInstance *loader_instance = g_session_map.Get(session); + if (nullptr == loader_instance) { + LoaderLogger::LogValidationErrorMessage("VUID-xrSessionEndDebugUtilsLabelRegionEXT-session-parameter", + "xrSessionEndDebugUtilsLabelRegionEXT", "session is not a valid XrSession", + {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}}); + return XR_ERROR_HANDLE_INVALID; + } + if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + return XR_ERROR_FUNCTION_UNSUPPORTED; + } + LoaderLogger::GetInstance().EndLabelRegion(session); + const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) { + return dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session); + } + return XR_SUCCESS; +} +XRLOADER_ABI_CATCH_FALLBACK + +XRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(XrSession session, + const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY { + LoaderInstance *loader_instance = g_session_map.Get(session); + if (nullptr == loader_instance) { + LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-session-parameter", + "xrSessionInsertDebugUtilsLabelEXT", "session is not a valid XrSession", + {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}}); + return XR_ERROR_HANDLE_INVALID; + } + if (!loader_instance->ExtensionIsEnabled(XR_EXT_DEBUG_UTILS_EXTENSION_NAME)) { + LoaderLogger::LogValidationErrorMessage("TBD", "xrSessionInsertDebugUtilsLabelEXT", + "Extension entrypoint called without enabling appropriate extension", + {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}}); + return XR_ERROR_FUNCTION_UNSUPPORTED; + } + if (nullptr == labelInfo) { + LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter", + "xrSessionInsertDebugUtilsLabelEXT", "labelInfo must be non-NULL", + {XrLoaderLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}}); + return XR_ERROR_VALIDATION_FAILURE; + } + + LoaderLogger::GetInstance().InsertLabel(session, labelInfo); + const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable(); + if (nullptr != dispatch_table->SessionInsertDebugUtilsLabelEXT) { + return dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo); + } + return XR_SUCCESS; +} +XRLOADER_ABI_CATCH_FALLBACK + +} // extern "C" |