mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 00:23:51 +00:00
More accurate interpretation of openxr session states
This commit is contained in:
parent
cf20faff21
commit
6425749b7e
8 changed files with 187 additions and 151 deletions
|
@ -179,7 +179,7 @@ namespace MWVR
|
||||||
OpenXRActionSet::updateControls()
|
OpenXRActionSet::updateControls()
|
||||||
{
|
{
|
||||||
auto* xr = Environment::get().getManager();
|
auto* xr = Environment::get().getManager();
|
||||||
if (!xr->impl().xrSessionRunning())
|
if (!xr->impl().appShouldReadInput())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const XrActiveActionSet activeActionSet{ mActionSet, XR_NULL_PATH };
|
const XrActiveActionSet activeActionSet{ mActionSet, XR_NULL_PATH };
|
||||||
|
|
|
@ -21,25 +21,11 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
OpenXRManager::realized()
|
OpenXRManager::realized() const
|
||||||
{
|
{
|
||||||
return !!mPrivate;
|
return !!mPrivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRManager::xrSessionRunning()
|
|
||||||
{
|
|
||||||
if (realized())
|
|
||||||
return impl().xrSessionRunning();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OpenXRManager::xrSessionCanRender()
|
|
||||||
{
|
|
||||||
if (realized())
|
|
||||||
return impl().xrSessionCanRender();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenXRManager::handleEvents()
|
void OpenXRManager::handleEvents()
|
||||||
{
|
{
|
||||||
if (realized())
|
if (realized())
|
||||||
|
@ -56,9 +42,30 @@ namespace MWVR
|
||||||
return impl().beginFrame();
|
return impl().beginFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXRManager::endFrame(FrameInfo frameInfo, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack)
|
void OpenXRManager::endFrame(FrameInfo frameInfo, const std::array<CompositionLayerProjectionView, 2>* layerStack)
|
||||||
{
|
{
|
||||||
return impl().endFrame(frameInfo, layerCount, layerStack);
|
return impl().endFrame(frameInfo, layerStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenXRManager::appShouldSyncFrameLoop() const
|
||||||
|
{
|
||||||
|
if (realized())
|
||||||
|
return impl().appShouldSyncFrameLoop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenXRManager::appShouldRender() const
|
||||||
|
{
|
||||||
|
if (realized())
|
||||||
|
return impl().appShouldRender();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenXRManager::appShouldReadInput() const
|
||||||
|
{
|
||||||
|
if (realized())
|
||||||
|
return impl().appShouldReadInput();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace MWVR
|
||||||
~OpenXRManager();
|
~OpenXRManager();
|
||||||
|
|
||||||
/// Manager has been initialized.
|
/// Manager has been initialized.
|
||||||
bool realized();
|
bool realized() const;
|
||||||
|
|
||||||
//! Forward call to xrWaitFrame()
|
//! Forward call to xrWaitFrame()
|
||||||
FrameInfo waitFrame();
|
FrameInfo waitFrame();
|
||||||
|
@ -51,13 +51,16 @@ namespace MWVR
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
|
|
||||||
//! Forward call to xrEndFrame()
|
//! Forward call to xrEndFrame()
|
||||||
void endFrame(FrameInfo frameInfo, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack);
|
void endFrame(FrameInfo frameInfo, const std::array<CompositionLayerProjectionView, 2>* layerStack);
|
||||||
|
|
||||||
//! Whether the openxr session is currently in a running state
|
//! Whether the app should call the openxr frame sync functions ( xr*Frame() )
|
||||||
bool xrSessionRunning();
|
bool appShouldSyncFrameLoop() const;
|
||||||
|
|
||||||
//! Whether frames can be rendered in the current state
|
//! Whether the app should render anything.
|
||||||
bool xrSessionCanRender();
|
bool appShouldRender() const;
|
||||||
|
|
||||||
|
//! Whether the session is focused and can read input
|
||||||
|
bool appShouldReadInput() const;
|
||||||
|
|
||||||
//! Process all openxr events
|
//! Process all openxr events
|
||||||
void handleEvents();
|
void handleEvents();
|
||||||
|
|
|
@ -474,41 +474,41 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OpenXRManagerImpl::endFrame(FrameInfo frameInfo, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack)
|
OpenXRManagerImpl::endFrame(FrameInfo frameInfo, const std::array<CompositionLayerProjectionView, 2>* layerStack)
|
||||||
{
|
{
|
||||||
std::array<XrCompositionLayerProjectionView, 2> compositionLayerProjectionViews{};
|
|
||||||
compositionLayerProjectionViews[(int)Side::LEFT_SIDE] = toXR(layerStack[(int)Side::LEFT_SIDE]);
|
|
||||||
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE] = toXR(layerStack[(int)Side::RIGHT_SIDE]);
|
|
||||||
XrCompositionLayerProjection layer{};
|
|
||||||
layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
|
||||||
layer.space = getReferenceSpace(ReferenceSpace::STAGE);
|
|
||||||
layer.viewCount = 2;
|
|
||||||
layer.views = compositionLayerProjectionViews.data();
|
|
||||||
auto* xrLayerStack = reinterpret_cast<XrCompositionLayerBaseHeader*>(&layer);
|
|
||||||
|
|
||||||
std::array<XrCompositionLayerDepthInfoKHR, 2> compositionLayerDepth = mLayerDepth;
|
|
||||||
if (xrExtensionIsEnabled(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME))
|
|
||||||
{
|
|
||||||
auto farClip = Settings::Manager::getFloat("viewing distance", "Camera");
|
|
||||||
// All values not set here are set previously as they are constant
|
|
||||||
compositionLayerDepth[(int)Side::LEFT_SIDE].farZ = farClip;
|
|
||||||
compositionLayerDepth[(int)Side::RIGHT_SIDE].farZ = farClip;
|
|
||||||
compositionLayerDepth[(int)Side::LEFT_SIDE].subImage = layerStack[(int)Side::LEFT_SIDE].swapchain->impl().xrSubImageDepth();
|
|
||||||
compositionLayerDepth[(int)Side::RIGHT_SIDE].subImage = layerStack[(int)Side::RIGHT_SIDE].swapchain->impl().xrSubImageDepth();
|
|
||||||
if (compositionLayerDepth[(int)Side::LEFT_SIDE].subImage.swapchain != XR_NULL_HANDLE
|
|
||||||
&& compositionLayerDepth[(int)Side::RIGHT_SIDE].subImage.swapchain != XR_NULL_HANDLE)
|
|
||||||
{
|
|
||||||
compositionLayerProjectionViews[(int)Side::LEFT_SIDE].next = &compositionLayerDepth[(int)Side::LEFT_SIDE];
|
|
||||||
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE].next = &compositionLayerDepth[(int)Side::RIGHT_SIDE];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XrFrameEndInfo frameEndInfo{ XR_TYPE_FRAME_END_INFO };
|
XrFrameEndInfo frameEndInfo{ XR_TYPE_FRAME_END_INFO };
|
||||||
frameEndInfo.displayTime = frameInfo.runtimePredictedDisplayTime;
|
frameEndInfo.displayTime = frameInfo.runtimePredictedDisplayTime;
|
||||||
frameEndInfo.environmentBlendMode = mEnvironmentBlendMode;
|
frameEndInfo.environmentBlendMode = mEnvironmentBlendMode;
|
||||||
//if (frameInfo.runtimeRequestsRender)
|
if (layerStack)
|
||||||
{
|
{
|
||||||
frameEndInfo.layerCount = layerCount;
|
std::array<XrCompositionLayerProjectionView, 2> compositionLayerProjectionViews{};
|
||||||
|
compositionLayerProjectionViews[(int)Side::LEFT_SIDE] = toXR((*layerStack)[(int)Side::LEFT_SIDE]);
|
||||||
|
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE] = toXR((*layerStack)[(int)Side::RIGHT_SIDE]);
|
||||||
|
XrCompositionLayerProjection layer{};
|
||||||
|
layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
|
||||||
|
layer.space = getReferenceSpace(ReferenceSpace::STAGE);
|
||||||
|
layer.viewCount = 2;
|
||||||
|
layer.views = compositionLayerProjectionViews.data();
|
||||||
|
auto* xrLayerStack = reinterpret_cast<XrCompositionLayerBaseHeader*>(&layer);
|
||||||
|
|
||||||
|
std::array<XrCompositionLayerDepthInfoKHR, 2> compositionLayerDepth = mLayerDepth;
|
||||||
|
if (xrExtensionIsEnabled(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME))
|
||||||
|
{
|
||||||
|
auto farClip = Settings::Manager::getFloat("viewing distance", "Camera");
|
||||||
|
// All values not set here are set previously as they are constant
|
||||||
|
compositionLayerDepth[(int)Side::LEFT_SIDE].farZ = farClip;
|
||||||
|
compositionLayerDepth[(int)Side::RIGHT_SIDE].farZ = farClip;
|
||||||
|
compositionLayerDepth[(int)Side::LEFT_SIDE].subImage = (*layerStack)[(int)Side::LEFT_SIDE].swapchain->impl().xrSubImageDepth();
|
||||||
|
compositionLayerDepth[(int)Side::RIGHT_SIDE].subImage = (*layerStack)[(int)Side::RIGHT_SIDE].swapchain->impl().xrSubImageDepth();
|
||||||
|
if (compositionLayerDepth[(int)Side::LEFT_SIDE].subImage.swapchain != XR_NULL_HANDLE
|
||||||
|
&& compositionLayerDepth[(int)Side::RIGHT_SIDE].subImage.swapchain != XR_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
compositionLayerProjectionViews[(int)Side::LEFT_SIDE].next = &compositionLayerDepth[(int)Side::LEFT_SIDE];
|
||||||
|
compositionLayerProjectionViews[(int)Side::RIGHT_SIDE].next = &compositionLayerDepth[(int)Side::RIGHT_SIDE];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frameEndInfo.layerCount = 1;
|
||||||
frameEndInfo.layers = &xrLayerStack;
|
frameEndInfo.layers = &xrLayerStack;
|
||||||
}
|
}
|
||||||
CHECK_XRCMD(xrEndFrame(mSession, &frameEndInfo));
|
CHECK_XRCMD(xrEndFrame(mSession, &frameEndInfo));
|
||||||
|
@ -602,6 +602,15 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
popEvent();
|
popEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mXrSessionShouldStop)
|
||||||
|
{
|
||||||
|
if (checkStopCondition())
|
||||||
|
{
|
||||||
|
CHECK_XRCMD(xrEndSession(mSession));
|
||||||
|
mXrSessionShouldStop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const XrEventDataBaseHeader* OpenXRManagerImpl::nextEvent()
|
const XrEventDataBaseHeader* OpenXRManagerImpl::nextEvent()
|
||||||
|
@ -638,50 +647,70 @@ namespace MWVR
|
||||||
OpenXRManagerImpl::handleSessionStateChanged(
|
OpenXRManagerImpl::handleSessionStateChanged(
|
||||||
const XrEventDataSessionStateChanged& stateChangedEvent)
|
const XrEventDataSessionStateChanged& stateChangedEvent)
|
||||||
{
|
{
|
||||||
auto oldState = mSessionState;
|
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: state " << to_string(mSessionState) << "->" << to_string(stateChangedEvent.state);
|
||||||
auto newState = stateChangedEvent.state;
|
mSessionState = stateChangedEvent.state;
|
||||||
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: state " << to_string(oldState) << "->" << to_string(newState);
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
switch (newState)
|
// Ref: https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#session-states
|
||||||
|
switch (mSessionState)
|
||||||
{
|
{
|
||||||
|
case XR_SESSION_STATE_IDLE:
|
||||||
|
{
|
||||||
|
mAppShouldSyncFrameLoop = false;
|
||||||
|
mAppShouldRender = false;
|
||||||
|
mAppShouldReadInput = false;
|
||||||
|
mXrSessionShouldStop = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case XR_SESSION_STATE_READY:
|
case XR_SESSION_STATE_READY:
|
||||||
{
|
{
|
||||||
|
mAppShouldSyncFrameLoop = true;
|
||||||
|
mAppShouldRender = false;
|
||||||
|
mAppShouldReadInput = false;
|
||||||
|
mXrSessionShouldStop = false;
|
||||||
|
|
||||||
XrSessionBeginInfo beginInfo{ XR_TYPE_SESSION_BEGIN_INFO };
|
XrSessionBeginInfo beginInfo{ XR_TYPE_SESSION_BEGIN_INFO };
|
||||||
beginInfo.primaryViewConfigurationType = mViewConfigType;
|
beginInfo.primaryViewConfigurationType = mViewConfigType;
|
||||||
CHECK_XRCMD(xrBeginSession(mSession, &beginInfo));
|
CHECK_XRCMD(xrBeginSession(mSession, &beginInfo));
|
||||||
mSessionRunning = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case XR_SESSION_STATE_STOPPING:
|
case XR_SESSION_STATE_STOPPING:
|
||||||
{
|
{
|
||||||
if (checkStopCondition())
|
mAppShouldSyncFrameLoop = false;
|
||||||
{
|
mAppShouldRender = false;
|
||||||
CHECK_XRCMD(xrEndSession(mSession));
|
mAppShouldReadInput = false;
|
||||||
mSessionStopRequested = false;
|
mXrSessionShouldStop = true;
|
||||||
mSessionRunning = false;
|
break;
|
||||||
}
|
}
|
||||||
else
|
case XR_SESSION_STATE_SYNCHRONIZED:
|
||||||
{
|
{
|
||||||
mSessionStopRequested = true;
|
mAppShouldSyncFrameLoop = true;
|
||||||
success = false;
|
mAppShouldRender = false;
|
||||||
}
|
mAppShouldReadInput = false;
|
||||||
|
mXrSessionShouldStop = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XR_SESSION_STATE_VISIBLE:
|
||||||
|
{
|
||||||
|
mAppShouldSyncFrameLoop = true;
|
||||||
|
mAppShouldRender = true;
|
||||||
|
mAppShouldReadInput = false;
|
||||||
|
mXrSessionShouldStop = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XR_SESSION_STATE_FOCUSED:
|
||||||
|
{
|
||||||
|
mAppShouldSyncFrameLoop = true;
|
||||||
|
mAppShouldRender = true;
|
||||||
|
mAppShouldReadInput = true;
|
||||||
|
mXrSessionShouldStop = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: Ignoring new state " << to_string(newState);
|
Log(Debug::Warning) << "XrEventDataSessionStateChanged: Ignoring new state " << to_string(mSessionState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
return true;
|
||||||
{
|
|
||||||
mSessionState = newState;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: Conditions for state " << to_string(newState) << " not met, retrying next frame";
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRManagerImpl::checkStopCondition()
|
bool OpenXRManagerImpl::checkStopCondition()
|
||||||
|
@ -760,11 +789,6 @@ namespace MWVR
|
||||||
return mEnabledExtensions.count(extensionName) != 0;
|
return mEnabledExtensions.count(extensionName) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRManagerImpl::xrSessionCanRender()
|
|
||||||
{
|
|
||||||
return xrSessionRunning() && !xrSessionStopRequested();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenXRManagerImpl::xrResourceAcquired()
|
void OpenXRManagerImpl::xrResourceAcquired()
|
||||||
{
|
{
|
||||||
mAcquiredResources++;
|
mAcquiredResources++;
|
||||||
|
@ -792,11 +816,6 @@ namespace MWVR
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenXRManagerImpl::xrSessionStopRequested()
|
|
||||||
{
|
|
||||||
return mSessionStopRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenXRManagerImpl::enablePredictions()
|
void OpenXRManagerImpl::enablePredictions()
|
||||||
{
|
{
|
||||||
mPredictionsEnabled = true;
|
mPredictionsEnabled = true;
|
||||||
|
|
|
@ -51,8 +51,10 @@ namespace MWVR
|
||||||
|
|
||||||
FrameInfo waitFrame();
|
FrameInfo waitFrame();
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
void endFrame(FrameInfo frameInfo, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack);
|
void endFrame(FrameInfo frameInfo, const std::array<CompositionLayerProjectionView, 2>* layerStack);
|
||||||
bool xrSessionRunning() const { return mSessionRunning; }
|
bool appShouldSyncFrameLoop() const { return mAppShouldSyncFrameLoop; }
|
||||||
|
bool appShouldRender() const { return mAppShouldRender; }
|
||||||
|
bool appShouldReadInput() const { return mAppShouldReadInput; }
|
||||||
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space);
|
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space);
|
||||||
MWVR::Pose getPredictedHeadPose(int64_t predictedDisplayTime, ReferenceSpace space);
|
MWVR::Pose getPredictedHeadPose(int64_t predictedDisplayTime, ReferenceSpace space);
|
||||||
void handleEvents();
|
void handleEvents();
|
||||||
|
@ -65,8 +67,6 @@ namespace MWVR
|
||||||
XrSession xrSession() const { return mSession; };
|
XrSession xrSession() const { return mSession; };
|
||||||
XrInstance xrInstance() const { return mInstance; };
|
XrInstance xrInstance() const { return mInstance; };
|
||||||
bool xrExtensionIsEnabled(const char* extensionName) const;
|
bool xrExtensionIsEnabled(const char* extensionName) const;
|
||||||
bool xrSessionStopRequested();
|
|
||||||
bool xrSessionCanRender();
|
|
||||||
void xrResourceAcquired();
|
void xrResourceAcquired();
|
||||||
void xrResourceReleased();
|
void xrResourceReleased();
|
||||||
void xrUpdateNames();
|
void xrUpdateNames();
|
||||||
|
@ -106,8 +106,12 @@ namespace MWVR
|
||||||
XrFrameState mFrameState{};
|
XrFrameState mFrameState{};
|
||||||
XrSessionState mSessionState = XR_SESSION_STATE_UNKNOWN;
|
XrSessionState mSessionState = XR_SESSION_STATE_UNKNOWN;
|
||||||
XrDebugUtilsMessengerEXT mDebugMessenger{ nullptr };
|
XrDebugUtilsMessengerEXT mDebugMessenger{ nullptr };
|
||||||
bool mSessionStopRequested = false;
|
|
||||||
bool mSessionRunning = false;
|
bool mXrSessionShouldStop = false;
|
||||||
|
bool mAppShouldSyncFrameLoop = false;
|
||||||
|
bool mAppShouldRender = false;
|
||||||
|
bool mAppShouldReadInput = false;
|
||||||
|
|
||||||
uint32_t mAcquiredResources = 0;
|
uint32_t mAcquiredResources = 0;
|
||||||
std::mutex mFrameStateMutex{};
|
std::mutex mFrameStateMutex{};
|
||||||
std::mutex mEventMutex{};
|
std::mutex mEventMutex{};
|
||||||
|
|
|
@ -111,12 +111,6 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VRSession::isRunning() const {
|
|
||||||
return true;
|
|
||||||
auto* xr = Environment::get().getManager();
|
|
||||||
return xr->xrSessionRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VRSession::swapBuffers(osg::GraphicsContext* gc, VRViewer& viewer)
|
void VRSession::swapBuffers(osg::GraphicsContext* gc, VRViewer& viewer)
|
||||||
{
|
{
|
||||||
auto* xr = Environment::get().getManager();
|
auto* xr = Environment::get().getManager();
|
||||||
|
@ -127,22 +121,29 @@ namespace MWVR
|
||||||
auto leftView = viewer.getView("LeftEye");
|
auto leftView = viewer.getView("LeftEye");
|
||||||
auto rightView = viewer.getView("RightEye");
|
auto rightView = viewer.getView("RightEye");
|
||||||
|
|
||||||
if (frameMeta->mShouldRender)
|
if (frameMeta->mShouldSyncFrameLoop)
|
||||||
{
|
{
|
||||||
viewer.blitEyesToMirrorTexture(gc);
|
if (frameMeta->mShouldRender)
|
||||||
gc->swapBuffersImplementation();
|
{
|
||||||
leftView->swapBuffers(gc);
|
viewer.blitEyesToMirrorTexture(gc);
|
||||||
rightView->swapBuffers(gc);
|
gc->swapBuffersImplementation();
|
||||||
|
leftView->swapBuffers(gc);
|
||||||
|
rightView->swapBuffers(gc);
|
||||||
|
std::array<CompositionLayerProjectionView, 2> layerStack{};
|
||||||
|
layerStack[(int)Side::LEFT_SIDE].swapchain = &leftView->swapchain();
|
||||||
|
layerStack[(int)Side::RIGHT_SIDE].swapchain = &rightView->swapchain();
|
||||||
|
layerStack[(int)Side::LEFT_SIDE].pose = frameMeta->mPredictedPoses.eye[(int)Side::LEFT_SIDE] / mPlayerScale;
|
||||||
|
layerStack[(int)Side::RIGHT_SIDE].pose = frameMeta->mPredictedPoses.eye[(int)Side::RIGHT_SIDE] / mPlayerScale;
|
||||||
|
layerStack[(int)Side::LEFT_SIDE].fov = frameMeta->mPredictedPoses.view[(int)Side::LEFT_SIDE].fov;
|
||||||
|
layerStack[(int)Side::RIGHT_SIDE].fov = frameMeta->mPredictedPoses.view[(int)Side::RIGHT_SIDE].fov;
|
||||||
|
xr->endFrame(frameMeta->mFrameInfo, &layerStack);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gc->swapBuffersImplementation();
|
||||||
|
xr->endFrame(frameMeta->mFrameInfo, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
std::array<CompositionLayerProjectionView, 2> layerStack{};
|
|
||||||
layerStack[(int)Side::LEFT_SIDE].swapchain = &leftView->swapchain();
|
|
||||||
layerStack[(int)Side::RIGHT_SIDE].swapchain = &rightView->swapchain();
|
|
||||||
layerStack[(int)Side::LEFT_SIDE].pose = frameMeta->mPredictedPoses.eye[(int)Side::LEFT_SIDE] / mPlayerScale;
|
|
||||||
layerStack[(int)Side::RIGHT_SIDE].pose = frameMeta->mPredictedPoses.eye[(int)Side::RIGHT_SIDE] / mPlayerScale;
|
|
||||||
layerStack[(int)Side::LEFT_SIDE].fov = frameMeta->mPredictedPoses.view[(int)Side::LEFT_SIDE].fov;
|
|
||||||
layerStack[(int)Side::RIGHT_SIDE].fov = frameMeta->mPredictedPoses.view[(int)Side::RIGHT_SIDE].fov;
|
|
||||||
|
|
||||||
xr->endFrame(frameMeta->mFrameInfo, 1, layerStack);
|
|
||||||
xr->xrResourceReleased();
|
xr->xrResourceReleased();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +182,7 @@ namespace MWVR
|
||||||
frame = std::move(getFrame(previousPhase));
|
frame = std::move(getFrame(previousPhase));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phase == mXrSyncPhase && frame->mShouldRender)
|
if (phase == mXrSyncPhase && frame->mShouldSyncFrameLoop)
|
||||||
{
|
{
|
||||||
// We may reach this point before xrEndFrame of the previous frame
|
// We may reach this point before xrEndFrame of the previous frame
|
||||||
// Must wait or openxr will interpret another call to xrBeginFrame() as skipping a frame
|
// Must wait or openxr will interpret another call to xrBeginFrame() as skipping a frame
|
||||||
|
@ -191,10 +192,7 @@ namespace MWVR
|
||||||
mCondition.wait(lock);
|
mCondition.wait(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame->mShouldRender)
|
Environment::get().getManager()->beginFrame();
|
||||||
{
|
|
||||||
Environment::get().getManager()->beginFrame();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,42 +213,48 @@ namespace MWVR
|
||||||
frame.reset(new VRFrameMeta);
|
frame.reset(new VRFrameMeta);
|
||||||
|
|
||||||
frame->mFrameNo = mFrames;
|
frame->mFrameNo = mFrames;
|
||||||
frame->mShouldRender = xr->xrSessionCanRender();
|
frame->mShouldSyncFrameLoop = xr->appShouldSyncFrameLoop();
|
||||||
if (frame->mShouldRender)
|
frame->mShouldRender = xr->appShouldRender();
|
||||||
|
if (frame->mShouldSyncFrameLoop)
|
||||||
{
|
{
|
||||||
frame->mFrameInfo = xr->waitFrame();
|
frame->mFrameInfo = xr->waitFrame();
|
||||||
xr->xrResourceAcquired();
|
xr->xrResourceAcquired();
|
||||||
|
|
||||||
|
if (frame->mShouldRender)
|
||||||
|
{
|
||||||
|
frame->mPredictedDisplayTime = frame->mFrameInfo.runtimePredictedDisplayTime;
|
||||||
|
|
||||||
|
PoseSet predictedPoses{};
|
||||||
|
|
||||||
|
xr->enablePredictions();
|
||||||
|
predictedPoses.head = xr->getPredictedHeadPose(frame->mPredictedDisplayTime, ReferenceSpace::STAGE) * mPlayerScale;
|
||||||
|
auto hmdViews = xr->getPredictedViews(frame->mPredictedDisplayTime, ReferenceSpace::VIEW);
|
||||||
|
predictedPoses.view[(int)Side::LEFT_SIDE].pose = hmdViews[(int)Side::LEFT_SIDE].pose * mPlayerScale;
|
||||||
|
predictedPoses.view[(int)Side::RIGHT_SIDE].pose = hmdViews[(int)Side::RIGHT_SIDE].pose * mPlayerScale;
|
||||||
|
predictedPoses.view[(int)Side::LEFT_SIDE].fov = hmdViews[(int)Side::LEFT_SIDE].fov;
|
||||||
|
predictedPoses.view[(int)Side::RIGHT_SIDE].fov = hmdViews[(int)Side::RIGHT_SIDE].fov;
|
||||||
|
auto stageViews = xr->getPredictedViews(frame->mPredictedDisplayTime, ReferenceSpace::STAGE);
|
||||||
|
predictedPoses.eye[(int)Side::LEFT_SIDE] = stageViews[(int)Side::LEFT_SIDE].pose * mPlayerScale;
|
||||||
|
predictedPoses.eye[(int)Side::RIGHT_SIDE] = stageViews[(int)Side::RIGHT_SIDE].pose * mPlayerScale;
|
||||||
|
|
||||||
|
auto* input = Environment::get().getInputManager();
|
||||||
|
if (input)
|
||||||
|
{
|
||||||
|
predictedPoses.hands[(int)Side::LEFT_SIDE] = input->getLimbPose(frame->mPredictedDisplayTime, TrackedLimb::LEFT_HAND) * mPlayerScale;
|
||||||
|
predictedPoses.hands[(int)Side::RIGHT_SIDE] = input->getLimbPose(frame->mPredictedDisplayTime, TrackedLimb::RIGHT_HAND) * mPlayerScale;
|
||||||
|
}
|
||||||
|
xr->disablePredictions();
|
||||||
|
|
||||||
|
frame->mPredictedPoses = predictedPoses;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
frame->mPredictedDisplayTime = frame->mFrameInfo.runtimePredictedDisplayTime;
|
|
||||||
|
|
||||||
PoseSet predictedPoses{};
|
|
||||||
|
|
||||||
xr->enablePredictions();
|
|
||||||
predictedPoses.head = xr->getPredictedHeadPose(frame->mPredictedDisplayTime, ReferenceSpace::STAGE) * mPlayerScale;
|
|
||||||
auto hmdViews = xr->getPredictedViews(frame->mPredictedDisplayTime, ReferenceSpace::VIEW);
|
|
||||||
predictedPoses.view[(int)Side::LEFT_SIDE].pose = hmdViews[(int)Side::LEFT_SIDE].pose * mPlayerScale;
|
|
||||||
predictedPoses.view[(int)Side::RIGHT_SIDE].pose = hmdViews[(int)Side::RIGHT_SIDE].pose * mPlayerScale;
|
|
||||||
predictedPoses.view[(int)Side::LEFT_SIDE].fov = hmdViews[(int)Side::LEFT_SIDE].fov;
|
|
||||||
predictedPoses.view[(int)Side::RIGHT_SIDE].fov = hmdViews[(int)Side::RIGHT_SIDE].fov;
|
|
||||||
auto stageViews = xr->getPredictedViews(frame->mPredictedDisplayTime, ReferenceSpace::STAGE);
|
|
||||||
predictedPoses.eye[(int)Side::LEFT_SIDE] = stageViews[(int)Side::LEFT_SIDE].pose * mPlayerScale;
|
|
||||||
predictedPoses.eye[(int)Side::RIGHT_SIDE] = stageViews[(int)Side::RIGHT_SIDE].pose * mPlayerScale;
|
|
||||||
|
|
||||||
auto* input = Environment::get().getInputManager();
|
|
||||||
if (input)
|
|
||||||
{
|
|
||||||
predictedPoses.hands[(int)Side::LEFT_SIDE] = input->getLimbPose(frame->mPredictedDisplayTime, TrackedLimb::LEFT_HAND) * mPlayerScale;
|
|
||||||
predictedPoses.hands[(int)Side::RIGHT_SIDE] = input->getLimbPose(frame->mPredictedDisplayTime, TrackedLimb::RIGHT_HAND) * mPlayerScale;
|
|
||||||
}
|
|
||||||
xr->disablePredictions();
|
|
||||||
|
|
||||||
frame->mPredictedPoses = predictedPoses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const PoseSet& VRSession::predictedPoses(FramePhase phase)
|
const PoseSet& VRSession::predictedPoses(FramePhase phase)
|
||||||
{
|
{
|
||||||
auto& frame = getFrame(phase);
|
auto& frame = getFrame(phase);
|
||||||
|
|
||||||
|
// TODO: Manage execution order properly instead of this hack
|
||||||
if (phase == FramePhase::Update && !frame)
|
if (phase == FramePhase::Update && !frame)
|
||||||
beginPhase(FramePhase::Update);
|
beginPhase(FramePhase::Update);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ namespace MWVR
|
||||||
long long mPredictedDisplayTime{ 0 };
|
long long mPredictedDisplayTime{ 0 };
|
||||||
PoseSet mPredictedPoses{};
|
PoseSet mPredictedPoses{};
|
||||||
bool mShouldRender{ false };
|
bool mShouldRender{ false };
|
||||||
|
bool mShouldSyncFrameLoop{ false };
|
||||||
FrameInfo mFrameInfo{};
|
FrameInfo mFrameInfo{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,8 +68,6 @@ namespace MWVR
|
||||||
void beginPhase(FramePhase phase);
|
void beginPhase(FramePhase phase);
|
||||||
std::unique_ptr<VRFrameMeta>& getFrame(FramePhase phase);
|
std::unique_ptr<VRFrameMeta>& getFrame(FramePhase phase);
|
||||||
|
|
||||||
bool isRunning() const;
|
|
||||||
|
|
||||||
float playerScale() const { return mPlayerScale; }
|
float playerScale() const { return mPlayerScale; }
|
||||||
float setPlayerScale(float scale) { return mPlayerScale = scale; }
|
float setPlayerScale(float scale) { return mPlayerScale = scale; }
|
||||||
|
|
||||||
|
|
|
@ -955,7 +955,7 @@ XR_EXT_debug_utils message level info = true
|
||||||
XR_EXT_debug_utils message level warning = true
|
XR_EXT_debug_utils message level warning = true
|
||||||
XR_EXT_debug_utils message level error = true
|
XR_EXT_debug_utils message level error = true
|
||||||
# Enable/disable openxr debug message types
|
# Enable/disable openxr debug message types
|
||||||
XR_EXT_debug_utils message type general = false
|
XR_EXT_debug_utils message type general = true
|
||||||
XR_EXT_debug_utils message type validation = true
|
XR_EXT_debug_utils message type validation = true
|
||||||
XR_EXT_debug_utils message type performance = true
|
XR_EXT_debug_utils message type performance = true
|
||||||
XR_EXT_debug_utils message type conformance = true
|
XR_EXT_debug_utils message type conformance = true
|
||||||
|
|
Loading…
Reference in a new issue