OpenXRVkSession.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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/OpenXRVkSession.h>
  9. #include <OpenXRVk/OpenXRVkDevice.h>
  10. #include <OpenXRVk/OpenXRVkInput.h>
  11. #include <OpenXRVk/OpenXRVkInstance.h>
  12. #include <OpenXRVk/OpenXRVkSpace.h>
  13. #include <OpenXRVk/OpenXRVkUtils.h>
  14. #include <AzCore/Debug/Trace.h>
  15. #include <AzCore/Casting/numeric_cast.h>
  16. #include <XR/XRBase.h>
  17. namespace OpenXRVk
  18. {
  19. XR::Ptr<Session> Session::Create()
  20. {
  21. return aznew Session;
  22. }
  23. AZ::RHI::ResultCode Session::InitInternal(AZ::RHI::XRSessionDescriptor* descriptor)
  24. {
  25. AZ::Vulkan::XRSessionDescriptor* sessionDescriptor = static_cast<AZ::Vulkan::XRSessionDescriptor*>(descriptor);
  26. Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  27. Device* xrVkDevice = static_cast<Device*>(GetDescriptor().m_device.get());
  28. m_xrInstance = xrVkInstance->GetXRInstance();
  29. AZ_Printf("OpenXRVk", "Creating session...\n");
  30. m_graphicsBinding.instance = xrVkInstance->GetNativeInstance();
  31. m_graphicsBinding.physicalDevice = xrVkInstance->GetActivePhysicalDevice();
  32. m_graphicsBinding.device = xrVkDevice->GetNativeDevice();
  33. m_graphicsBinding.queueFamilyIndex = sessionDescriptor->m_inputData.m_graphicsBinding.m_queueFamilyIndex;
  34. m_graphicsBinding.queueIndex = sessionDescriptor->m_inputData.m_graphicsBinding.m_queueIndex;
  35. AZ_Assert(m_xrInstance != XR_NULL_HANDLE, "XR instance is null.");
  36. AZ_Assert(m_session == XR_NULL_HANDLE, "XR session is already initialized.");
  37. XrSessionCreateInfo createInfo{ XR_TYPE_SESSION_CREATE_INFO };
  38. createInfo.next = reinterpret_cast<const XrBaseInStructure*>(&m_graphicsBinding);
  39. createInfo.systemId = xrVkInstance->GetXRSystemId();
  40. XrResult result = xrCreateSession(m_xrInstance, &createInfo, &m_session);
  41. ASSERT_IF_UNSUCCESSFUL(result);
  42. LogReferenceSpaces();
  43. Input* xrVkInput = static_cast<Input*>(GetInput());
  44. xrVkInput->InitializeActionSpace(m_session);
  45. xrVkInput->InitializeActionSets(m_session);
  46. Space* xrVkSpace = static_cast<Space*>(GetSpace());
  47. xrVkSpace->CreateVisualizedSpaces(m_session);
  48. return ConvertResult(result);
  49. }
  50. void Session::LogReferenceSpaces()
  51. {
  52. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  53. {
  54. AZ_Warning("OpenXrVK", m_session != XR_NULL_HANDLE, "Session is not initialized");
  55. if (m_session == XR_NULL_HANDLE)
  56. {
  57. return;
  58. }
  59. uint32_t spaceCount = 0;
  60. XrResult result = xrEnumerateReferenceSpaces(m_session, 0, &spaceCount, nullptr);
  61. WARN_IF_UNSUCCESSFUL(result);
  62. AZStd::vector<XrReferenceSpaceType> spaces(spaceCount);
  63. result = xrEnumerateReferenceSpaces(m_session, spaceCount, &spaceCount, spaces.data());
  64. AZ_Printf("OpenXRVk", "Available reference spaces: %d\n", spaceCount);
  65. for (XrReferenceSpaceType space : spaces)
  66. {
  67. AZ_Printf("OpenXRVk", " Name: %s\n", to_string(space));
  68. }
  69. }
  70. }
  71. void Session::HandleSessionStateChangedEvent(const XrEventDataSessionStateChanged& stateChangedEvent)
  72. {
  73. Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
  74. const XrSessionState oldState = m_sessionState;
  75. m_sessionState = stateChangedEvent.state;
  76. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  77. {
  78. AZ_Printf(
  79. "OpenXRVk",
  80. "XrEventDataSessionStateChanged: state %s->%s session=%lld time=%lld\n", to_string(oldState), to_string(m_sessionState),
  81. stateChangedEvent.session, stateChangedEvent.time);
  82. }
  83. if ((stateChangedEvent.session != XR_NULL_HANDLE) && (stateChangedEvent.session != m_session))
  84. {
  85. AZ_Printf("OpenXRVk", "XrEventDataSessionStateChanged for unknown session\n");
  86. return;
  87. }
  88. switch (m_sessionState)
  89. {
  90. case XR_SESSION_STATE_READY:
  91. {
  92. AZ_Assert(m_session != XR_NULL_HANDLE, "Session is null");
  93. XrSessionBeginInfo sessionBeginInfo{ XR_TYPE_SESSION_BEGIN_INFO };
  94. sessionBeginInfo.primaryViewConfigurationType = xrVkInstance->GetViewConfigType();
  95. XrResult result = xrBeginSession(m_session, &sessionBeginInfo);
  96. WARN_IF_UNSUCCESSFUL(result);
  97. m_sessionRunning = true;
  98. break;
  99. }
  100. case XR_SESSION_STATE_STOPPING:
  101. {
  102. AZ_Assert(m_session != XR_NULL_HANDLE, "Session is null");
  103. m_sessionRunning = false;
  104. XrResult result = xrEndSession(m_session);
  105. WARN_IF_UNSUCCESSFUL(result);
  106. break;
  107. }
  108. case XR_SESSION_STATE_EXITING:
  109. {
  110. m_exitRenderLoop = true;
  111. // Do not attempt to restart because user closed this session.
  112. m_requestRestart = false;
  113. break;
  114. }
  115. case XR_SESSION_STATE_LOSS_PENDING:
  116. {
  117. m_exitRenderLoop = true;
  118. // Poll for a new instance.
  119. m_requestRestart = true;
  120. break;
  121. }
  122. default:
  123. {
  124. break;
  125. }
  126. }
  127. }
  128. const XrEventDataBaseHeader* Session::TryReadNextEvent()
  129. {
  130. XrEventDataBaseHeader* baseHeader = reinterpret_cast<XrEventDataBaseHeader*>(&m_eventDataBuffer);
  131. *baseHeader = { XR_TYPE_EVENT_DATA_BUFFER };
  132. const XrResult result = xrPollEvent(m_xrInstance, &m_eventDataBuffer);
  133. if (result == XR_SUCCESS)
  134. {
  135. if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST)
  136. {
  137. [[maybe_unused]] const XrEventDataEventsLost* const eventsLost = reinterpret_cast<const XrEventDataEventsLost*>(baseHeader);
  138. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  139. {
  140. AZ_Printf("OpenXrVK", "%d events lost\n", eventsLost->lostEventCount);
  141. }
  142. }
  143. return baseHeader;
  144. }
  145. if (result == XR_EVENT_UNAVAILABLE)
  146. {
  147. return nullptr;
  148. }
  149. WARN_IF_UNSUCCESSFUL(result);
  150. return nullptr;
  151. }
  152. void Session::PollEvents()
  153. {
  154. m_exitRenderLoop = m_requestRestart = false;
  155. // Process all pending messages.
  156. while (const XrEventDataBaseHeader* event = TryReadNextEvent())
  157. {
  158. switch (event->type)
  159. {
  160. case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
  161. {
  162. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  163. {
  164. [[maybe_unused]] const auto& instanceLossPending = *reinterpret_cast<const XrEventDataInstanceLossPending*>(event);
  165. AZ_Printf("OpenXRVk", "XrEventDataInstanceLossPending by %lld\n", instanceLossPending.lossTime);
  166. }
  167. m_exitRenderLoop = true;
  168. m_requestRestart = true;
  169. return;
  170. }
  171. case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
  172. {
  173. auto sessionStateChangedEvent = *reinterpret_cast<const XrEventDataSessionStateChanged*>(event);
  174. HandleSessionStateChangedEvent(sessionStateChangedEvent);
  175. break;
  176. }
  177. case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
  178. {
  179. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  180. {
  181. Input* xrVkInput = static_cast<Input*>(GetInput());
  182. LogActionSourceName(xrVkInput->GetGrabAction(), "Grab");
  183. LogActionSourceName(xrVkInput->GetQuitAction(), "Quit");
  184. LogActionSourceName(xrVkInput->GetPoseAction(), "Pose");
  185. LogActionSourceName(xrVkInput->GetVibrationAction(), "Vibrate");
  186. }
  187. break;
  188. }
  189. case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
  190. [[fallthrough]];
  191. default:
  192. {
  193. if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
  194. {
  195. AZ_Printf("OpenXRVk", "Ignoring event type %d\n", event->type);
  196. }
  197. break;
  198. }
  199. }
  200. }
  201. }
  202. void Session::LogActionSourceName(XrAction action, const AZStd::string_view actionName) const
  203. {
  204. XrBoundSourcesForActionEnumerateInfo getInfo = { XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO };
  205. getInfo.action = action;
  206. uint32_t pathCount = 0;
  207. XrResult result = xrEnumerateBoundSourcesForAction(m_session, &getInfo, 0, &pathCount, nullptr);
  208. WARN_IF_UNSUCCESSFUL(result);
  209. AZStd::vector<XrPath> paths(pathCount);
  210. result = xrEnumerateBoundSourcesForAction(m_session, &getInfo, aznumeric_cast<uint32_t>(paths.size()), &pathCount, paths.data());
  211. WARN_IF_UNSUCCESSFUL(result);
  212. AZStd::string sourceName;
  213. for (uint32_t i = 0; i < pathCount; ++i)
  214. {
  215. constexpr XrInputSourceLocalizedNameFlags all = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
  216. XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT | XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
  217. XrInputSourceLocalizedNameGetInfo nameInfo = { XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO };
  218. nameInfo.sourcePath = paths[i];
  219. nameInfo.whichComponents = all;
  220. uint32_t size = 0;
  221. result = xrGetInputSourceLocalizedName(m_session, &nameInfo, 0, &size, nullptr);
  222. WARN_IF_UNSUCCESSFUL(result);
  223. if (size < 1)
  224. {
  225. continue;
  226. }
  227. AZStd::vector<char> grabSource(size);
  228. result = xrGetInputSourceLocalizedName(m_session, &nameInfo, uint32_t(grabSource.size()), &size, grabSource.data());
  229. WARN_IF_UNSUCCESSFUL(result);
  230. if (!sourceName.empty())
  231. {
  232. sourceName += " and ";
  233. }
  234. sourceName += "'";
  235. sourceName += AZStd::string(grabSource.data(), size - 1);
  236. sourceName += "'";
  237. }
  238. AZ_Printf("OpenXrVK",
  239. "%s action is bound to %s\n", actionName.data(), ((!sourceName.empty()) ? sourceName.c_str() : "nothing"));
  240. }
  241. void Session::LocateControllerSpace(AZ::u32 handIndex)
  242. {
  243. Input* xrInput = static_cast<Input*>(GetInput());
  244. Device* device = static_cast<Device*>(GetDescriptor().m_device.get());
  245. Space* space = static_cast<Space*>(GetSpace());
  246. xrInput->LocateControllerSpace(device->GetPredictedDisplayTime(), space->GetXrSpace(OpenXRVk::SpaceType::View), handIndex);
  247. }
  248. AZ::RPI::PoseData Session::GetControllerPose(AZ::u32 handIndex) const
  249. {
  250. Input* xrInput = static_cast<Input*>(GetInput());
  251. return xrInput->GetControllerPose(handIndex);
  252. }
  253. float Session::GetControllerScale(AZ::u32 handIndex) const
  254. {
  255. Input* xrInput = static_cast<Input*>(GetInput());
  256. return xrInput->GetControllerScale(handIndex);
  257. }
  258. AZ::RPI::PoseData Session::GetViewFrontPose() const
  259. {
  260. Input* xrInput = static_cast<Input*>(GetInput());
  261. return xrInput->GetVisualizedSpacePose(OpenXRVk::SpaceType::ViewFront);
  262. }
  263. XrSession Session::GetXrSession() const
  264. {
  265. return m_session;
  266. }
  267. XrSpace Session::GetXrSpace(SpaceType spaceType) const
  268. {
  269. Space* space = static_cast<Space*>(GetSpace());
  270. return space->GetXrSpace(spaceType);
  271. }
  272. bool Session::IsSessionRunning() const
  273. {
  274. return m_sessionRunning;
  275. }
  276. bool Session::IsSessionFocused() const
  277. {
  278. return m_sessionState == XR_SESSION_STATE_FOCUSED;
  279. }
  280. bool Session::IsRestartRequested() const
  281. {
  282. return m_requestRestart;
  283. }
  284. bool Session::IsExitRenderLoopRequested() const
  285. {
  286. return m_exitRenderLoop;
  287. }
  288. void Session::ShutdownInternal()
  289. {
  290. if (m_session != XR_NULL_HANDLE)
  291. {
  292. xrDestroySession(m_session);
  293. }
  294. }
  295. }