OpenXRVkDevice.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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 <OpenXRVk/OpenXRVkReferenceSpacesInterface.h>
  15. #include <OpenXRVkCommon.h>
  16. #include <Atom/RHI.Reflect/VkAllocator.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. m_xrVkDevice = xrDeviceDescriptor->m_inputData.m_xrVkDevice;
  28. m_xrVkPhysicalDevice = xrDeviceDescriptor->m_inputData.m_xrVkPhysicalDevice;
  29. m_xrQueueBinding = xrDeviceDescriptor->m_inputData.m_xrQueueBinding;
  30. return AZ::RHI::ResultCode::Success;
  31. }
  32. bool Device::BeginFrameInternal()
  33. {
  34. Platform::OpenXRBeginFrameInternal();
  35. Session* session = static_cast<Session*>(GetSession().get());
  36. XrSession xrSession = session->GetXrSession();
  37. m_xrLayers.clear();
  38. m_projectionLayerViews.clear();
  39. XrFrameWaitInfo frameWaitInfo{ XR_TYPE_FRAME_WAIT_INFO };
  40. XrResult result = xrWaitFrame(xrSession, &frameWaitInfo, &m_frameState);
  41. WARN_IF_UNSUCCESSFUL(result);
  42. XrFrameBeginInfo frameBeginInfo{ XR_TYPE_FRAME_BEGIN_INFO };
  43. result = xrBeginFrame(xrSession, &frameBeginInfo);
  44. //The XR_FRAME_DISCARDED can sometimes spam harmlessly so filter it out
  45. if (result != XR_FRAME_DISCARDED)
  46. {
  47. WARN_IF_UNSUCCESSFUL(result);
  48. }
  49. // Notify the session that a new frame is starting with its new predicted display time.
  50. // The new predicted display time will be used to calculate XrPoses for existing Reference Spaces.
  51. session->OnBeginFrame(m_frameState.predictedDisplayTime);
  52. //Always return true as we want EndFrame to always be called.
  53. return true;
  54. }
  55. void Device::EndFrameInternal(XR::Ptr<XR::SwapChain> baseSwapChain)
  56. {
  57. Platform::OpenXREndFrameInternal();
  58. Session* session = static_cast<Session*>(GetSession().get());
  59. Instance* instance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  60. SwapChain* swapChain = static_cast<SwapChain*>(baseSwapChain.get());
  61. XrSession xrSession = session->GetXrSession();
  62. for (uint32_t i = 0; i < swapChain->GetNumViews(); i++)
  63. {
  64. XR::SwapChain::View* baseSwapChainView = baseSwapChain->GetView(i);
  65. SwapChain::View* viewSwapChain = static_cast<SwapChain::View*>(baseSwapChainView);
  66. if (baseSwapChainView->m_isImageAcquired)
  67. {
  68. XrSwapchainImageReleaseInfo releaseInfo{ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO };
  69. XrResult result = xrReleaseSwapchainImage(viewSwapChain->GetSwapChainHandle(), &releaseInfo);
  70. ASSERT_IF_UNSUCCESSFUL(result);
  71. baseSwapChainView->m_isImageAcquired = false;
  72. }
  73. }
  74. m_xrLayer.space = session->GetViewSpaceXrSpace();
  75. m_xrLayer.viewCount = aznumeric_cast<uint32_t>(m_projectionLayerViews.size());
  76. m_xrLayer.views = m_projectionLayerViews.data();
  77. m_xrLayers.push_back(reinterpret_cast<XrCompositionLayerBaseHeader*>(&m_xrLayer));
  78. XrFrameEndInfo frameEndInfo{ XR_TYPE_FRAME_END_INFO };
  79. frameEndInfo.displayTime = m_frameState.predictedDisplayTime;
  80. frameEndInfo.environmentBlendMode = instance->GetEnvironmentBlendMode();
  81. frameEndInfo.layerCount = aznumeric_cast<uint32_t>(m_xrLayers.size());
  82. frameEndInfo.layers = m_xrLayers.data();
  83. XrResult result = xrEndFrame(xrSession, &frameEndInfo);
  84. //The XR_ERROR_VALIDATION_FAILURE can sometimes spam harmlessly so filter it out.
  85. //It usually happens when xrBeginFrame yields XR_FRAME_DISCARDED
  86. if (result != XR_ERROR_VALIDATION_FAILURE)
  87. {
  88. WARN_IF_UNSUCCESSFUL(result);
  89. }
  90. }
  91. void Device::PostFrameInternal()
  92. {
  93. Platform::OpenXRPostFrameInternal();
  94. }
  95. bool Device::AcquireSwapChainImageInternal(AZ::u32 viewIndex, XR::SwapChain* baseSwapChain)
  96. {
  97. XR::SwapChain::View* baseSwapChainView = baseSwapChain->GetView(viewIndex);
  98. SwapChain::View* swapChainView = static_cast<SwapChain::View*>(baseSwapChainView);
  99. XrSwapchain swapChainHandle = swapChainView->GetSwapChainHandle();
  100. Session* session = static_cast<Session*>(GetSession().get());
  101. XrSwapchainImageAcquireInfo acquireInfo{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO };
  102. auto result = xrAcquireSwapchainImage(swapChainHandle, &acquireInfo, &baseSwapChainView->m_activeImageIndex);
  103. baseSwapChainView->m_isImageAcquired = (result == XR_SUCCESS);
  104. WARN_IF_UNSUCCESSFUL(result);
  105. XrSwapchainImageWaitInfo waitInfo{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO };
  106. waitInfo.timeout = XR_INFINITE_DURATION;
  107. result = xrWaitSwapchainImage(swapChainHandle, &waitInfo);
  108. ASSERT_IF_UNSUCCESSFUL(result);
  109. // REMARK: The data in m_views was updated during BeginFrameInternal(), which
  110. // calls session->OnBeginFrame(...).
  111. const auto& xrViews = session->GetXrViews();
  112. m_projectionLayerViews.resize(xrViews.size());
  113. m_projectionLayerViews[viewIndex] = { XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW };
  114. m_projectionLayerViews[viewIndex].pose = xrViews[viewIndex].pose;
  115. m_projectionLayerViews[viewIndex].fov = xrViews[viewIndex].fov;
  116. m_projectionLayerViews[viewIndex].subImage.swapchain = swapChainHandle;
  117. m_projectionLayerViews[viewIndex].subImage.imageRect.offset = { 0, 0 };
  118. m_projectionLayerViews[viewIndex].subImage.imageRect.extent = { static_cast<int>(swapChainView->GetWidth()),
  119. static_cast<int>(swapChainView->GetHeight()) };
  120. return true;
  121. }
  122. bool Device::ShouldRender() const
  123. {
  124. return m_frameState.shouldRender == XR_TRUE;
  125. }
  126. VkDevice Device::GetNativeDevice() const
  127. {
  128. return m_xrVkDevice;
  129. }
  130. VkPhysicalDevice Device::GetNativePhysicalDevice() const
  131. {
  132. return m_xrVkPhysicalDevice;
  133. }
  134. const AZ::Vulkan::XRDeviceDescriptor::GraphicsBinding& Device::GetGraphicsBinding(AZ::RHI::HardwareQueueClass queueClass) const
  135. {
  136. return m_xrQueueBinding[static_cast<uint32_t>(queueClass)];
  137. }
  138. AZ::RHI::ResultCode Device::GetViewFov(AZ::u32 viewIndex, AZ::RPI::FovData& outFovData) const
  139. {
  140. if (auto spacesIface = OpenXRReferenceSpacesInterface::Get();
  141. spacesIface != nullptr)
  142. {
  143. outFovData = spacesIface->GetViewFovData(viewIndex);
  144. return AZ::RHI::ResultCode::Success;
  145. }
  146. return AZ::RHI::ResultCode::Fail;
  147. }
  148. AZ::RHI::ResultCode Device::GetViewPose([[maybe_unused]] AZ::u32 viewIndex, [[maybe_unused]] AZ::RPI::PoseData& outPoseData) const
  149. {
  150. AZ_Assert(false, "Don't call this function!");
  151. return AZ::RHI::ResultCode::Fail;
  152. }
  153. XrTime Device::GetPredictedDisplayTime() const
  154. {
  155. return m_frameState.predictedDisplayTime;
  156. }
  157. void Device::ShutdownInternal()
  158. {
  159. m_projectionLayerViews.clear();
  160. m_xrLayers.clear();
  161. m_xrVkDevice = VK_NULL_HANDLE;
  162. m_xrVkPhysicalDevice = VK_NULL_HANDLE;
  163. }
  164. }