OpenXRVkInstance.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <OpenXRVk/OpenXRVkInstance.h>
  9. #include <OpenXRVk/OpenXRVkUtils.h>
  10. #include <Atom/RHI.Reflect/Vulkan/XRVkDescriptors.h>
  11. #include <Atom/RHI.Reflect/VkAllocator.h>
  12. #include <AzCore/Casting/numeric_cast.h>
  13. #include <OpenXRVkCommon.h>
  14. namespace OpenXRVk
  15. {
  16. XR::Ptr<Instance> Instance::Create()
  17. {
  18. return aznew Instance;
  19. }
  20. XR::StringList Instance::GetInstanceExtensionNames(const char* layerName /*= nullptr*/) const
  21. {
  22. XR::StringList extensionNames;
  23. AZ::u32 extPropertyCount = 0;
  24. XrResult result = xrEnumerateInstanceExtensionProperties(layerName, 0, &extPropertyCount, nullptr);
  25. if (IsError(result) || extPropertyCount == 0)
  26. {
  27. return extensionNames;
  28. }
  29. AZStd::vector<XrExtensionProperties> extProperties;
  30. extProperties.resize(extPropertyCount);
  31. for (XrExtensionProperties& extension : extProperties)
  32. {
  33. extension.type = XR_TYPE_EXTENSION_PROPERTIES;
  34. }
  35. result = xrEnumerateInstanceExtensionProperties(layerName, aznumeric_cast<AZ::u32>(extProperties.size()), &extPropertyCount, extProperties.data());
  36. if (IsError(result))
  37. {
  38. return extensionNames;
  39. }
  40. extensionNames.reserve(extensionNames.size() + extProperties.size());
  41. for (uint32_t extPropertyIndex = 0; extPropertyIndex < extPropertyCount; extPropertyIndex++)
  42. {
  43. extensionNames.emplace_back(extProperties[extPropertyIndex].extensionName);
  44. }
  45. return extensionNames;
  46. }
  47. XR::StringList Instance::GetInstanceLayerNames() const
  48. {
  49. XR::StringList layerNames;
  50. AZ::u32 layerPropertyCount = 0;
  51. XrResult result = xrEnumerateApiLayerProperties(0, &layerPropertyCount, nullptr);
  52. if (IsError(result) || layerPropertyCount == 0)
  53. {
  54. return layerNames;
  55. }
  56. AZStd::vector<XrApiLayerProperties> layerProperties(layerPropertyCount);
  57. for (XrApiLayerProperties& layer : layerProperties)
  58. {
  59. layer.type = XR_TYPE_API_LAYER_PROPERTIES;
  60. }
  61. result = xrEnumerateApiLayerProperties(aznumeric_cast<AZ::u32>(layerProperties.size()), &layerPropertyCount, layerProperties.data());
  62. if (IsError(result))
  63. {
  64. return layerNames;
  65. }
  66. layerNames.reserve(layerNames.size() + layerProperties.size());
  67. for (uint32_t layerPropertyIndex = 0; layerPropertyIndex < layerPropertyCount; ++layerPropertyIndex)
  68. {
  69. layerNames.emplace_back(layerProperties[layerPropertyIndex].layerName);
  70. }
  71. return layerNames;
  72. }
  73. AZ::RHI::ResultCode Instance::InitInstanceInternal()
  74. {
  75. if (!Platform::OpenXRInitializeLoader())
  76. {
  77. AZ_Error("OpenXRVk", false, "Could not initialize xr loader.");
  78. return AZ::RHI::ResultCode::Fail;
  79. }
  80. XR::RawStringList optionalLayers;
  81. XR::RawStringList optionalExtensions = { XR_KHR_VULKAN_ENABLE_EXTENSION_NAME };
  82. XR::StringList instanceLayerNames = GetInstanceLayerNames();
  83. XR::RawStringList supportedLayers = FilterList(optionalLayers, instanceLayerNames);
  84. m_requiredLayers.insert(m_requiredLayers.end(), supportedLayers.begin(), supportedLayers.end());
  85. XR::StringList instanceExtensions = GetInstanceExtensionNames();
  86. XR::RawStringList supportedExtensions = FilterList(optionalExtensions, instanceExtensions);
  87. m_requiredExtensions.insert(m_requiredExtensions.end(), supportedExtensions.begin(), supportedExtensions.end());
  88. if (m_validationMode == AZ::RHI::ValidationMode::Enabled)
  89. {
  90. AZ_Printf("OpenXRVk", "Available Extensions: (%i)\n", instanceExtensions.size());
  91. for (const AZStd::string& extension : instanceExtensions)
  92. {
  93. AZ_Printf("OpenXRVk", "Name=%s\n", extension.c_str());
  94. }
  95. AZ_Printf("OpenXRVk", "Extensions to enable: (%i)\n", m_requiredExtensions.size());
  96. for (const char* extension : m_requiredExtensions)
  97. {
  98. AZ_Printf("OpenXRVk", "Name=%s\n", extension);
  99. }
  100. AZ_Printf("OpenXRVk", "Available Layers: (%i)\n", instanceLayerNames.size());
  101. for (const AZStd::string& layerName : instanceLayerNames)
  102. {
  103. AZ_Printf("OpenXRVk", "Name=%s \n", layerName.c_str());
  104. }
  105. }
  106. AZ_Assert(m_xrInstance == XR_NULL_HANDLE, "XR Instance is already initialized");
  107. XrInstanceCreateInfo createInfo{ XR_TYPE_INSTANCE_CREATE_INFO };
  108. createInfo.next = nullptr;
  109. createInfo.enabledExtensionCount = aznumeric_cast<AZ::u32>(m_requiredExtensions.size());
  110. createInfo.enabledExtensionNames = m_requiredExtensions.data();
  111. createInfo.enabledApiLayerCount = aznumeric_cast<AZ::u32>(supportedLayers.size());
  112. createInfo.enabledApiLayerNames = supportedLayers.data();
  113. azstrncpy(createInfo.applicationInfo.applicationName, XR_MAX_APPLICATION_NAME_SIZE, "O3deApp", 4);
  114. createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
  115. //Create XR instance
  116. XrResult result = xrCreateInstance(&createInfo, &m_xrInstance);
  117. if(IsError(result))
  118. {
  119. AZ_Warning("OpenXRVk", false, "Failed to create XR instance");
  120. return AZ::RHI::ResultCode::Fail;
  121. }
  122. if (m_validationMode == AZ::RHI::ValidationMode::Enabled)
  123. {
  124. XrInstanceProperties instanceProperties{ XR_TYPE_INSTANCE_PROPERTIES };
  125. result = xrGetInstanceProperties(m_xrInstance, &instanceProperties);
  126. if (IsSuccess(result))
  127. {
  128. AZStd::string verStr = AZStd::string::format("%d.%d.%d",
  129. XR_VERSION_MAJOR(instanceProperties.runtimeVersion),
  130. XR_VERSION_MINOR(instanceProperties.runtimeVersion),
  131. XR_VERSION_PATCH(instanceProperties.runtimeVersion));
  132. AZ_Printf("OpenXRVk", "Instance RuntimeName=%s RuntimeVersion=%s\n", instanceProperties.runtimeName, verStr.c_str());
  133. }
  134. }
  135. AZ_Assert(m_xrInstance != XR_NULL_HANDLE, "XR Instance is Null");
  136. AZ_Assert(m_xrSystemId == XR_NULL_SYSTEM_ID, "XR System id already initialized");
  137. //TODO::Add support for handheld display
  138. m_formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
  139. //TODO::Add support for other view configuration types
  140. m_viewConfigType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
  141. //TODO::Add support for other environment blend types
  142. m_environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
  143. XrSystemGetInfo systemInfo{ XR_TYPE_SYSTEM_GET_INFO };
  144. systemInfo.formFactor = m_formFactor;
  145. result = xrGetSystem(m_xrInstance, &systemInfo, &m_xrSystemId);
  146. if (IsError(result))
  147. {
  148. AZ_Warning("OpenXRVk", false, "Failed to get XR System id");
  149. return AZ::RHI::ResultCode::Fail;
  150. }
  151. // Query the runtime Vulkan API version requirements
  152. XrGraphicsRequirementsVulkan2KHR graphicsRequirements{ XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR };
  153. PFN_xrGetVulkanGraphicsRequirementsKHR pfnGetVulkanGraphicsRequirementsKHR = nullptr;
  154. result = xrGetInstanceProcAddr(m_xrInstance, "xrGetVulkanGraphicsRequirementsKHR",
  155. reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanGraphicsRequirementsKHR));
  156. WARN_IF_UNSUCCESSFUL(result);
  157. XrGraphicsRequirementsVulkanKHR legacyRequirements{ XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR };
  158. result = pfnGetVulkanGraphicsRequirementsKHR(m_xrInstance, m_xrSystemId, &legacyRequirements);
  159. WARN_IF_UNSUCCESSFUL(result);
  160. graphicsRequirements.maxApiVersionSupported = legacyRequirements.maxApiVersionSupported;
  161. graphicsRequirements.minApiVersionSupported = legacyRequirements.minApiVersionSupported;
  162. if (m_validationMode == AZ::RHI::ValidationMode::Enabled)
  163. {
  164. AZ_Printf("OpenXRVk", "graphicsRequirements.maxApiVersionSupported %d.%d.%d\n",
  165. XR_VERSION_MAJOR(graphicsRequirements.maxApiVersionSupported),
  166. XR_VERSION_MINOR(graphicsRequirements.maxApiVersionSupported),
  167. XR_VERSION_PATCH(graphicsRequirements.maxApiVersionSupported));
  168. AZ_Printf("OpenXRVk", "graphicsRequirements.minApiVersionSupported %d.%d.%d\n",
  169. XR_VERSION_MAJOR(graphicsRequirements.minApiVersionSupported),
  170. XR_VERSION_MINOR(graphicsRequirements.minApiVersionSupported),
  171. XR_VERSION_PATCH(graphicsRequirements.minApiVersionSupported));
  172. AZ_Printf("OpenXRVk", "Using system %d for form factor %s\n", m_xrSystemId, to_string(m_formFactor));
  173. LogViewConfigurations();
  174. }
  175. return AZ::RHI::ResultCode::Success;
  176. }
  177. void Instance::LogViewConfigurations()
  178. {
  179. AZ::u32 viewConfigTypeCount = 0;
  180. XrResult result = xrEnumerateViewConfigurations(m_xrInstance, m_xrSystemId, 0, &viewConfigTypeCount, nullptr);
  181. RETURN_IF_UNSUCCESSFUL(result);
  182. AZStd::vector<XrViewConfigurationType> viewConfigTypes(viewConfigTypeCount);
  183. result = xrEnumerateViewConfigurations(m_xrInstance, m_xrSystemId, viewConfigTypeCount, &viewConfigTypeCount, viewConfigTypes.data());
  184. RETURN_IF_UNSUCCESSFUL(result);
  185. AZ_Warning("OpenXRVk", aznumeric_cast<AZ::u32>(viewConfigTypes.size()) == viewConfigTypeCount, "Size Mismatch");
  186. AZ_Printf("OpenXRVk", "Available View Configuration Types: (%d)\n", viewConfigTypeCount);
  187. for (XrViewConfigurationType viewConfigType : viewConfigTypes)
  188. {
  189. AZ_Printf("OpenXRVk", "View Configuration Type: %s %s\n", to_string(viewConfigType),
  190. viewConfigType == m_viewConfigType ? "(Selected)" : "");
  191. XrViewConfigurationProperties viewConfigProperties{ XR_TYPE_VIEW_CONFIGURATION_PROPERTIES };
  192. result = xrGetViewConfigurationProperties(m_xrInstance, m_xrSystemId, viewConfigType, &viewConfigProperties);
  193. RETURN_IF_UNSUCCESSFUL(result);
  194. AZ_Printf("OpenXRVk", "View configuration FovMutable=%s\n", viewConfigProperties.fovMutable == XR_TRUE ? "True" : "False");
  195. AZ::u32 viewCount = 0;
  196. result = xrEnumerateViewConfigurationViews(m_xrInstance, m_xrSystemId, viewConfigType, 0, &viewCount, nullptr);
  197. RETURN_IF_UNSUCCESSFUL(result);
  198. if (viewCount > 0)
  199. {
  200. AZStd::vector<XrViewConfigurationView> views(viewCount);
  201. for (XrViewConfigurationView& view : views)
  202. {
  203. view.type = XR_TYPE_VIEW_CONFIGURATION_VIEW;
  204. }
  205. result = xrEnumerateViewConfigurationViews(m_xrInstance, m_xrSystemId, viewConfigType, viewCount, &viewCount, views.data());
  206. RETURN_IF_UNSUCCESSFUL(result);
  207. for (uint32_t i = 0; i < views.size(); i++)
  208. {
  209. const XrViewConfigurationView& view = views[i];
  210. AZ_Printf(
  211. "OpenXRVk", "View [%d]: Recommended Width=%d Height=%d SampleCount=%d\n", i, view.recommendedImageRectWidth,
  212. view.recommendedImageRectHeight, view.recommendedSwapchainSampleCount);
  213. AZ_Printf(
  214. "OpenXRVk", "View [%d]: Maximum Width=%d Height=%d SampleCount=%d\n", i, view.maxImageRectWidth,
  215. view.maxImageRectHeight, view.maxSwapchainSampleCount);
  216. }
  217. }
  218. else
  219. {
  220. AZ_Printf("OpenXRVk", "Empty view configuration type\n");
  221. }
  222. LogEnvironmentBlendMode(viewConfigType);
  223. }
  224. }
  225. void Instance::LogEnvironmentBlendMode(XrViewConfigurationType type)
  226. {
  227. AZ::u32 count = 0;
  228. XrResult result = xrEnumerateEnvironmentBlendModes(m_xrInstance, m_xrSystemId, type, 0, &count, nullptr);
  229. AZ_Warning("OpenXRVk", count > 0, "BlendModes not supported");
  230. RETURN_IF_UNSUCCESSFUL(result);
  231. AZ_Printf("OpenXRVk", "Available Environment Blend Mode count : (%d)\n", count);
  232. AZStd::vector<XrEnvironmentBlendMode> blendModes(count);
  233. result = xrEnumerateEnvironmentBlendModes(m_xrInstance, m_xrSystemId, type, count, &count, blendModes.data());
  234. RETURN_IF_UNSUCCESSFUL(result);
  235. [[maybe_unused]] bool blendModeFound = false;
  236. for (XrEnvironmentBlendMode mode : blendModes)
  237. {
  238. const bool blendModeMatch = (mode == m_environmentBlendMode);
  239. AZ_Printf("OpenXRVk", "Environment Blend Mode (%s) : %s\n", to_string(mode), blendModeMatch ? "(Selected)" : "");
  240. blendModeFound |= blendModeMatch;
  241. }
  242. }
  243. AZ::RHI::ResultCode Instance::InitNativeInstance(AZ::RHI::XRInstanceDescriptor* instanceDescriptor)
  244. {
  245. m_functionLoader = AZ::Vulkan::FunctionLoader::Create();
  246. if (!m_functionLoader->Init() ||
  247. !m_functionLoader->LoadProcAddresses(&m_context, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE))
  248. {
  249. m_functionLoader.reset();
  250. AZ_Error("OpenXRVk", false, "Could not initialize function loader.");
  251. return AZ::RHI::ResultCode::Fail;
  252. }
  253. AZ::Vulkan::XRInstanceDescriptor* xrInstanceDescriptor = static_cast<AZ::Vulkan::XRInstanceDescriptor*>(instanceDescriptor);
  254. XrVulkanInstanceCreateInfoKHR createInfo{ XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR };
  255. createInfo.systemId = m_xrSystemId;
  256. createInfo.pfnGetInstanceProcAddr = m_context.GetInstanceProcAddr;
  257. createInfo.vulkanCreateInfo = xrInstanceDescriptor->m_inputData.m_createInfo;
  258. createInfo.vulkanAllocator = AZ::Vulkan::VkSystemAllocator::Get();
  259. PFN_xrGetVulkanInstanceExtensionsKHR pfnGetVulkanInstanceExtensionsKHR = nullptr;
  260. XrResult result = xrGetInstanceProcAddr(m_xrInstance, "xrGetVulkanInstanceExtensionsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanInstanceExtensionsKHR));
  261. ASSERT_IF_UNSUCCESSFUL(result);
  262. AZ::u32 extensionNamesSize = 0;
  263. result = pfnGetVulkanInstanceExtensionsKHR(m_xrInstance, m_xrSystemId, 0, &extensionNamesSize, nullptr);
  264. ASSERT_IF_UNSUCCESSFUL(result);
  265. AZStd::vector<char> extensionNames(extensionNamesSize);
  266. result = pfnGetVulkanInstanceExtensionsKHR(m_xrInstance, m_xrSystemId, extensionNamesSize, &extensionNamesSize, &extensionNames[0]);
  267. ASSERT_IF_UNSUCCESSFUL(result);
  268. AZStd::vector<const char*> extensions = ParseExtensionString(&extensionNames[0]);
  269. for (uint32_t i = 0; i < createInfo.vulkanCreateInfo->enabledExtensionCount; ++i)
  270. {
  271. extensions.push_back(createInfo.vulkanCreateInfo->ppEnabledExtensionNames[i]);
  272. }
  273. if (m_validationMode == AZ::RHI::ValidationMode::Enabled)
  274. {
  275. AZ_Printf("OpenXRVk", "Vulkan instance extensions to enable: (%i)\n", extensions.size());
  276. for (const AZStd::string& extension : extensions)
  277. {
  278. AZ_Printf("OpenXRVk", "Name=%s\n", extension.c_str());
  279. }
  280. }
  281. VkInstanceCreateInfo instInfo{ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
  282. memcpy(&instInfo, createInfo.vulkanCreateInfo, sizeof(instInfo));
  283. instInfo.enabledExtensionCount = aznumeric_cast<AZ::u32>(extensions.size());
  284. instInfo.ppEnabledExtensionNames = extensions.empty() ? nullptr : extensions.data();
  285. auto pfnCreateInstance = (PFN_vkCreateInstance)createInfo.pfnGetInstanceProcAddr(nullptr, "vkCreateInstance");
  286. VkResult vkResult = pfnCreateInstance(&instInfo, AZ::Vulkan::VkSystemAllocator::Get(), &m_xrVkInstance);
  287. if (vkResult != VK_SUCCESS)
  288. {
  289. ShutdownInternal();
  290. AZ_Error("OpenXRVk", false, "Failed to create the instance.");
  291. return AZ::RHI::ResultCode::Fail;
  292. }
  293. // Now that we have created the instance, load the function pointers for it.
  294. if (!m_functionLoader->LoadProcAddresses(&m_context, m_xrVkInstance, VK_NULL_HANDLE, VK_NULL_HANDLE))
  295. {
  296. ShutdownInternal();
  297. AZ_Warning("OpenXRVk", false, "Failed to initialize function loader for the instance.");
  298. return AZ::RHI::ResultCode::Fail;
  299. }
  300. FilterAvailableExtensions(m_context);
  301. //Populate the instance descriptor with the correct VkInstance
  302. xrInstanceDescriptor->m_outputData.m_xrVkInstance = m_xrVkInstance;
  303. xrInstanceDescriptor->m_outputData.m_context = m_context;
  304. //Get the list of Physical devices
  305. m_supportedXRDevices = PhysicalDevice::EnumerateDeviceList(m_xrSystemId, m_xrInstance, m_xrVkInstance);
  306. if (m_supportedXRDevices.empty())
  307. {
  308. ShutdownInternal();
  309. AZ_Error("OpenXRVk", false, "No physical devices found.");
  310. return AZ::RHI::ResultCode::Fail;
  311. }
  312. //Just use the first device at the moment.
  313. m_physicalDeviceActiveIndex = 0;
  314. return AZ::RHI::ResultCode::Success;
  315. }
  316. void Instance::ShutdownInternal()
  317. {
  318. if (m_xrVkInstance != VK_NULL_HANDLE)
  319. {
  320. m_supportedXRDevices.clear();
  321. m_context.DestroyInstance(m_xrVkInstance, AZ::Vulkan::VkSystemAllocator::Get());
  322. m_xrVkInstance = VK_NULL_HANDLE;
  323. }
  324. if (m_functionLoader)
  325. {
  326. m_functionLoader->Shutdown();
  327. }
  328. m_functionLoader = nullptr;
  329. }
  330. AZ::RHI::ResultCode Instance::GetXRPhysicalDevice(AZ::RHI::XRPhysicalDeviceDescriptor* physicalDeviceDescriptor, int32_t index)
  331. {
  332. AZ::Vulkan::XRPhysicalDeviceDescriptor* xrPhysicalDeviceDescriptor = static_cast<AZ::Vulkan::XRPhysicalDeviceDescriptor*>(physicalDeviceDescriptor);
  333. if (xrPhysicalDeviceDescriptor && (index < m_supportedXRDevices.size()))
  334. {
  335. xrPhysicalDeviceDescriptor->m_outputData.m_xrVkPhysicalDevice = m_supportedXRDevices[index];
  336. return AZ::RHI::ResultCode::Success;
  337. }
  338. return AZ::RHI::ResultCode::Fail;
  339. }
  340. AZ::u32 Instance::GetNumPhysicalDevices() const
  341. {
  342. return aznumeric_cast<AZ::u32>(m_supportedXRDevices.size());
  343. }
  344. VkPhysicalDevice Instance::GetActivePhysicalDevice() const
  345. {
  346. AZ_Assert(m_physicalDeviceActiveIndex < m_supportedXRDevices.size(), "Index out of range");
  347. return m_supportedXRDevices[m_physicalDeviceActiveIndex];
  348. }
  349. XrInstance Instance::GetXRInstance() const
  350. {
  351. return m_xrInstance;
  352. }
  353. XrSystemId Instance::GetXRSystemId() const
  354. {
  355. return m_xrSystemId;
  356. }
  357. VkInstance Instance::GetNativeInstance() const
  358. {
  359. return m_xrVkInstance;
  360. }
  361. GladVulkanContext& Instance::GetContext()
  362. {
  363. return m_context;
  364. }
  365. AZ::Vulkan::FunctionLoader& Instance::GetFunctionLoader()
  366. {
  367. return *m_functionLoader;
  368. }
  369. XrEnvironmentBlendMode Instance::GetEnvironmentBlendMode() const
  370. {
  371. return m_environmentBlendMode;
  372. }
  373. XrViewConfigurationType Instance::GetViewConfigType() const
  374. {
  375. return m_viewConfigType;
  376. }
  377. }