2
0

OpenXRVkSwapChain.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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 <Atom/RHI.Reflect/Vulkan/XRVkDescriptors.h>
  9. #include <AzCore/Casting/numeric_cast.h>
  10. #include <AzCore/std/containers/set.h>
  11. #include <AzCore/std/containers/vector.h>
  12. #include <OpenXRVk/OpenXRVkInstance.h>
  13. #include <OpenXRVk/OpenXRVkSession.h>
  14. #include <OpenXRVk/OpenXRVkSwapChain.h>
  15. #include <OpenXRVk/OpenXRVkUtils.h>
  16. #include <XR/XRFactory.h>
  17. // TODO: Expose ConvertFormat in Vulkan RHI::Reflect
  18. #include <../Source/RHI/Formats.inl>
  19. namespace AZ::Vulkan
  20. {
  21. RHI::Format ConvertFormat(VkFormat format)
  22. {
  23. #define RHIVK_VK_TO_RHI(_FormatID, _VKFormat, _Color, _Depth, _Stencil) \
  24. case _VKFormat: \
  25. return RHI::Format::_FormatID;
  26. switch (format)
  27. {
  28. case VK_FORMAT_UNDEFINED:
  29. return RHI::Format::Unknown;
  30. RHIVK_EXPAND_FOR_FORMATS(RHIVK_VK_TO_RHI)
  31. default:
  32. AZ_Assert(false, "unhandled conversion in ConvertFormat");
  33. return RHI::Format::Unknown;
  34. }
  35. #undef RHIVK_VK_TO_RHI
  36. }
  37. }
  38. namespace OpenXRVk
  39. {
  40. XR::Ptr<SwapChain> SwapChain::Create()
  41. {
  42. return aznew SwapChain;
  43. }
  44. XR::Ptr<SwapChain::Image> SwapChain::Image::Create()
  45. {
  46. return aznew SwapChain::Image;
  47. }
  48. XR::Ptr<SwapChain::View> SwapChain::View::Create()
  49. {
  50. return aznew SwapChain::View;
  51. }
  52. AZ::RHI::ResultCode SwapChain::View::Init(XrSwapchain handle, AZ::u32 width, AZ::u32 height)
  53. {
  54. m_handle = handle;
  55. m_width = width;
  56. m_height = height;
  57. return AZ::RHI::ResultCode::Success;
  58. }
  59. AZ::u32 SwapChain::View::GetCurrentImageIndex() const
  60. {
  61. return m_activeImageIndex;
  62. }
  63. AZ::RHI::ResultCode SwapChain::Image::Init(XrSwapchainImageVulkan2KHR swapchainImage)
  64. {
  65. m_swapchainImage = swapchainImage;
  66. return AZ::RHI::ResultCode::Success;
  67. }
  68. VkImage SwapChain::Image::GetNativeImage()
  69. {
  70. return m_swapchainImage.image;
  71. }
  72. XrSwapchain SwapChain::View::GetSwapChainHandle() const
  73. {
  74. return m_handle;
  75. }
  76. AZ::u32 SwapChain::View::GetWidth() const
  77. {
  78. return m_width;
  79. }
  80. AZ::u32 SwapChain::View::GetHeight() const
  81. {
  82. return m_height;
  83. }
  84. void SwapChain::View::Shutdown()
  85. {
  86. xrDestroySwapchain(m_handle);
  87. }
  88. AZ::RHI::ResultCode SwapChain::InitInternal()
  89. {
  90. Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  91. Session* xrVkSession = static_cast<Session*>(GetDescriptor().m_session.get());
  92. Device* xrDevice = static_cast<Device*>(GetDescriptor().m_device.get());
  93. XrInstance xrInstance = xrVkInstance->GetXRInstance();
  94. XrSystemId xrSystemId = xrVkInstance->GetXRSystemId();
  95. XrSession xrSession = xrVkSession->GetXrSession();
  96. // Read graphics properties for preferred swapchain length and logging.
  97. XrSystemProperties systemProperties{ XR_TYPE_SYSTEM_PROPERTIES };
  98. XrResult result = xrGetSystemProperties(xrInstance, xrSystemId, &systemProperties);
  99. WARN_IF_UNSUCCESSFUL(result);
  100. if(GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  101. {
  102. // Log system properties.
  103. AZ_Printf("OpenXRVk", "System Properties: Name=%s VendorId=%d\n", systemProperties.systemName, systemProperties.vendorId);
  104. AZ_Printf("OpenXRVk",
  105. "System Graphics Properties: MaxWidth=%d MaxHeight=%d MaxLayers=%d\n",
  106. systemProperties.graphicsProperties.maxSwapchainImageWidth, systemProperties.graphicsProperties.maxSwapchainImageHeight,
  107. systemProperties.graphicsProperties.maxLayerCount);
  108. AZ_Printf("OpenXRVk",
  109. "System Tracking Properties: OrientationTracking=%s PositionTracking=%s\n",
  110. systemProperties.trackingProperties.orientationTracking == XR_TRUE ? "True" : "False",
  111. systemProperties.trackingProperties.positionTracking == XR_TRUE ? "True" : "False");
  112. }
  113. //Only supporting XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO for now
  114. XrViewConfigurationType viewConfigType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
  115. result = xrEnumerateViewConfigurationViews(xrInstance, xrSystemId,
  116. viewConfigType, 0, &m_numViews, nullptr);
  117. WARN_IF_UNSUCCESSFUL(result);
  118. m_configViews.resize(m_numViews, { XR_TYPE_VIEW_CONFIGURATION_VIEW });
  119. result = xrEnumerateViewConfigurationViews(xrInstance, xrSystemId,
  120. viewConfigType, m_numViews, &m_numViews, m_configViews.data());
  121. WARN_IF_UNSUCCESSFUL(result);
  122. // Create and cache view buffer for xrLocateViews later.
  123. xrDevice->InitXrViews(m_numViews);
  124. // Create the swapchain and get the images.
  125. if (m_numViews > 0)
  126. {
  127. // Select a swapchain format.
  128. uint32_t swapchainFormatCount = 0;
  129. result = xrEnumerateSwapchainFormats(xrSession, 0, &swapchainFormatCount, nullptr);
  130. AZStd::vector<int64_t> swapChainFormats(swapchainFormatCount);
  131. result = xrEnumerateSwapchainFormats(xrSession, aznumeric_cast<uint32_t>(swapChainFormats.size()),
  132. &swapchainFormatCount, swapChainFormats.data());
  133. WARN_IF_UNSUCCESSFUL(result);
  134. AZ_Assert(swapchainFormatCount == swapChainFormats.size(), "Size mismatch swapchainFormatCount %i swapChainFormats size %i", swapchainFormatCount, swapChainFormats.size());
  135. m_colorSwapChainFormat = SelectColorSwapChainFormat(swapChainFormats);
  136. // Print swapchain formats and the selected one.
  137. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  138. {
  139. AZStd::string swapchainFormatsString;
  140. for (int64_t format : swapChainFormats)
  141. {
  142. const bool selected = format == static_cast<int64_t>(m_colorSwapChainFormat);
  143. swapchainFormatsString += " ";
  144. if (selected)
  145. {
  146. swapchainFormatsString += "[";
  147. }
  148. swapchainFormatsString += AZStd::string::format("%" PRId64, format);
  149. if (selected)
  150. {
  151. swapchainFormatsString += "]";
  152. }
  153. }
  154. AZ_Printf("OpenXRVk", "Swapchain Formats: %s\n", swapchainFormatsString.c_str());
  155. }
  156. // Create a swapchain for each view.
  157. for (uint32_t i = 0; i < m_numViews; i++)
  158. {
  159. const XrViewConfigurationView& configView = m_configViews[i];
  160. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  161. {
  162. AZ_Printf("OpenXRVk",
  163. "Creating swapchain for view %d with dimensions Width=%d Height=%d SampleCount=%d\n", i,
  164. configView.recommendedImageRectWidth, configView.recommendedImageRectHeight, configView.recommendedSwapchainSampleCount);
  165. }
  166. XR::Ptr<XR::SwapChain::View> baseViewSwapChain = XR::Factory::Get().CreateSwapChainView();
  167. SwapChain::View* viewSwapChain = static_cast<SwapChain::View*>(baseViewSwapChain.get());
  168. if (viewSwapChain)
  169. {
  170. // Create the xr swapchain.
  171. XrSwapchainCreateInfo swapchainCreateInfo{ XR_TYPE_SWAPCHAIN_CREATE_INFO };
  172. swapchainCreateInfo.arraySize = m_arraySize;
  173. swapchainCreateInfo.format = static_cast<int64_t>(m_colorSwapChainFormat);
  174. swapchainCreateInfo.width = configView.recommendedImageRectWidth;
  175. swapchainCreateInfo.height = configView.recommendedImageRectHeight;
  176. swapchainCreateInfo.mipCount = m_mipCount;
  177. swapchainCreateInfo.faceCount = m_faceCount;
  178. swapchainCreateInfo.sampleCount = m_sampleCount;
  179. swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
  180. XrSwapchain handle = XR_NULL_HANDLE;
  181. result = xrCreateSwapchain(xrSession, &swapchainCreateInfo, &handle);
  182. WARN_IF_UNSUCCESSFUL(result);
  183. AZ::RHI::ResultCode resultCode = viewSwapChain->Init(handle, swapchainCreateInfo.width, swapchainCreateInfo.height);
  184. if(resultCode == AZ::RHI::ResultCode::Success)
  185. {
  186. m_viewSwapchains.push_back(viewSwapChain);
  187. }
  188. }
  189. result = xrEnumerateSwapchainImages(viewSwapChain->GetSwapChainHandle(), 0, &viewSwapChain->m_numImages, nullptr);
  190. WARN_IF_UNSUCCESSFUL(result);
  191. viewSwapChain->m_swapChainImageHeaders.resize(viewSwapChain->m_numImages);
  192. viewSwapChain->m_swapchainImages.resize(viewSwapChain->m_numImages);
  193. for (AZ::u32 j = 0; j < viewSwapChain->m_numImages; ++j)
  194. {
  195. viewSwapChain->m_swapchainImages[j] = { XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR };
  196. viewSwapChain->m_swapChainImageHeaders[j] = reinterpret_cast<XrSwapchainImageBaseHeader*>(&viewSwapChain->m_swapchainImages[j]);
  197. }
  198. result = xrEnumerateSwapchainImages(viewSwapChain->GetSwapChainHandle(), viewSwapChain->m_numImages, &viewSwapChain->m_numImages, viewSwapChain->m_swapChainImageHeaders[0]);
  199. WARN_IF_UNSUCCESSFUL(result);
  200. for (uint32_t j = 0; j < viewSwapChain->m_numImages; ++j)
  201. {
  202. XR::Ptr<XR::SwapChain::Image> baseViewSwapChainImage = XR::Factory::Get().CreateSwapChainImage();
  203. SwapChain::Image* viewSwapChainImage = static_cast<SwapChain::Image*>(baseViewSwapChainImage.get());
  204. AZ::RHI::ResultCode resultCode = viewSwapChainImage->Init(viewSwapChain->m_swapchainImages[j]);
  205. if (resultCode == AZ::RHI::ResultCode::Success)
  206. {
  207. viewSwapChain->m_images.push_back(baseViewSwapChainImage);
  208. }
  209. }
  210. }
  211. }
  212. return AZ::RHI::ResultCode::Success;
  213. }
  214. VkFormat SwapChain::SelectColorSwapChainFormat(const AZStd::vector<int64_t>& runtimeFormats) const
  215. {
  216. // List of supported color swapchain formats.
  217. constexpr int64_t SupportedColorSwapchainFormats[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM };
  218. auto swapchainFormatIt =
  219. AZStd::find_first_of(runtimeFormats.begin(), runtimeFormats.end(), AZStd::begin(SupportedColorSwapchainFormats),
  220. AZStd::end(SupportedColorSwapchainFormats));
  221. if (swapchainFormatIt == runtimeFormats.end())
  222. {
  223. AZ_Error("OpenXRVk", false, "No runtime swapchain format supported for color swapchain");
  224. return VK_FORMAT_UNDEFINED;
  225. }
  226. return static_cast<VkFormat>(*swapchainFormatIt);
  227. }
  228. AZStd::vector<XrViewConfigurationView> SwapChain::GetViewConfigs() const
  229. {
  230. return m_configViews;
  231. }
  232. AZ::RHI::ResultCode SwapChain::GetSwapChainImage(AZ::RHI::XRSwapChainDescriptor* swapchainDescriptor) const
  233. {
  234. AZ::Vulkan::XRSwapChainDescriptor* xrSwapChainDescriptor = static_cast<AZ::Vulkan::XRSwapChainDescriptor*>(swapchainDescriptor);
  235. uint32_t swapChainIndex = xrSwapChainDescriptor->m_inputData.m_swapChainIndex;
  236. uint32_t swapChainImageIndex = xrSwapChainDescriptor->m_inputData.m_swapChainImageIndex;
  237. XR::SwapChain::View* viewSwapChain = GetView(swapChainIndex);
  238. SwapChain::Image* swapchainImage = static_cast<SwapChain::Image*>(viewSwapChain->m_images[swapChainImageIndex].get());
  239. xrSwapChainDescriptor->m_outputData.m_nativeImage = swapchainImage->GetNativeImage();
  240. return AZ::RHI::ResultCode::Success;
  241. }
  242. AZ::u32 SwapChain::GetSwapChainWidth(AZ::u32 viewIndex) const
  243. {
  244. return m_configViews[viewIndex].recommendedImageRectWidth;
  245. }
  246. AZ::u32 SwapChain::GetSwapChainHeight(AZ::u32 viewIndex) const
  247. {
  248. return m_configViews[viewIndex].recommendedImageRectHeight;
  249. }
  250. AZ::RHI::Format SwapChain::GetSwapChainFormat([[maybe_unused]] AZ::u32 viewIndex) const
  251. {
  252. return AZ::Vulkan::ConvertFormat(m_colorSwapChainFormat);
  253. }
  254. void SwapChain::ShutdownInternal()
  255. {
  256. for(XR::Ptr<XR::SwapChain::View> viewSwapChain : m_viewSwapchains)
  257. {
  258. viewSwapChain->Shutdown();
  259. }
  260. }
  261. }