OpenXRVkDevice.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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/OpenXRVkDevice.h>
  9. #include <OpenXRVk/OpenXRVkInstance.h>
  10. #include <OpenXRVk/OpenXRVkSession.h>
  11. #include <OpenXRVk/OpenXRVkSwapChain.h>
  12. #include <OpenXRVk/OpenXRVkSpace.h>
  13. #include <OpenXRVk/OpenXRVkUtils.h>
  14. #include <OpenXRVkCommon.h>
  15. #include <Atom/RHI.Reflect/VkAllocator.h>
  16. #include <Atom/RHI.Reflect/Vulkan/XRVkDescriptors.h>
  17. #include <AzCore/Casting/numeric_cast.h>
  18. namespace OpenXRVk
  19. {
  20. XR::Ptr<Device> Device::Create()
  21. {
  22. return aznew Device;
  23. }
  24. AZ::RHI::ResultCode Device::InitDeviceInternal(AZ::RHI::XRDeviceDescriptor* deviceDescriptor)
  25. {
  26. AZ::Vulkan::XRDeviceDescriptor* xrDeviceDescriptor = static_cast<AZ::Vulkan::XRDeviceDescriptor*>(deviceDescriptor);
  27. Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  28. XrVulkanDeviceCreateInfoKHR xrDeviceCreateInfo{ XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR };
  29. xrDeviceCreateInfo.systemId = xrVkInstance->GetXRSystemId();
  30. xrDeviceCreateInfo.pfnGetInstanceProcAddr = xrVkInstance->GetContext().GetInstanceProcAddr;
  31. xrDeviceCreateInfo.vulkanCreateInfo = xrDeviceDescriptor->m_inputData.m_deviceCreateInfo;
  32. xrDeviceCreateInfo.vulkanPhysicalDevice = xrVkInstance->GetActivePhysicalDevice();
  33. xrDeviceCreateInfo.vulkanAllocator = AZ::Vulkan::VkSystemAllocator::Get();
  34. PFN_xrGetVulkanDeviceExtensionsKHR pfnGetVulkanDeviceExtensionsKHR = nullptr;
  35. XrResult result = xrGetInstanceProcAddr(
  36. xrVkInstance->GetXRInstance(), "xrGetVulkanDeviceExtensionsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&pfnGetVulkanDeviceExtensionsKHR));
  37. ASSERT_IF_UNSUCCESSFUL(result);
  38. AZ::u32 deviceExtensionNamesSize = 0;
  39. result = pfnGetVulkanDeviceExtensionsKHR(xrVkInstance->GetXRInstance(), xrDeviceCreateInfo.systemId, 0, &deviceExtensionNamesSize, nullptr);
  40. ASSERT_IF_UNSUCCESSFUL(result);
  41. AZStd::vector<char> deviceExtensionNames(deviceExtensionNamesSize);
  42. result = pfnGetVulkanDeviceExtensionsKHR(
  43. xrVkInstance->GetXRInstance(), xrDeviceCreateInfo.systemId, deviceExtensionNamesSize, &deviceExtensionNamesSize, &deviceExtensionNames[0]);
  44. ASSERT_IF_UNSUCCESSFUL(result);
  45. AZStd::vector<const char*> extensions = ParseExtensionString(&deviceExtensionNames[0]);
  46. for (uint32_t i = 0; i < xrDeviceCreateInfo.vulkanCreateInfo->enabledExtensionCount; ++i)
  47. {
  48. extensions.push_back(xrDeviceCreateInfo.vulkanCreateInfo->ppEnabledExtensionNames[i]);
  49. }
  50. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  51. {
  52. AZ_Printf("OpenXRVk", "Vulkan device extensions to enable: (%i)\n", extensions.size());
  53. for (const AZStd::string& extension : extensions)
  54. {
  55. AZ_Printf("OpenXRVk", "Name=%s\n", extension.c_str());
  56. }
  57. }
  58. VkPhysicalDeviceFeatures features{};
  59. memcpy(&features, xrDeviceCreateInfo.vulkanCreateInfo->pEnabledFeatures, sizeof(features));
  60. VkPhysicalDeviceFeatures availableFeatures{};
  61. xrVkInstance->GetContext().GetPhysicalDeviceFeatures(xrVkInstance->GetActivePhysicalDevice(), &availableFeatures);
  62. if (availableFeatures.shaderStorageImageMultisample == VK_TRUE)
  63. {
  64. // Setting this quiets down a validation error triggered by the Oculus runtime
  65. features.shaderStorageImageMultisample = VK_TRUE;
  66. }
  67. VkDeviceCreateInfo deviceInfo{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
  68. memcpy(&deviceInfo, xrDeviceCreateInfo.vulkanCreateInfo, sizeof(deviceInfo));
  69. deviceInfo.pEnabledFeatures = &features;
  70. deviceInfo.enabledExtensionCount = aznumeric_cast<AZ::u32>(extensions.size());
  71. deviceInfo.ppEnabledExtensionNames = extensions.empty() ? nullptr : extensions.data();
  72. //Create VkDevice
  73. auto pfnCreateDevice = (PFN_vkCreateDevice)xrDeviceCreateInfo.pfnGetInstanceProcAddr(xrVkInstance->GetNativeInstance(), "vkCreateDevice");
  74. VkResult vulkanResult = pfnCreateDevice(xrDeviceCreateInfo.vulkanPhysicalDevice, &deviceInfo, xrDeviceCreateInfo.vulkanAllocator, &m_xrVkDevice);
  75. if (vulkanResult != VK_SUCCESS)
  76. {
  77. ShutdownInternal();
  78. AZ_Error("OpenXRVk", false, "Failed to create the device.");
  79. return AZ::RHI::ResultCode::Fail;
  80. }
  81. {
  82. VkPhysicalDevice xrVkPhysicalDevice = xrVkInstance->GetActivePhysicalDevice();
  83. // Now that we have created the device, load the function pointers for it.
  84. const bool functionsLoaded = xrVkInstance->GetFunctionLoader().LoadProcAddresses(
  85. &m_context, xrVkInstance->GetNativeInstance(), xrVkPhysicalDevice, m_xrVkDevice);
  86. FilterAvailableExtensions(m_context);
  87. if (!functionsLoaded)
  88. {
  89. ShutdownInternal();
  90. AZ_Error("OpenXRVk", false, "Failed to initialize function loader for the device.");
  91. return AZ::RHI::ResultCode::Fail;
  92. }
  93. }
  94. //Populate the output data of the descriptor
  95. xrDeviceDescriptor->m_outputData.m_xrVkDevice = m_xrVkDevice;
  96. xrDeviceDescriptor->m_outputData.m_context = m_context;
  97. return AZ::RHI::ResultCode::Success;
  98. }
  99. bool Device::BeginFrameInternal()
  100. {
  101. Platform::OpenXRBeginFrameInternal();
  102. Session* session = static_cast<Session*>(GetSession().get());
  103. XrSession xrSession = session->GetXrSession();
  104. m_xrLayers.clear();
  105. m_projectionLayerViews.clear();
  106. XrFrameWaitInfo frameWaitInfo{ XR_TYPE_FRAME_WAIT_INFO };
  107. XrResult result = xrWaitFrame(xrSession, &frameWaitInfo, &m_frameState);
  108. WARN_IF_UNSUCCESSFUL(result);
  109. XrFrameBeginInfo frameBeginInfo{ XR_TYPE_FRAME_BEGIN_INFO };
  110. result = xrBeginFrame(xrSession, &frameBeginInfo);
  111. //The XR_FRAME_DISCARDED can sometimes spam harmlessly so filter it out
  112. if (result != XR_FRAME_DISCARDED)
  113. {
  114. WARN_IF_UNSUCCESSFUL(result);
  115. }
  116. //Always return true as we want EndFrame to always be called.
  117. return true;
  118. }
  119. void Device::EndFrameInternal(XR::Ptr<XR::SwapChain> baseSwapChain)
  120. {
  121. Platform::OpenXREndFrameInternal();
  122. Session* session = static_cast<Session*>(GetSession().get());
  123. Instance* instance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  124. SwapChain* swapChain = static_cast<SwapChain*>(baseSwapChain.get());
  125. Space* xrSpace = static_cast<Space*>(GetSession()->GetSpace());
  126. XrSession xrSession = session->GetXrSession();
  127. for(uint32_t i = 0; i < swapChain->GetNumViews(); i++)
  128. {
  129. XR::SwapChain::View* baseSwapChainView = baseSwapChain->GetView(i);
  130. SwapChain::View* viewSwapChain = static_cast<SwapChain::View*>(baseSwapChainView);
  131. if (baseSwapChainView->m_isImageAcquired)
  132. {
  133. XrSwapchainImageReleaseInfo releaseInfo{ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO };
  134. XrResult result = xrReleaseSwapchainImage(viewSwapChain->GetSwapChainHandle(), &releaseInfo);
  135. ASSERT_IF_UNSUCCESSFUL(result);
  136. baseSwapChainView->m_isImageAcquired = false;
  137. }
  138. }
  139. m_xrLayer.space = xrSpace->GetXrSpace(OpenXRVk::SpaceType::View);
  140. m_xrLayer.viewCount = aznumeric_cast<uint32_t>(m_projectionLayerViews.size());
  141. m_xrLayer.views = m_projectionLayerViews.data();
  142. m_xrLayers.push_back(reinterpret_cast<XrCompositionLayerBaseHeader*>(&m_xrLayer));
  143. XrFrameEndInfo frameEndInfo{ XR_TYPE_FRAME_END_INFO };
  144. frameEndInfo.displayTime = m_frameState.predictedDisplayTime;
  145. frameEndInfo.environmentBlendMode = instance->GetEnvironmentBlendMode();
  146. frameEndInfo.layerCount = aznumeric_cast<uint32_t>(m_xrLayers.size());
  147. frameEndInfo.layers = m_xrLayers.data();
  148. XrResult result = xrEndFrame(xrSession, &frameEndInfo);
  149. //The XR_ERROR_VALIDATION_FAILURE can sometimes spam harmlessly so filter it out.
  150. //It usually happens when xrBeginFrame yields XR_FRAME_DISCARDED
  151. if (result != XR_ERROR_VALIDATION_FAILURE)
  152. {
  153. WARN_IF_UNSUCCESSFUL(result);
  154. }
  155. }
  156. void Device::PostFrameInternal()
  157. {
  158. Platform::OpenXRPostFrameInternal();
  159. }
  160. bool Device::AcquireSwapChainImageInternal(AZ::u32 viewIndex, XR::SwapChain* baseSwapChain)
  161. {
  162. XR::SwapChain::View* baseSwapChainView = baseSwapChain->GetView(viewIndex);
  163. SwapChain::View* swapChainView = static_cast<SwapChain::View*>(baseSwapChainView);
  164. Space* xrSpace = static_cast<Space*>(GetSession()->GetSpace());
  165. Instance* instance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  166. Session* session = static_cast<Session*>(GetSession().get());
  167. XrSession xrSession = session->GetXrSession();
  168. XrSwapchain swapChainHandle = swapChainView->GetSwapChainHandle();
  169. XrViewState viewState{ XR_TYPE_VIEW_STATE };
  170. uint32_t viewCapacityInput = aznumeric_cast<uint32_t>(m_views.size());
  171. XrViewLocateInfo viewLocateInfo{ XR_TYPE_VIEW_LOCATE_INFO };
  172. viewLocateInfo.viewConfigurationType = instance->GetViewConfigType();
  173. viewLocateInfo.displayTime = m_frameState.predictedDisplayTime;
  174. viewLocateInfo.space = xrSpace->GetXrSpace(OpenXRVk::SpaceType::View);
  175. XrResult result = xrLocateViews(xrSession, &viewLocateInfo, &viewState, viewCapacityInput, &m_viewCountOutput, m_views.data());
  176. ASSERT_IF_UNSUCCESSFUL(result);
  177. if ((viewState.viewStateFlags & XR_VIEW_STATE_POSITION_VALID_BIT) == 0 ||
  178. (viewState.viewStateFlags & XR_VIEW_STATE_ORIENTATION_VALID_BIT) == 0)
  179. {
  180. //There is no valid tracking poses for the views
  181. return false;
  182. }
  183. AZ_Assert(m_viewCountOutput == viewCapacityInput, "Size mismatch between xrLocateViews %i and xrEnumerateViewConfigurationViews %i", m_viewCountOutput, viewCapacityInput);
  184. AZ_Assert(m_viewCountOutput == static_cast<SwapChain*>(baseSwapChain)->GetViewConfigs().size(), "Size mismatch between xrLocateViews %i and xrEnumerateViewConfigurationViews %i", m_viewCountOutput, static_cast<SwapChain*>(baseSwapChain)->GetViewConfigs().size());
  185. m_projectionLayerViews.resize(m_viewCountOutput);
  186. XrSwapchainImageAcquireInfo acquireInfo{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO };
  187. result = xrAcquireSwapchainImage(swapChainHandle, &acquireInfo, &baseSwapChainView->m_activeImageIndex);
  188. baseSwapChainView->m_isImageAcquired = (result == XR_SUCCESS);
  189. WARN_IF_UNSUCCESSFUL(result);
  190. XrSwapchainImageWaitInfo waitInfo{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO };
  191. waitInfo.timeout = XR_INFINITE_DURATION;
  192. result = xrWaitSwapchainImage(swapChainHandle, &waitInfo);
  193. ASSERT_IF_UNSUCCESSFUL(result);
  194. m_projectionLayerViews[viewIndex] = { XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW };
  195. m_projectionLayerViews[viewIndex].pose = m_views[viewIndex].pose;
  196. m_projectionLayerViews[viewIndex].fov = m_views[viewIndex].fov;
  197. m_projectionLayerViews[viewIndex].subImage.swapchain = swapChainHandle;
  198. m_projectionLayerViews[viewIndex].subImage.imageRect.offset = { 0, 0 };
  199. m_projectionLayerViews[viewIndex].subImage.imageRect.extent = { static_cast<int>(swapChainView->GetWidth()),
  200. static_cast<int>(swapChainView->GetHeight()) };
  201. return true;
  202. }
  203. bool Device::ShouldRender() const
  204. {
  205. return m_frameState.shouldRender == XR_TRUE;
  206. }
  207. void Device::InitXrViews(uint32_t numViews)
  208. {
  209. // Create and cache view buffer for xrLocateViews later.
  210. m_views.clear();
  211. m_views.resize(numViews, { XR_TYPE_VIEW });
  212. }
  213. VkDevice Device::GetNativeDevice() const
  214. {
  215. return m_xrVkDevice;
  216. }
  217. const GladVulkanContext& Device::GetContext() const
  218. {
  219. return m_context;
  220. }
  221. AZ::RHI::ResultCode Device::GetViewFov(AZ::u32 viewIndex, AZ::RPI::FovData& outFovData) const
  222. {
  223. if(viewIndex < m_projectionLayerViews.size())
  224. {
  225. outFovData.m_angleLeft = m_projectionLayerViews[viewIndex].fov.angleLeft;
  226. outFovData.m_angleRight = m_projectionLayerViews[viewIndex].fov.angleRight;
  227. outFovData.m_angleUp = m_projectionLayerViews[viewIndex].fov.angleUp;
  228. outFovData.m_angleDown = m_projectionLayerViews[viewIndex].fov.angleDown;
  229. return AZ::RHI::ResultCode::Success;
  230. }
  231. return AZ::RHI::ResultCode::Fail;
  232. }
  233. AZ::RHI::ResultCode Device::GetViewPose(AZ::u32 viewIndex, AZ::RPI::PoseData& outPoseData) const
  234. {
  235. if (viewIndex < m_projectionLayerViews.size())
  236. {
  237. const XrQuaternionf& orientation = m_projectionLayerViews[viewIndex].pose.orientation;
  238. const XrVector3f& position = m_projectionLayerViews[viewIndex].pose.position;
  239. outPoseData.m_orientation.Set(orientation.x,
  240. orientation.y,
  241. orientation.z,
  242. orientation.w);
  243. outPoseData.m_position.Set(position.x,
  244. position.y,
  245. position.z);
  246. return AZ::RHI::ResultCode::Success;
  247. }
  248. return AZ::RHI::ResultCode::Fail;
  249. }
  250. XrTime Device::GetPredictedDisplayTime() const
  251. {
  252. return m_frameState.predictedDisplayTime;
  253. }
  254. void Device::ShutdownInternal()
  255. {
  256. m_projectionLayerViews.clear();
  257. m_views.clear();
  258. m_xrLayers.clear();
  259. if (m_xrVkDevice != VK_NULL_HANDLE)
  260. {
  261. m_context.DestroyDevice(m_xrVkDevice, AZ::Vulkan::VkSystemAllocator::Get());
  262. m_xrVkDevice = VK_NULL_HANDLE;
  263. }
  264. }
  265. }