loader_core.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. // Copyright (c) 2017-2023, The Khronos Group Inc.
  2. // Copyright (c) 2017-2019 Valve Corporation
  3. // Copyright (c) 2017-2019 LunarG, Inc.
  4. //
  5. // SPDX-License-Identifier: Apache-2.0 OR MIT
  6. //
  7. // Initial Authors: Mark Young <[email protected]>, Dave Houlton <[email protected]>
  8. //
  9. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  10. #define _CRT_SECURE_NO_WARNINGS
  11. #endif // defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  12. #include "api_layer_interface.hpp"
  13. #include "exception_handling.hpp"
  14. #include "hex_and_handles.h"
  15. #include "loader_instance.hpp"
  16. #include "loader_logger_recorders.hpp"
  17. #include "loader_logger.hpp"
  18. #include "loader_platform.hpp"
  19. #include "runtime_interface.hpp"
  20. #include "xr_generated_dispatch_table_core.h"
  21. #include "xr_generated_loader.hpp"
  22. #include <openxr/openxr.h>
  23. #include <cstring>
  24. #include <memory>
  25. #include <mutex>
  26. #include <sstream>
  27. #include <string>
  28. #include <utility>
  29. #include <vector>
  30. // Global loader lock to:
  31. // 1. Ensure ActiveLoaderInstance get and set operations are done atomically.
  32. // 2. Ensure RuntimeInterface isn't used to unload the runtime while the runtime is in use.
  33. static std::mutex &GetGlobalLoaderMutex() {
  34. static std::mutex loader_mutex;
  35. return loader_mutex;
  36. }
  37. // Prototypes for the debug utils calls used internally.
  38. static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineCreateDebugUtilsMessengerEXT(
  39. XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo, XrDebugUtilsMessengerEXT *messenger);
  40. static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger);
  41. // Terminal functions needed by xrCreateInstance.
  42. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(XrInstance, const char *, PFN_xrVoidFunction *);
  43. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *, XrInstance *);
  44. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *,
  45. const struct XrApiLayerCreateInfo *, XrInstance *);
  46. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance, const XrDebugUtilsObjectNameInfoEXT *);
  47. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance,
  48. const XrDebugUtilsMessengerCreateInfoEXT *,
  49. XrDebugUtilsMessengerEXT *);
  50. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT);
  51. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
  52. XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
  53. const XrDebugUtilsMessengerCallbackDataEXT *callbackData);
  54. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrGetInstanceProcAddr(XrInstance instance, const char *name,
  55. PFN_xrVoidFunction *function);
  56. // Utility template function meant to validate if a fixed size string contains
  57. // a null-terminator.
  58. template <size_t max_length>
  59. inline bool IsMissingNullTerminator(const char (&str)[max_length]) {
  60. for (size_t index = 0; index < max_length; ++index) {
  61. if (str[index] == '\0') {
  62. return false;
  63. }
  64. }
  65. return true;
  66. }
  67. // ---- Core 1.0 manual loader trampoline functions
  68. #ifdef XR_KHR_LOADER_INIT_SUPPORT // platforms that support XR_KHR_loader_init.
  69. XRAPI_ATTR XrResult XRAPI_CALL LoaderXrInitializeLoaderKHR(const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo) XRLOADER_ABI_TRY {
  70. LoaderLogger::LogVerboseMessage("xrInitializeLoaderKHR", "Entering loader trampoline");
  71. return InitializeLoader(loaderInitInfo);
  72. }
  73. XRLOADER_ABI_CATCH_FALLBACK
  74. #endif
  75. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
  76. uint32_t *propertyCountOutput,
  77. XrApiLayerProperties *properties) XRLOADER_ABI_TRY {
  78. LoaderLogger::LogVerboseMessage("xrEnumerateApiLayerProperties", "Entering loader trampoline");
  79. // Make sure only one thread is attempting to read the JSON files at a time.
  80. std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
  81. XrResult result = ApiLayerInterface::GetApiLayerProperties("xrEnumerateApiLayerProperties", propertyCapacityInput,
  82. propertyCountOutput, properties);
  83. if (XR_FAILED(result)) {
  84. LoaderLogger::LogErrorMessage("xrEnumerateApiLayerProperties", "Failed ApiLayerInterface::GetApiLayerProperties");
  85. }
  86. return result;
  87. }
  88. XRLOADER_ABI_CATCH_FALLBACK
  89. static XRAPI_ATTR XrResult XRAPI_CALL
  90. LoaderXrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput,
  91. XrExtensionProperties *properties) XRLOADER_ABI_TRY {
  92. bool just_layer_properties = false;
  93. LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Entering loader trampoline");
  94. // "Independent of elementCapacityInput or elements parameters, elementCountOutput must be a valid pointer,
  95. // and the function sets elementCountOutput." - 2.11
  96. if (nullptr == propertyCountOutput) {
  97. return XR_ERROR_VALIDATION_FAILURE;
  98. }
  99. if (nullptr != layerName && 0 != strlen(layerName)) {
  100. // Application is only interested in layer's properties, not all of them.
  101. just_layer_properties = true;
  102. }
  103. std::vector<XrExtensionProperties> extension_properties = {};
  104. XrResult result;
  105. {
  106. // Make sure the runtime isn't unloaded while this call is in progress.
  107. std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
  108. // Get the layer extension properties
  109. result = ApiLayerInterface::GetInstanceExtensionProperties("xrEnumerateInstanceExtensionProperties", layerName,
  110. extension_properties);
  111. if (XR_SUCCEEDED(result) && !just_layer_properties) {
  112. // If not specific to a layer, get the runtime extension properties
  113. result = RuntimeInterface::LoadRuntime("xrEnumerateInstanceExtensionProperties");
  114. if (XR_SUCCEEDED(result)) {
  115. RuntimeInterface::GetRuntime().GetInstanceExtensionProperties(extension_properties);
  116. } else {
  117. LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
  118. "Failed to find default runtime with RuntimeInterface::LoadRuntime()");
  119. }
  120. }
  121. }
  122. if (XR_FAILED(result)) {
  123. LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties", "Failed querying extension properties");
  124. return result;
  125. }
  126. // If this is not in reference to a specific layer, then add the loader-specific extension properties as well.
  127. // These are extensions that the loader directly supports.
  128. if (!just_layer_properties) {
  129. for (const XrExtensionProperties &loader_prop : LoaderInstance::LoaderSpecificExtensions()) {
  130. bool found_prop = false;
  131. for (XrExtensionProperties &existing_prop : extension_properties) {
  132. if (0 == strcmp(existing_prop.extensionName, loader_prop.extensionName)) {
  133. found_prop = true;
  134. // Use the loader version if it is newer
  135. if (existing_prop.extensionVersion < loader_prop.extensionVersion) {
  136. existing_prop.extensionVersion = loader_prop.extensionVersion;
  137. }
  138. break;
  139. }
  140. }
  141. // Only add extensions not supported by the loader
  142. if (!found_prop) {
  143. extension_properties.push_back(loader_prop);
  144. }
  145. }
  146. }
  147. auto num_extension_properties = static_cast<uint32_t>(extension_properties.size());
  148. if (propertyCapacityInput == 0) {
  149. *propertyCountOutput = num_extension_properties;
  150. } else if (nullptr != properties) {
  151. if (propertyCapacityInput < num_extension_properties) {
  152. *propertyCountOutput = num_extension_properties;
  153. LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter",
  154. "xrEnumerateInstanceExtensionProperties", "insufficient space in array");
  155. return XR_ERROR_SIZE_INSUFFICIENT;
  156. }
  157. uint32_t num_to_copy = num_extension_properties;
  158. // Determine how many extension properties we can copy over
  159. if (propertyCapacityInput < num_to_copy) {
  160. num_to_copy = propertyCapacityInput;
  161. }
  162. bool properties_valid = true;
  163. for (uint32_t prop = 0; prop < propertyCapacityInput && prop < extension_properties.size(); ++prop) {
  164. if (XR_TYPE_EXTENSION_PROPERTIES != properties[prop].type) {
  165. properties_valid = false;
  166. LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-type-type",
  167. "xrEnumerateInstanceExtensionProperties", "unknown type in properties");
  168. }
  169. if (properties_valid) {
  170. properties[prop] = extension_properties[prop];
  171. }
  172. }
  173. if (!properties_valid) {
  174. LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-properties-parameter",
  175. "xrEnumerateInstanceExtensionProperties", "invalid properties");
  176. return XR_ERROR_VALIDATION_FAILURE;
  177. }
  178. if (nullptr != propertyCountOutput) {
  179. *propertyCountOutput = num_to_copy;
  180. }
  181. } else {
  182. // incoming_count is not 0 BUT the properties is NULL
  183. return XR_ERROR_VALIDATION_FAILURE;
  184. }
  185. LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Completed loader trampoline");
  186. return XR_SUCCESS;
  187. }
  188. XRLOADER_ABI_CATCH_FALLBACK
  189. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrCreateInstance(const XrInstanceCreateInfo *info,
  190. XrInstance *instance) XRLOADER_ABI_TRY {
  191. LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader trampoline");
  192. if (nullptr == info) {
  193. LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance", "must be non-NULL");
  194. return XR_ERROR_VALIDATION_FAILURE;
  195. }
  196. // If application requested OpenXR API version is higher than the loader version, then we need to throw
  197. // an error.
  198. uint16_t app_major = XR_VERSION_MAJOR(info->applicationInfo.apiVersion); // NOLINT
  199. uint16_t app_minor = XR_VERSION_MINOR(info->applicationInfo.apiVersion); // NOLINT
  200. uint16_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION); // NOLINT
  201. uint16_t loader_minor = XR_VERSION_MINOR(XR_CURRENT_API_VERSION); // NOLINT
  202. if (app_major > loader_major || (app_major == loader_major && app_minor > loader_minor)) {
  203. std::ostringstream oss;
  204. oss << "xrCreateInstance called with invalid API version " << app_major << "." << app_minor
  205. << ". Max supported version is " << loader_major << "." << loader_minor;
  206. LoaderLogger::LogErrorMessage("xrCreateInstance", oss.str());
  207. return XR_ERROR_API_VERSION_UNSUPPORTED;
  208. }
  209. if (nullptr == instance) {
  210. LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-instance-parameter", "xrCreateInstance", "must be non-NULL");
  211. return XR_ERROR_VALIDATION_FAILURE;
  212. }
  213. // Make sure the ActiveLoaderInstance::IsAvailable check is done atomically with RuntimeInterface::LoadRuntime.
  214. std::unique_lock<std::mutex> instance_lock(GetGlobalLoaderMutex());
  215. // Check if there is already an XrInstance that is alive. If so, another instance cannot be created.
  216. // The loader does not support multiple simultaneous instances because the loader is intended to be
  217. // usable by apps using future OpenXR APIs (through xrGetInstanceProcAddr). Because the loader would
  218. // not be aware of new handle types, it would not be able to look up the appropriate dispatch table
  219. // in some cases.
  220. if (ActiveLoaderInstance::IsAvailable()) { // If there is an XrInstance already alive.
  221. LoaderLogger::LogErrorMessage("xrCreateInstance", "Loader does not support simultaneous XrInstances");
  222. return XR_ERROR_LIMIT_REACHED;
  223. }
  224. std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces;
  225. XrResult result;
  226. // Make sure only one thread is attempting to read the JSON files and use the instance.
  227. {
  228. // Load the available runtime
  229. result = RuntimeInterface::LoadRuntime("xrCreateInstance");
  230. if (XR_FAILED(result)) {
  231. LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading runtime information");
  232. } else {
  233. // Load the appropriate layers
  234. result = ApiLayerInterface::LoadApiLayers("xrCreateInstance", info->enabledApiLayerCount, info->enabledApiLayerNames,
  235. api_layer_interfaces);
  236. if (XR_FAILED(result)) {
  237. LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading layer information");
  238. }
  239. }
  240. }
  241. // Create the loader instance (only send down first runtime interface)
  242. LoaderInstance *loader_instance = nullptr;
  243. if (XR_SUCCEEDED(result)) {
  244. std::unique_ptr<LoaderInstance> owned_loader_instance;
  245. result = LoaderInstance::CreateInstance(LoaderXrTermGetInstanceProcAddr, LoaderXrTermCreateInstance,
  246. LoaderXrTermCreateApiLayerInstance, std::move(api_layer_interfaces), info,
  247. &owned_loader_instance);
  248. if (XR_SUCCEEDED(result)) {
  249. loader_instance = owned_loader_instance.get();
  250. result = ActiveLoaderInstance::Set(std::move(owned_loader_instance), "xrCreateInstance");
  251. }
  252. }
  253. if (XR_SUCCEEDED(result)) {
  254. // Create a debug utils messenger if the create structure is in the "next" chain
  255. const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next);
  256. const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr;
  257. while (next_header != nullptr) {
  258. if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
  259. LoaderLogger::LogInfoMessage("xrCreateInstance", "Found XrDebugUtilsMessengerCreateInfoEXT in \'next\' chain.");
  260. dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header);
  261. XrDebugUtilsMessengerEXT messenger;
  262. result = LoaderTrampolineCreateDebugUtilsMessengerEXT(loader_instance->GetInstanceHandle(), dbg_utils_create_info,
  263. &messenger);
  264. if (XR_FAILED(result)) {
  265. return XR_ERROR_VALIDATION_FAILURE;
  266. }
  267. loader_instance->SetDefaultDebugUtilsMessenger(messenger);
  268. break;
  269. }
  270. next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next);
  271. }
  272. }
  273. if (XR_FAILED(result)) {
  274. // Ensure the global loader instance and runtime are destroyed if something went wrong.
  275. ActiveLoaderInstance::Remove();
  276. RuntimeInterface::UnloadRuntime("xrCreateInstance");
  277. LoaderLogger::LogErrorMessage("xrCreateInstance", "xrCreateInstance failed");
  278. } else {
  279. *instance = loader_instance->GetInstanceHandle();
  280. LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader trampoline");
  281. }
  282. return result;
  283. }
  284. XRLOADER_ABI_CATCH_FALLBACK
  285. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
  286. LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader trampoline");
  287. // Runtimes may detect XR_NULL_HANDLE provided as a required handle parameter and return XR_ERROR_HANDLE_INVALID. - 2.9
  288. if (XR_NULL_HANDLE == instance) {
  289. LoaderLogger::LogErrorMessage("xrDestroyInstance", "Instance handle is XR_NULL_HANDLE.");
  290. return XR_ERROR_HANDLE_INVALID;
  291. }
  292. // Make sure the runtime isn't unloaded while it is being used by xrEnumerateInstanceExtensionProperties.
  293. std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
  294. LoaderInstance *loader_instance;
  295. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyInstance");
  296. if (XR_FAILED(result)) {
  297. return result;
  298. }
  299. const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
  300. // If we allocated a default debug utils messenger, free it
  301. XrDebugUtilsMessengerEXT messenger = loader_instance->DefaultDebugUtilsMessenger();
  302. if (messenger != XR_NULL_HANDLE) {
  303. LoaderTrampolineDestroyDebugUtilsMessengerEXT(messenger);
  304. }
  305. // Now destroy the instance
  306. if (XR_FAILED(dispatch_table->DestroyInstance(instance))) {
  307. LoaderLogger::LogErrorMessage("xrDestroyInstance", "Unknown error occurred calling down chain");
  308. }
  309. // Get rid of the loader instance. This will make it possible to create another instance in the future.
  310. ActiveLoaderInstance::Remove();
  311. // Lock the instance create/destroy mutex
  312. LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader trampoline");
  313. // Finally, unload the runtime if necessary
  314. RuntimeInterface::UnloadRuntime("xrDestroyInstance");
  315. return XR_SUCCESS;
  316. }
  317. XRLOADER_ABI_CATCH_FALLBACK
  318. // ---- Core 1.0 manual loader terminator functions
  319. // Validate that the applicationInfo structure in the XrInstanceCreateInfo is valid.
  320. static XrResult ValidateApplicationInfo(const XrApplicationInfo &info) {
  321. if (IsMissingNullTerminator<XR_MAX_APPLICATION_NAME_SIZE>(info.applicationName)) {
  322. LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-applicationName-parameter", "xrCreateInstance",
  323. "application name missing NULL terminator.");
  324. return XR_ERROR_NAME_INVALID;
  325. }
  326. if (IsMissingNullTerminator<XR_MAX_ENGINE_NAME_SIZE>(info.engineName)) {
  327. LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-engineName-parameter", "xrCreateInstance",
  328. "engine name missing NULL terminator.");
  329. return XR_ERROR_NAME_INVALID;
  330. }
  331. if (strlen(info.applicationName) == 0) {
  332. LoaderLogger::LogErrorMessage("xrCreateInstance",
  333. "VUID-XrApplicationInfo-engineName-parameter: application name can not be empty.");
  334. return XR_ERROR_NAME_INVALID;
  335. }
  336. return XR_SUCCESS;
  337. }
  338. // Validate that the XrInstanceCreateInfo is valid
  339. static XrResult ValidateInstanceCreateInfo(const XrInstanceCreateInfo *info) {
  340. // Should have a valid 'type'
  341. if (XR_TYPE_INSTANCE_CREATE_INFO != info->type) {
  342. LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-type-type", "xrCreateInstance",
  343. "expected XR_TYPE_INSTANCE_CREATE_INFO.");
  344. return XR_ERROR_VALIDATION_FAILURE;
  345. }
  346. // Flags must be 0
  347. if (0 != info->createFlags) {
  348. LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-createFlags-zerobitmask", "xrCreateInstance",
  349. "flags must be 0.");
  350. return XR_ERROR_VALIDATION_FAILURE;
  351. }
  352. // ApplicationInfo struct must be valid
  353. XrResult result = ValidateApplicationInfo(info->applicationInfo);
  354. if (XR_FAILED(result)) {
  355. LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-applicationInfo-parameter", "xrCreateInstance",
  356. "info->applicationInfo is not valid.");
  357. return result;
  358. }
  359. // VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter already tested in LoadApiLayers()
  360. if ((info->enabledExtensionCount != 0u) && nullptr == info->enabledExtensionNames) {
  361. LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter", "xrCreateInstance",
  362. "enabledExtensionCount is non-0 but array is NULL");
  363. return XR_ERROR_VALIDATION_FAILURE;
  364. }
  365. return XR_SUCCESS;
  366. }
  367. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *createInfo,
  368. XrInstance *instance) XRLOADER_ABI_TRY {
  369. LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader terminator");
  370. XrResult result = ValidateInstanceCreateInfo(createInfo);
  371. if (XR_FAILED(result)) {
  372. LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance",
  373. "something wrong with XrInstanceCreateInfo contents");
  374. return result;
  375. }
  376. result = RuntimeInterface::GetRuntime().CreateInstance(createInfo, instance);
  377. LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader terminator");
  378. return result;
  379. }
  380. XRLOADER_ABI_CATCH_FALLBACK
  381. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *info,
  382. const struct XrApiLayerCreateInfo * /*apiLayerInfo*/,
  383. XrInstance *instance) {
  384. return LoaderXrTermCreateInstance(info, instance);
  385. }
  386. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
  387. LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader terminator");
  388. LoaderLogger::GetInstance().RemoveLogRecordersForXrInstance(instance);
  389. XrResult result = RuntimeInterface::GetRuntime().DestroyInstance(instance);
  390. LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader terminator");
  391. return result;
  392. }
  393. XRLOADER_ABI_CATCH_FALLBACK
  394. static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(XrInstance instance, const char *name,
  395. PFN_xrVoidFunction *function) XRLOADER_ABI_TRY {
  396. // A few instance commands need to go through a loader terminator.
  397. // Otherwise, go directly to the runtime version of the command if it exists.
  398. // But first set the function pointer to NULL so that the fall-through below actually works.
  399. *function = nullptr;
  400. // NOTE: ActiveLoaderInstance cannot be used in this function because it is called before an instance is made active.
  401. if (0 == strcmp(name, "xrGetInstanceProcAddr")) {
  402. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermGetInstanceProcAddr);
  403. } else if (0 == strcmp(name, "xrCreateInstance")) {
  404. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateInstance);
  405. } else if (0 == strcmp(name, "xrDestroyInstance")) {
  406. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyInstance);
  407. } else if (0 == strcmp(name, "xrSetDebugUtilsObjectNameEXT")) {
  408. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSetDebugUtilsObjectNameEXT);
  409. } else if (0 == strcmp(name, "xrCreateDebugUtilsMessengerEXT")) {
  410. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateDebugUtilsMessengerEXT);
  411. } else if (0 == strcmp(name, "xrDestroyDebugUtilsMessengerEXT")) {
  412. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyDebugUtilsMessengerEXT);
  413. } else if (0 == strcmp(name, "xrSubmitDebugUtilsMessageEXT")) {
  414. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSubmitDebugUtilsMessageEXT);
  415. } else if (0 == strcmp(name, "xrCreateApiLayerInstance")) {
  416. // Special layer version of xrCreateInstance terminator. If we get called this by a layer,
  417. // we simply re-direct the information back into the standard xrCreateInstance terminator.
  418. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateApiLayerInstance);
  419. }
  420. if (nullptr != *function) {
  421. return XR_SUCCESS;
  422. }
  423. return RuntimeInterface::GetInstanceProcAddr(instance, name, function);
  424. }
  425. XRLOADER_ABI_CATCH_FALLBACK
  426. // ---- Extension manual loader trampoline functions
  427. static XRAPI_ATTR XrResult XRAPI_CALL
  428. LoaderTrampolineCreateDebugUtilsMessengerEXT(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
  429. XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
  430. LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader trampoline");
  431. if (instance == XR_NULL_HANDLE) {
  432. LoaderLogger::LogErrorMessage("xrCreateDebugUtilsMessengerEXT", "Instance handle is XR_NULL_HANDLE.");
  433. return XR_ERROR_HANDLE_INVALID;
  434. }
  435. LoaderInstance *loader_instance;
  436. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateDebugUtilsMessengerEXT");
  437. if (XR_FAILED(result)) {
  438. return result;
  439. }
  440. result = loader_instance->DispatchTable()->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
  441. LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader trampoline");
  442. return result;
  443. }
  444. XRLOADER_ABI_CATCH_BAD_ALLOC_OOM XRLOADER_ABI_CATCH_FALLBACK
  445. static XRAPI_ATTR XrResult XRAPI_CALL
  446. LoaderTrampolineDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
  447. // TODO: get instance from messenger in loader
  448. // Also, is the loader really doing all this every call?
  449. LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader trampoline");
  450. if (messenger == XR_NULL_HANDLE) {
  451. LoaderLogger::LogErrorMessage("xrDestroyDebugUtilsMessengerEXT", "Messenger handle is XR_NULL_HANDLE.");
  452. return XR_ERROR_HANDLE_INVALID;
  453. }
  454. LoaderInstance *loader_instance;
  455. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyDebugUtilsMessengerEXT");
  456. if (XR_FAILED(result)) {
  457. return result;
  458. }
  459. result = loader_instance->DispatchTable()->DestroyDebugUtilsMessengerEXT(messenger);
  460. LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader trampoline");
  461. return result;
  462. }
  463. XRLOADER_ABI_CATCH_FALLBACK
  464. static XRAPI_ATTR XrResult XRAPI_CALL
  465. LoaderTrampolineSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
  466. if (session == XR_NULL_HANDLE) {
  467. LoaderLogger::LogErrorMessage("xrSessionBeginDebugUtilsLabelRegionEXT", "Session handle is XR_NULL_HANDLE.");
  468. return XR_ERROR_HANDLE_INVALID;
  469. }
  470. if (nullptr == labelInfo) {
  471. LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter",
  472. "xrSessionBeginDebugUtilsLabelRegionEXT", "labelInfo must be non-NULL",
  473. {XrSdkLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
  474. return XR_ERROR_VALIDATION_FAILURE;
  475. }
  476. LoaderInstance *loader_instance;
  477. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionBeginDebugUtilsLabelRegionEXT");
  478. if (XR_FAILED(result)) {
  479. return result;
  480. }
  481. LoaderLogger::GetInstance().BeginLabelRegion(session, labelInfo);
  482. const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
  483. if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) {
  484. return dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
  485. }
  486. return XR_SUCCESS;
  487. }
  488. XRLOADER_ABI_CATCH_FALLBACK
  489. static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineSessionEndDebugUtilsLabelRegionEXT(XrSession session) XRLOADER_ABI_TRY {
  490. if (session == XR_NULL_HANDLE) {
  491. LoaderLogger::LogErrorMessage("xrSessionEndDebugUtilsLabelRegionEXT", "Session handle is XR_NULL_HANDLE.");
  492. return XR_ERROR_HANDLE_INVALID;
  493. }
  494. LoaderInstance *loader_instance;
  495. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionEndDebugUtilsLabelRegionEXT");
  496. if (XR_FAILED(result)) {
  497. return result;
  498. }
  499. LoaderLogger::GetInstance().EndLabelRegion(session);
  500. const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
  501. if (nullptr != dispatch_table->SessionEndDebugUtilsLabelRegionEXT) {
  502. return dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session);
  503. }
  504. return XR_SUCCESS;
  505. }
  506. XRLOADER_ABI_CATCH_FALLBACK
  507. static XRAPI_ATTR XrResult XRAPI_CALL
  508. LoaderTrampolineSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
  509. if (session == XR_NULL_HANDLE) {
  510. LoaderLogger::LogErrorMessage("xrSessionInsertDebugUtilsLabelEXT", "Session handle is XR_NULL_HANDLE.");
  511. return XR_ERROR_HANDLE_INVALID;
  512. }
  513. LoaderInstance *loader_instance;
  514. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionInsertDebugUtilsLabelEXT");
  515. if (XR_FAILED(result)) {
  516. return result;
  517. }
  518. if (nullptr == labelInfo) {
  519. LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter",
  520. "xrSessionInsertDebugUtilsLabelEXT", "labelInfo must be non-NULL",
  521. {XrSdkLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
  522. return XR_ERROR_VALIDATION_FAILURE;
  523. }
  524. LoaderLogger::GetInstance().InsertLabel(session, labelInfo);
  525. const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
  526. if (nullptr != dispatch_table->SessionInsertDebugUtilsLabelEXT) {
  527. return dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo);
  528. }
  529. return XR_SUCCESS;
  530. }
  531. XRLOADER_ABI_CATCH_FALLBACK
  532. // No-op trampoline needed for xrGetInstanceProcAddr. Work done in terminator.
  533. static XRAPI_ATTR XrResult XRAPI_CALL
  534. LoaderTrampolineSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
  535. LoaderInstance *loader_instance;
  536. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSetDebugUtilsObjectNameEXT");
  537. if (XR_SUCCEEDED(result)) {
  538. result = loader_instance->DispatchTable()->SetDebugUtilsObjectNameEXT(instance, nameInfo);
  539. }
  540. return result;
  541. }
  542. XRLOADER_ABI_CATCH_FALLBACK
  543. // No-op trampoline needed for xrGetInstanceProcAddr. Work done in terminator.
  544. static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineSubmitDebugUtilsMessageEXT(
  545. XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
  546. const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
  547. LoaderInstance *loader_instance;
  548. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSubmitDebugUtilsMessageEXT");
  549. if (XR_SUCCEEDED(result)) {
  550. result =
  551. loader_instance->DispatchTable()->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
  552. }
  553. return result;
  554. }
  555. XRLOADER_ABI_CATCH_FALLBACK
  556. // ---- Extension manual loader terminator functions
  557. XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance instance,
  558. const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
  559. XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
  560. LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader terminator");
  561. if (nullptr == messenger) {
  562. LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-messenger-parameter",
  563. "xrCreateDebugUtilsMessengerEXT", "invalid messenger pointer");
  564. return XR_ERROR_VALIDATION_FAILURE;
  565. }
  566. const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
  567. XrResult result = XR_SUCCESS;
  568. // This extension is supported entirely by the loader which means the runtime may or may not support it.
  569. if (nullptr != dispatch_table->CreateDebugUtilsMessengerEXT) {
  570. result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
  571. } else {
  572. // Just allocate a character so we have a unique value
  573. char *temp_mess_ptr = new char;
  574. *messenger = reinterpret_cast<XrDebugUtilsMessengerEXT>(temp_mess_ptr);
  575. }
  576. if (XR_SUCCEEDED(result)) {
  577. LoaderLogger::GetInstance().AddLogRecorderForXrInstance(instance, MakeDebugUtilsLoaderLogRecorder(createInfo, *messenger));
  578. RuntimeInterface::GetRuntime().TrackDebugMessenger(instance, *messenger);
  579. }
  580. LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader terminator");
  581. return result;
  582. }
  583. XRLOADER_ABI_CATCH_FALLBACK
  584. XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
  585. LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader terminator");
  586. const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger);
  587. XrResult result = XR_SUCCESS;
  588. LoaderLogger::GetInstance().RemoveLogRecorder(MakeHandleGeneric(messenger));
  589. RuntimeInterface::GetRuntime().ForgetDebugMessenger(messenger);
  590. // This extension is supported entirely by the loader which means the runtime may or may not support it.
  591. if (nullptr != dispatch_table->DestroyDebugUtilsMessengerEXT) {
  592. result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
  593. } else {
  594. // Delete the character we would've created
  595. delete (reinterpret_cast<char *>(MakeHandleGeneric(messenger)));
  596. }
  597. LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader terminator");
  598. return result;
  599. }
  600. XRLOADER_ABI_CATCH_FALLBACK
  601. XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
  602. XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
  603. const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
  604. LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Entering loader terminator");
  605. const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
  606. XrResult result = XR_SUCCESS;
  607. if (nullptr != dispatch_table->SubmitDebugUtilsMessageEXT) {
  608. result = dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
  609. } else {
  610. // Only log the message from the loader if the runtime doesn't support this extension. If we did,
  611. // then the user would receive multiple instances of the same message.
  612. LoaderLogger::GetInstance().LogDebugUtilsMessage(messageSeverity, messageTypes, callbackData);
  613. }
  614. LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Completed loader terminator");
  615. return result;
  616. }
  617. XRLOADER_ABI_CATCH_FALLBACK
  618. XRAPI_ATTR XrResult XRAPI_CALL
  619. LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
  620. LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Entering loader terminator");
  621. const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
  622. XrResult result = XR_SUCCESS;
  623. if (nullptr != dispatch_table->SetDebugUtilsObjectNameEXT) {
  624. result = dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo);
  625. }
  626. LoaderLogger::GetInstance().AddObjectName(nameInfo->objectHandle, nameInfo->objectType, nameInfo->objectName);
  627. LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Completed loader terminator");
  628. return result;
  629. }
  630. XRLOADER_ABI_CATCH_FALLBACK
  631. XRAPI_ATTR XrResult XRAPI_CALL LoaderXrGetInstanceProcAddr(XrInstance instance, const char *name,
  632. PFN_xrVoidFunction *function) XRLOADER_ABI_TRY {
  633. if (nullptr == function) {
  634. LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter", "xrGetInstanceProcAddr",
  635. "Invalid Function pointer");
  636. return XR_ERROR_VALIDATION_FAILURE;
  637. }
  638. if (nullptr == name) {
  639. LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter", "xrGetInstanceProcAddr",
  640. "Invalid Name pointer");
  641. return XR_ERROR_VALIDATION_FAILURE;
  642. }
  643. // Initialize the function to nullptr in case it does not get caught in a known case
  644. *function = nullptr;
  645. LoaderInstance *loader_instance = nullptr;
  646. if (instance == XR_NULL_HANDLE) {
  647. // Null instance is allowed for a few specific API entry points, otherwise return error
  648. if (strcmp(name, "xrCreateInstance") != 0 && strcmp(name, "xrEnumerateApiLayerProperties") != 0 &&
  649. strcmp(name, "xrEnumerateInstanceExtensionProperties") != 0 && strcmp(name, "xrInitializeLoaderKHR") != 0) {
  650. // TODO why is xrGetInstanceProcAddr not listed in here?
  651. std::string error_str = "XR_NULL_HANDLE for instance but query for ";
  652. error_str += name;
  653. error_str += " requires a valid instance";
  654. LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-instance-parameter", "xrGetInstanceProcAddr",
  655. error_str);
  656. return XR_ERROR_HANDLE_INVALID;
  657. }
  658. } else {
  659. // non null instance passed in, it should be our current instance
  660. XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetInstanceProcAddr");
  661. if (XR_FAILED(result)) {
  662. return result;
  663. }
  664. if (loader_instance->GetInstanceHandle() != instance) {
  665. return XR_ERROR_HANDLE_INVALID;
  666. }
  667. }
  668. // These functions must always go through the loader's implementation (trampoline).
  669. if (strcmp(name, "xrGetInstanceProcAddr") == 0) {
  670. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrGetInstanceProcAddr);
  671. return XR_SUCCESS;
  672. } else if (strcmp(name, "xrInitializeLoaderKHR") == 0) {
  673. #ifdef XR_KHR_LOADER_INIT_SUPPORT
  674. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrInitializeLoaderKHR);
  675. return XR_SUCCESS;
  676. #else
  677. return XR_ERROR_FUNCTION_UNSUPPORTED;
  678. #endif
  679. } else if (strcmp(name, "xrEnumerateApiLayerProperties") == 0) {
  680. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrEnumerateApiLayerProperties);
  681. return XR_SUCCESS;
  682. } else if (strcmp(name, "xrEnumerateInstanceExtensionProperties") == 0) {
  683. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrEnumerateInstanceExtensionProperties);
  684. return XR_SUCCESS;
  685. } else if (strcmp(name, "xrCreateInstance") == 0) {
  686. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrCreateInstance);
  687. return XR_SUCCESS;
  688. } else if (strcmp(name, "xrDestroyInstance") == 0) {
  689. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrDestroyInstance);
  690. return XR_SUCCESS;
  691. }
  692. // XR_EXT_debug_utils is built into the loader and handled partly through the xrGetInstanceProcAddress terminator,
  693. // but the check to see if the extension is enabled must be done here where ActiveLoaderInstance is safe to use.
  694. if (*function == nullptr) {
  695. if (strcmp(name, "xrCreateDebugUtilsMessengerEXT") == 0) {
  696. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineCreateDebugUtilsMessengerEXT);
  697. } else if (strcmp(name, "xrDestroyDebugUtilsMessengerEXT") == 0) {
  698. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineDestroyDebugUtilsMessengerEXT);
  699. } else if (strcmp(name, "xrSessionBeginDebugUtilsLabelRegionEXT") == 0) {
  700. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionBeginDebugUtilsLabelRegionEXT);
  701. } else if (strcmp(name, "xrSessionEndDebugUtilsLabelRegionEXT") == 0) {
  702. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionEndDebugUtilsLabelRegionEXT);
  703. } else if (strcmp(name, "xrSessionInsertDebugUtilsLabelEXT") == 0) {
  704. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionInsertDebugUtilsLabelEXT);
  705. } else if (strcmp(name, "xrSetDebugUtilsObjectNameEXT") == 0) {
  706. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSetDebugUtilsObjectNameEXT);
  707. } else if (strcmp(name, "xrSubmitDebugUtilsMessageEXT") == 0) {
  708. *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSubmitDebugUtilsMessageEXT);
  709. }
  710. if (*function != nullptr && !loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
  711. // The function matches one of the XR_EXT_debug_utils functions but the extension is not enabled.
  712. *function = nullptr;
  713. return XR_ERROR_FUNCTION_UNSUPPORTED;
  714. }
  715. }
  716. if (*function != nullptr) {
  717. // The loader has a trampoline or implementation of this function.
  718. return XR_SUCCESS;
  719. }
  720. // If the function is not supported by the loader, call down to the next layer.
  721. return loader_instance->GetInstanceProcAddr(name, function);
  722. }
  723. XRLOADER_ABI_CATCH_FALLBACK
  724. // Exported loader functions
  725. //
  726. // The application might override these by exporting the same symbols and so we can't use these
  727. // symbols anywhere in the loader code, and instead the internal non exported functions that these
  728. // stubs call should be used internally.
  729. LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
  730. uint32_t *propertyCountOutput,
  731. XrApiLayerProperties *properties) {
  732. return LoaderXrEnumerateApiLayerProperties(propertyCapacityInput, propertyCountOutput, properties);
  733. }
  734. LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(const char *layerName,
  735. uint32_t propertyCapacityInput,
  736. uint32_t *propertyCountOutput,
  737. XrExtensionProperties *properties) {
  738. return LoaderXrEnumerateInstanceExtensionProperties(layerName, propertyCapacityInput, propertyCountOutput, properties);
  739. }
  740. LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *info, XrInstance *instance) {
  741. return LoaderXrCreateInstance(info, instance);
  742. }
  743. LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance) { return LoaderXrDestroyInstance(instance); }
  744. LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(XrInstance instance, const char *name,
  745. PFN_xrVoidFunction *function) {
  746. return LoaderXrGetInstanceProcAddr(instance, name, function);
  747. }
  748. #ifdef XR_KHR_LOADER_INIT_SUPPORT
  749. LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrInitializeLoaderKHR(const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo) {
  750. return LoaderXrInitializeLoaderKHR(loaderInitInfo);
  751. }
  752. #endif