123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <OpenXRVk/OpenXRVkSession.h>
- #include <OpenXRVk/OpenXRVkDevice.h>
- #include <OpenXRVk/OpenXRVkInput.h>
- #include <OpenXRVk/OpenXRVkInstance.h>
- #include <OpenXRVk/OpenXRVkSpace.h>
- #include <OpenXRVk/OpenXRVkUtils.h>
- #include <AzCore/Debug/Trace.h>
- #include <AzCore/Casting/numeric_cast.h>
- #include <XR/XRBase.h>
- namespace OpenXRVk
- {
- XR::Ptr<Session> Session::Create()
- {
- return aznew Session;
- }
- AZ::RHI::ResultCode Session::InitInternal(AZ::RHI::XRSessionDescriptor* descriptor)
- {
- AZ::Vulkan::XRSessionDescriptor* sessionDescriptor = static_cast<AZ::Vulkan::XRSessionDescriptor*>(descriptor);
- Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
- Device* xrVkDevice = static_cast<Device*>(GetDescriptor().m_device.get());
- m_xrInstance = xrVkInstance->GetXRInstance();
- AZ_Printf("OpenXRVk", "Creating session...\n");
- m_graphicsBinding.instance = xrVkInstance->GetNativeInstance();
- m_graphicsBinding.physicalDevice = xrVkInstance->GetActivePhysicalDevice();
- m_graphicsBinding.device = xrVkDevice->GetNativeDevice();
- m_graphicsBinding.queueFamilyIndex = sessionDescriptor->m_inputData.m_graphicsBinding.m_queueFamilyIndex;
- m_graphicsBinding.queueIndex = sessionDescriptor->m_inputData.m_graphicsBinding.m_queueIndex;
- AZ_Assert(m_xrInstance != XR_NULL_HANDLE, "XR instance is null.");
- AZ_Assert(m_session == XR_NULL_HANDLE, "XR session is already initialized.");
- XrSessionCreateInfo createInfo{ XR_TYPE_SESSION_CREATE_INFO };
- createInfo.next = reinterpret_cast<const XrBaseInStructure*>(&m_graphicsBinding);
- createInfo.systemId = xrVkInstance->GetXRSystemId();
- XrResult result = xrCreateSession(m_xrInstance, &createInfo, &m_session);
- ASSERT_IF_UNSUCCESSFUL(result);
-
- LogReferenceSpaces();
- Input* xrVkInput = static_cast<Input*>(GetInput());
- xrVkInput->InitializeActionSpace(m_session);
- xrVkInput->InitializeActionSets(m_session);
- Space* xrVkSpace = static_cast<Space*>(GetSpace());
- xrVkSpace->CreateVisualizedSpaces(m_session);
- return ConvertResult(result);
- }
- void Session::LogReferenceSpaces()
- {
- if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
- {
- AZ_Warning("OpenXrVK", m_session != XR_NULL_HANDLE, "Session is not initialized");
- if (m_session == XR_NULL_HANDLE)
- {
- return;
- }
- uint32_t spaceCount = 0;
- XrResult result = xrEnumerateReferenceSpaces(m_session, 0, &spaceCount, nullptr);
- WARN_IF_UNSUCCESSFUL(result);
- AZStd::vector<XrReferenceSpaceType> spaces(spaceCount);
- result = xrEnumerateReferenceSpaces(m_session, spaceCount, &spaceCount, spaces.data());
- AZ_Printf("OpenXRVk", "Available reference spaces: %d\n", spaceCount);
- for (XrReferenceSpaceType space : spaces)
- {
- AZ_Printf("OpenXRVk", " Name: %s\n", to_string(space));
- }
- }
- }
- void Session::HandleSessionStateChangedEvent(const XrEventDataSessionStateChanged& stateChangedEvent)
- {
- Instance* xrVkInstance = static_cast<Instance*>(GetDescriptor().m_instance.get());
- const XrSessionState oldState = m_sessionState;
- m_sessionState = stateChangedEvent.state;
- if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
- {
- AZ_Printf(
- "OpenXRVk",
- "XrEventDataSessionStateChanged: state %s->%s session=%lld time=%lld\n", to_string(oldState), to_string(m_sessionState),
- stateChangedEvent.session, stateChangedEvent.time);
- }
- if ((stateChangedEvent.session != XR_NULL_HANDLE) && (stateChangedEvent.session != m_session))
- {
- AZ_Printf("OpenXRVk", "XrEventDataSessionStateChanged for unknown session\n");
- return;
- }
- switch (m_sessionState)
- {
- case XR_SESSION_STATE_READY:
- {
- AZ_Assert(m_session != XR_NULL_HANDLE, "Session is null");
- XrSessionBeginInfo sessionBeginInfo{ XR_TYPE_SESSION_BEGIN_INFO };
- sessionBeginInfo.primaryViewConfigurationType = xrVkInstance->GetViewConfigType();
- XrResult result = xrBeginSession(m_session, &sessionBeginInfo);
- WARN_IF_UNSUCCESSFUL(result);
- m_sessionRunning = true;
- break;
- }
- case XR_SESSION_STATE_STOPPING:
- {
- AZ_Assert(m_session != XR_NULL_HANDLE, "Session is null");
- m_sessionRunning = false;
- XrResult result = xrEndSession(m_session);
- WARN_IF_UNSUCCESSFUL(result);
- break;
- }
- case XR_SESSION_STATE_EXITING:
- {
- m_exitRenderLoop = true;
- // Do not attempt to restart because user closed this session.
- m_requestRestart = false;
- break;
- }
- case XR_SESSION_STATE_LOSS_PENDING:
- {
- m_exitRenderLoop = true;
- // Poll for a new instance.
- m_requestRestart = true;
- break;
- }
- default:
- {
- break;
- }
- }
- }
-
- const XrEventDataBaseHeader* Session::TryReadNextEvent()
- {
- XrEventDataBaseHeader* baseHeader = reinterpret_cast<XrEventDataBaseHeader*>(&m_eventDataBuffer);
- *baseHeader = { XR_TYPE_EVENT_DATA_BUFFER };
- const XrResult result = xrPollEvent(m_xrInstance, &m_eventDataBuffer);
- if (result == XR_SUCCESS)
- {
- if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST)
- {
- [[maybe_unused]] const XrEventDataEventsLost* const eventsLost = reinterpret_cast<const XrEventDataEventsLost*>(baseHeader);
- if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
- {
- AZ_Printf("OpenXrVK", "%d events lost\n", eventsLost->lostEventCount);
- }
- }
- return baseHeader;
- }
- if (result == XR_EVENT_UNAVAILABLE)
- {
- return nullptr;
- }
- WARN_IF_UNSUCCESSFUL(result);
- return nullptr;
- }
- void Session::PollEvents()
- {
- m_exitRenderLoop = m_requestRestart = false;
- // Process all pending messages.
- while (const XrEventDataBaseHeader* event = TryReadNextEvent())
- {
- switch (event->type)
- {
- case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
- {
- if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
- {
- [[maybe_unused]] const auto& instanceLossPending = *reinterpret_cast<const XrEventDataInstanceLossPending*>(event);
- AZ_Printf("OpenXRVk", "XrEventDataInstanceLossPending by %lld\n", instanceLossPending.lossTime);
- }
- m_exitRenderLoop = true;
- m_requestRestart = true;
- return;
- }
- case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
- {
- auto sessionStateChangedEvent = *reinterpret_cast<const XrEventDataSessionStateChanged*>(event);
- HandleSessionStateChangedEvent(sessionStateChangedEvent);
- break;
- }
- case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
- {
- if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
- {
- Input* xrVkInput = static_cast<Input*>(GetInput());
- LogActionSourceName(xrVkInput->GetGrabAction(), "Grab");
- LogActionSourceName(xrVkInput->GetQuitAction(), "Quit");
- LogActionSourceName(xrVkInput->GetPoseAction(), "Pose");
- LogActionSourceName(xrVkInput->GetVibrationAction(), "Vibrate");
- }
- break;
- }
- case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
- [[fallthrough]];
- default:
- {
- if (GetDescriptor().m_validationMode == AZ::RHI::ValidationMode::Enabled)
- {
- AZ_Printf("OpenXRVk", "Ignoring event type %d\n", event->type);
- }
- break;
- }
- }
- }
- }
- void Session::LogActionSourceName(XrAction action, const AZStd::string_view actionName) const
- {
- XrBoundSourcesForActionEnumerateInfo getInfo = { XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO };
- getInfo.action = action;
- uint32_t pathCount = 0;
- XrResult result = xrEnumerateBoundSourcesForAction(m_session, &getInfo, 0, &pathCount, nullptr);
- WARN_IF_UNSUCCESSFUL(result);
- AZStd::vector<XrPath> paths(pathCount);
- result = xrEnumerateBoundSourcesForAction(m_session, &getInfo, aznumeric_cast<uint32_t>(paths.size()), &pathCount, paths.data());
- WARN_IF_UNSUCCESSFUL(result);
- AZStd::string sourceName;
- for (uint32_t i = 0; i < pathCount; ++i)
- {
- constexpr XrInputSourceLocalizedNameFlags all = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
- XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT | XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
- XrInputSourceLocalizedNameGetInfo nameInfo = { XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO };
- nameInfo.sourcePath = paths[i];
- nameInfo.whichComponents = all;
- uint32_t size = 0;
- result = xrGetInputSourceLocalizedName(m_session, &nameInfo, 0, &size, nullptr);
- WARN_IF_UNSUCCESSFUL(result);
- if (size < 1)
- {
- continue;
- }
- AZStd::vector<char> grabSource(size);
- result = xrGetInputSourceLocalizedName(m_session, &nameInfo, uint32_t(grabSource.size()), &size, grabSource.data());
- WARN_IF_UNSUCCESSFUL(result);
- if (!sourceName.empty())
- {
- sourceName += " and ";
- }
- sourceName += "'";
- sourceName += AZStd::string(grabSource.data(), size - 1);
- sourceName += "'";
- }
-
- AZ_Printf("OpenXrVK",
- "%s action is bound to %s\n", actionName.data(), ((!sourceName.empty()) ? sourceName.c_str() : "nothing"));
- }
- void Session::LocateControllerSpace(AZ::u32 handIndex)
- {
- Input* xrInput = static_cast<Input*>(GetInput());
- Device* device = static_cast<Device*>(GetDescriptor().m_device.get());
- Space* space = static_cast<Space*>(GetSpace());
- xrInput->LocateControllerSpace(device->GetPredictedDisplayTime(), space->GetXrSpace(OpenXRVk::SpaceType::View), handIndex);
- }
- AZ::RPI::PoseData Session::GetControllerPose(AZ::u32 handIndex) const
- {
- Input* xrInput = static_cast<Input*>(GetInput());
- return xrInput->GetControllerPose(handIndex);
- }
-
- float Session::GetControllerScale(AZ::u32 handIndex) const
- {
- Input* xrInput = static_cast<Input*>(GetInput());
- return xrInput->GetControllerScale(handIndex);
- }
- AZ::RPI::PoseData Session::GetViewFrontPose() const
- {
- Input* xrInput = static_cast<Input*>(GetInput());
- return xrInput->GetVisualizedSpacePose(OpenXRVk::SpaceType::ViewFront);
- }
- XrSession Session::GetXrSession() const
- {
- return m_session;
- }
- XrSpace Session::GetXrSpace(SpaceType spaceType) const
- {
- Space* space = static_cast<Space*>(GetSpace());
- return space->GetXrSpace(spaceType);
- }
- bool Session::IsSessionRunning() const
- {
- return m_sessionRunning;
- }
- bool Session::IsSessionFocused() const
- {
- return m_sessionState == XR_SESSION_STATE_FOCUSED;
- }
- bool Session::IsRestartRequested() const
- {
- return m_requestRestart;
- }
- bool Session::IsExitRenderLoopRequested() const
- {
- return m_exitRenderLoop;
- }
- void Session::ShutdownInternal()
- {
- if (m_session != XR_NULL_HANDLE)
- {
- xrDestroySession(m_session);
- }
- }
- }
|