OpenXRVkSession.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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 <AzCore/Debug/Trace.h>
  9. #include <AzCore/Casting/numeric_cast.h>
  10. #include <XR/XRBase.h>
  11. #include <OpenXRVk/OpenXRVkDevice.h>
  12. #include <OpenXRVk/OpenXRVkInput.h>
  13. #include <OpenXRVk/OpenXRVkInstance.h>
  14. #include <OpenXRVk/OpenXRVkSpace.h>
  15. #include <OpenXRVk/OpenXRVkUtils.h>
  16. #include <OpenXRVk/OpenXRVkSession.h>
  17. #include <Atom/RHI.Reflect/Vulkan/XRVkDescriptors.h>
  18. #include <Atom/RPI.Public/XR/XRSpaceNotificationBus.h>
  19. #include "OpenXRVkReferenceSpacesManager.h"
  20. #include "OpenXRVkActionsManager.h"
  21. namespace OpenXRVk
  22. {
  23. XR::Ptr<Session> Session::Create()
  24. {
  25. return aznew Session;
  26. }
  27. AZ::RHI::ResultCode Session::InitInternal([[maybe_unused]] AZ::RHI::XRSessionDescriptor* descriptor)
  28. {
  29. Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  30. Device* xrVkDevice = static_cast<Device*>(GetDescriptor().m_device.get());
  31. auto graphicBinding = xrVkDevice->GetGraphicsBinding(AZ::RHI::HardwareQueueClass::Graphics);
  32. m_xrInstance = xrVkInstance->GetXRInstance();
  33. AZ_Printf("OpenXRVk", "Creating session...\n");
  34. m_graphicsBinding.instance = xrVkInstance->GetNativeInstance();
  35. m_graphicsBinding.physicalDevice = xrVkDevice->GetNativePhysicalDevice();
  36. m_graphicsBinding.device = xrVkDevice->GetNativeDevice();
  37. m_graphicsBinding.queueFamilyIndex = graphicBinding.m_queueFamilyIndex;
  38. m_graphicsBinding.queueIndex = graphicBinding.m_queueIndex;
  39. AZ_Assert(m_xrInstance != XR_NULL_HANDLE, "XR instance is null.");
  40. AZ_Assert(m_session == XR_NULL_HANDLE, "XR session is already initialized.");
  41. XrSessionCreateInfo createInfo{ XR_TYPE_SESSION_CREATE_INFO };
  42. createInfo.next = reinterpret_cast<const XrBaseInStructure*>(&m_graphicsBinding);
  43. createInfo.systemId = xrVkInstance->GetXRSystemId();
  44. XrResult result = xrCreateSession(m_xrInstance, &createInfo, &m_session);
  45. ASSERT_IF_UNSUCCESSFUL(result);
  46. m_referenceSpacesMgr = AZStd::make_unique<ReferenceSpacesManager>();
  47. bool success = m_referenceSpacesMgr->Init(m_xrInstance, m_session, xrVkInstance->GetViewConfigType(), xrVkInstance->GetViewCount());
  48. AZ_Error("OpenXRVk::Session", success, "Failed to instantiate the visualized Spaces manager.");
  49. m_actionsMgr = AZStd::make_unique<ActionsManager>();
  50. success = m_actionsMgr->Init(m_xrInstance, m_session);
  51. AZ_Error("OpenXRVk::Session", success, "Failed to instantiate the actions manager");
  52. LogReferenceSpaces();
  53. return ConvertResult(result);
  54. }
  55. void Session::LogReferenceSpaces()
  56. {
  57. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  58. {
  59. AZ_Warning("OpenXrVK", m_session != XR_NULL_HANDLE, "Session is not initialized");
  60. if (m_session == XR_NULL_HANDLE)
  61. {
  62. return;
  63. }
  64. uint32_t spaceCount = 0;
  65. XrResult result = xrEnumerateReferenceSpaces(m_session, 0, &spaceCount, nullptr);
  66. WARN_IF_UNSUCCESSFUL(result);
  67. AZStd::vector<XrReferenceSpaceType> spaces(spaceCount);
  68. result = xrEnumerateReferenceSpaces(m_session, spaceCount, &spaceCount, spaces.data());
  69. AZ_Printf("OpenXRVk", "Available reference spaces: %d\n", spaceCount);
  70. for (XrReferenceSpaceType space : spaces)
  71. {
  72. AZ_Printf("OpenXRVk", " Name: %s\n", to_string(space));
  73. }
  74. }
  75. }
  76. void Session::HandleSessionStateChangedEvent(const XrEventDataSessionStateChanged& stateChangedEvent)
  77. {
  78. Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  79. const XrSessionState oldState = m_sessionState;
  80. m_sessionState = stateChangedEvent.state;
  81. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  82. {
  83. AZ_Printf(
  84. "OpenXRVk",
  85. "XrEventDataSessionStateChanged: state %s->%s session=%lld time=%lld\n", to_string(oldState), to_string(m_sessionState),
  86. stateChangedEvent.session, stateChangedEvent.time);
  87. }
  88. if ((stateChangedEvent.session != XR_NULL_HANDLE) && (stateChangedEvent.session != m_session))
  89. {
  90. AZ_Printf("OpenXRVk", "XrEventDataSessionStateChanged for unknown session\n");
  91. return;
  92. }
  93. switch (m_sessionState)
  94. {
  95. case XR_SESSION_STATE_READY:
  96. {
  97. AZ_Assert(m_session != XR_NULL_HANDLE, "Session is null");
  98. XrSessionBeginInfo sessionBeginInfo{ XR_TYPE_SESSION_BEGIN_INFO };
  99. sessionBeginInfo.primaryViewConfigurationType = xrVkInstance->GetViewConfigType();
  100. XrResult result = xrBeginSession(m_session, &sessionBeginInfo);
  101. WARN_IF_UNSUCCESSFUL(result);
  102. m_sessionRunning = true;
  103. m_referenceSpacesMgr->OnSessionReady();
  104. break;
  105. }
  106. case XR_SESSION_STATE_STOPPING:
  107. {
  108. AZ_Assert(m_session != XR_NULL_HANDLE, "Session is null");
  109. m_sessionRunning = false;
  110. XrResult result = xrEndSession(m_session);
  111. WARN_IF_UNSUCCESSFUL(result);
  112. break;
  113. }
  114. case XR_SESSION_STATE_EXITING:
  115. {
  116. m_exitRenderLoop = true;
  117. // Do not attempt to restart because user closed this session.
  118. m_requestRestart = false;
  119. break;
  120. }
  121. case XR_SESSION_STATE_LOSS_PENDING:
  122. {
  123. m_exitRenderLoop = true;
  124. // Poll for a new instance.
  125. m_requestRestart = true;
  126. break;
  127. }
  128. default:
  129. {
  130. break;
  131. }
  132. }
  133. }
  134. const XrEventDataBaseHeader* Session::TryReadNextEvent()
  135. {
  136. XrEventDataBaseHeader* baseHeader = reinterpret_cast<XrEventDataBaseHeader*>(&m_eventDataBuffer);
  137. *baseHeader = { XR_TYPE_EVENT_DATA_BUFFER };
  138. const XrResult result = xrPollEvent(m_xrInstance, &m_eventDataBuffer);
  139. if (result == XR_SUCCESS)
  140. {
  141. if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST)
  142. {
  143. [[maybe_unused]] const XrEventDataEventsLost* const eventsLost = reinterpret_cast<const XrEventDataEventsLost*>(baseHeader);
  144. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  145. {
  146. AZ_Printf("OpenXrVK", "%d events lost\n", eventsLost->lostEventCount);
  147. }
  148. }
  149. return baseHeader;
  150. }
  151. if (result == XR_EVENT_UNAVAILABLE)
  152. {
  153. return nullptr;
  154. }
  155. WARN_IF_UNSUCCESSFUL(result);
  156. return nullptr;
  157. }
  158. void Session::PollEvents()
  159. {
  160. m_exitRenderLoop = m_requestRestart = false;
  161. // Process all pending messages.
  162. while (const XrEventDataBaseHeader* event = TryReadNextEvent())
  163. {
  164. switch (event->type)
  165. {
  166. case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
  167. {
  168. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  169. {
  170. [[maybe_unused]] const auto& instanceLossPending = *reinterpret_cast<const XrEventDataInstanceLossPending*>(event);
  171. AZ_Printf("OpenXRVk", "XrEventDataInstanceLossPending by %lld\n", instanceLossPending.lossTime);
  172. }
  173. m_exitRenderLoop = true;
  174. m_requestRestart = true;
  175. return;
  176. }
  177. case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
  178. {
  179. auto sessionStateChangedEvent = *reinterpret_cast<const XrEventDataSessionStateChanged*>(event);
  180. HandleSessionStateChangedEvent(sessionStateChangedEvent);
  181. break;
  182. }
  183. case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
  184. {
  185. m_actionsMgr->OnInteractionProfileChanged();
  186. break;
  187. }
  188. case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
  189. [[fallthrough]];
  190. default:
  191. {
  192. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  193. {
  194. AZ_Printf("OpenXRVk", "Ignoring event type %d\n", event->type);
  195. }
  196. break;
  197. }
  198. }
  199. }
  200. }
  201. void Session::SetBaseSpaceTypeForVisualization(SpaceType spaceType)
  202. {
  203. m_baseSpaceTypeForVisualization = spaceType;
  204. }
  205. void Session::SetBaseSpaceTypeForControllers(SpaceType spaceType)
  206. {
  207. m_baseSpaceTypeForControllers = spaceType;
  208. }
  209. SpaceType Session::GetBaseSpaceTypeForVisualization() const
  210. {
  211. return m_baseSpaceTypeForVisualization;
  212. }
  213. SpaceType Session::GetBaseSpaceTypeForControllers() const
  214. {
  215. return m_baseSpaceTypeForControllers;
  216. }
  217. void Session::LogActionSourceName(XrAction action, const AZStd::string_view actionName) const
  218. {
  219. XrBoundSourcesForActionEnumerateInfo getInfo = { XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO };
  220. getInfo.action = action;
  221. uint32_t pathCount = 0;
  222. XrResult result = xrEnumerateBoundSourcesForAction(m_session, &getInfo, 0, &pathCount, nullptr);
  223. WARN_IF_UNSUCCESSFUL(result);
  224. AZStd::vector<XrPath> paths(pathCount);
  225. result = xrEnumerateBoundSourcesForAction(m_session, &getInfo, aznumeric_cast<uint32_t>(paths.size()), &pathCount, paths.data());
  226. WARN_IF_UNSUCCESSFUL(result);
  227. AZStd::string sourceName;
  228. for (uint32_t i = 0; i < pathCount; ++i)
  229. {
  230. constexpr XrInputSourceLocalizedNameFlags all = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
  231. XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT | XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
  232. XrInputSourceLocalizedNameGetInfo nameInfo = { XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO };
  233. nameInfo.sourcePath = paths[i];
  234. nameInfo.whichComponents = all;
  235. uint32_t size = 0;
  236. result = xrGetInputSourceLocalizedName(m_session, &nameInfo, 0, &size, nullptr);
  237. WARN_IF_UNSUCCESSFUL(result);
  238. if (size < 1)
  239. {
  240. continue;
  241. }
  242. AZStd::vector<char> grabSource(size);
  243. result = xrGetInputSourceLocalizedName(m_session, &nameInfo, uint32_t(grabSource.size()), &size, grabSource.data());
  244. WARN_IF_UNSUCCESSFUL(result);
  245. if (!sourceName.empty())
  246. {
  247. sourceName += " and ";
  248. }
  249. sourceName += "'";
  250. sourceName += AZStd::string(grabSource.data(), size - 1);
  251. sourceName += "'";
  252. }
  253. AZ_Printf("OpenXrVK",
  254. "%s action is bound to %s\n", actionName.data(), ((!sourceName.empty()) ? sourceName.c_str() : "nothing"));
  255. }
  256. void Session::LocateControllerSpace(AZ::u32 handIndex)
  257. {
  258. Input* xrInput = GetNativeInput();
  259. Device* device = static_cast<Device*>(GetDescriptor().m_device.get());
  260. Space* space = static_cast<Space*>(GetSpace());
  261. xrInput->LocateControllerSpace(device->GetPredictedDisplayTime(), space->GetXrSpace(OpenXRVk::SpaceType::View), handIndex);
  262. }
  263. AZ::RHI::ResultCode Session::GetControllerPose(AZ::u32 handIndex, AZ::RPI::PoseData& outPoseData) const
  264. {
  265. return GetNativeInput()->GetControllerPose(handIndex, outPoseData);
  266. }
  267. AZ::RHI::ResultCode Session::GetControllerTransform(AZ::u32 handIndex, AZ::Transform& outTransform) const
  268. {
  269. return GetNativeInput()->GetControllerTransform(handIndex, outTransform);
  270. }
  271. AZ::RHI::ResultCode Session::GetControllerStagePose(AZ::u32 handIndex, AZ::RPI::PoseData& outPoseData) const
  272. {
  273. Input* xrInput = GetNativeInput();
  274. return handIndex == 0 ? xrInput->GetVisualizedSpacePose(OpenXRVk::SpaceType::StageLeft, outPoseData) :
  275. xrInput->GetVisualizedSpacePose(OpenXRVk::SpaceType::StageRight, outPoseData);
  276. }
  277. AZ::RHI::ResultCode Session::GetViewFrontPose(AZ::RPI::PoseData& outPoseData) const
  278. {
  279. return GetNativeInput()->GetVisualizedSpacePose(OpenXRVk::SpaceType::ViewFront, outPoseData);
  280. }
  281. AZ::RHI::ResultCode Session::GetViewLocalPose(AZ::RPI::PoseData& outPoseData) const
  282. {
  283. return GetNativeInput()->GetVisualizedSpacePose(OpenXRVk::SpaceType::View, outPoseData);
  284. }
  285. float Session::GetControllerScale(AZ::u32 handIndex) const
  286. {
  287. return GetNativeInput()->GetControllerScale(handIndex);
  288. }
  289. float Session::GetSqueezeState(AZ::u32 handIndex) const
  290. {
  291. return GetNativeInput()->GetSqueezeState(handIndex);
  292. }
  293. float Session::GetTriggerState(AZ::u32 handIndex) const
  294. {
  295. return GetNativeInput()->GetTriggerState(handIndex);
  296. }
  297. float Session::GetXButtonState() const
  298. {
  299. return (GetNativeInput()->GetXButtonState() ? 1.f : 0.f);
  300. }
  301. float Session::GetYButtonState() const
  302. {
  303. return (GetNativeInput()->GetYButtonState() ? 1.f : 0.f);
  304. }
  305. float Session::GetAButtonState() const
  306. {
  307. return (GetNativeInput()->GetAButtonState() ? 1.f : 0.f);
  308. }
  309. float Session::GetBButtonState() const
  310. {
  311. return (GetNativeInput()->GetBButtonState() ? 1.f : 0.f);
  312. }
  313. float Session::GetXJoyStickState(AZ::u32 handIndex) const
  314. {
  315. return GetNativeInput()->GetXJoyStickState(handIndex);
  316. }
  317. float Session::GetYJoyStickState(AZ::u32 handIndex) const
  318. {
  319. return GetNativeInput()->GetYJoyStickState(handIndex);
  320. }
  321. XrSession Session::GetXrSession() const
  322. {
  323. return m_session;
  324. }
  325. XrSpace Session::GetXrSpace(SpaceType spaceType) const
  326. {
  327. Space* space = static_cast<Space*>(GetSpace());
  328. return space->GetXrSpace(spaceType);
  329. }
  330. const AZStd::vector<XrView>& Session::GetXrViews() const
  331. {
  332. return m_referenceSpacesMgr->GetXrViews();
  333. }
  334. XrSpace Session::GetViewSpaceXrSpace() const
  335. {
  336. return m_referenceSpacesMgr->GetViewSpaceXrSpace();
  337. }
  338. bool Session::IsSessionRunning() const
  339. {
  340. return m_sessionRunning;
  341. }
  342. bool Session::IsSessionFocused() const
  343. {
  344. return m_sessionState == XR_SESSION_STATE_FOCUSED;
  345. }
  346. bool Session::IsRestartRequested() const
  347. {
  348. return m_requestRestart;
  349. }
  350. bool Session::IsExitRenderLoopRequested() const
  351. {
  352. return m_exitRenderLoop;
  353. }
  354. void Session::ShutdownInternal()
  355. {
  356. if (m_session != XR_NULL_HANDLE)
  357. {
  358. xrDestroySession(m_session);
  359. }
  360. }
  361. Input* Session::GetNativeInput() const
  362. {
  363. return static_cast<Input*>(GetInput());
  364. }
  365. void Session::OnBeginFrame([[maybe_unused]] XrTime predictedDisplayTime)
  366. {
  367. if (IsSessionFocused())
  368. {
  369. // Syncing actions only works if the session is in focused state
  370. m_actionsMgr->SyncActions(predictedDisplayTime);
  371. }
  372. m_referenceSpacesMgr->SyncViews(predictedDisplayTime);
  373. //Notify the rest of the engine.
  374. const auto& viewPoses = m_referenceSpacesMgr->GetViewPoses();
  375. AZ::RPI::XRSpaceNotificationBus::Broadcast(&AZ::RPI::XRSpaceNotifications::OnXRSpaceLocationsChanged,
  376. m_referenceSpacesMgr->GetViewSpacePose(),
  377. viewPoses[0], viewPoses[1]);
  378. }
  379. }