OpenXRVkInstance.cpp 17 KB

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