mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 15:36:42 +00:00
Improved XR event processing logic. Particularly, handling session stop/start in a more predictable, less crashy manner. Added disabling of rendering when XR session is not running.
This commit is contained in:
parent
2a4bdfedc1
commit
5e729a0e82
10 changed files with 189 additions and 60 deletions
|
@ -32,6 +32,13 @@ namespace MWVR
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenXRManager::frameShouldRender()
|
||||||
|
{
|
||||||
|
if (realized())
|
||||||
|
return impl().frameShouldRender();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void OpenXRManager::handleEvents()
|
void OpenXRManager::handleEvents()
|
||||||
{
|
{
|
||||||
if (realized())
|
if (realized())
|
||||||
|
@ -86,6 +93,16 @@ namespace MWVR
|
||||||
return impl().disablePredictions();
|
return impl().disablePredictions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenXRManager::xrResourceAcquired()
|
||||||
|
{
|
||||||
|
return impl().xrResourceAcquired();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenXRManager::xrResourceReleased()
|
||||||
|
{
|
||||||
|
return impl().xrResourceReleased();
|
||||||
|
}
|
||||||
|
|
||||||
std::array<View, 2> OpenXRManager::getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space)
|
std::array<View, 2> OpenXRManager::getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space)
|
||||||
{
|
{
|
||||||
return impl().getPredictedViews(predictedDisplayTime, space);
|
return impl().getPredictedViews(predictedDisplayTime, space);
|
||||||
|
|
|
@ -56,6 +56,9 @@ namespace MWVR
|
||||||
//! Whether the openxr session is currently in a running state
|
//! Whether the openxr session is currently in a running state
|
||||||
bool xrSessionRunning();
|
bool xrSessionRunning();
|
||||||
|
|
||||||
|
//! Whether frames should be rendered in the current state
|
||||||
|
bool frameShouldRender();
|
||||||
|
|
||||||
//! Process all openxr events
|
//! Process all openxr events
|
||||||
void handleEvents();
|
void handleEvents();
|
||||||
|
|
||||||
|
@ -68,6 +71,12 @@ namespace MWVR
|
||||||
//! Disable pose predictions.
|
//! Disable pose predictions.
|
||||||
void disablePredictions();
|
void disablePredictions();
|
||||||
|
|
||||||
|
//! Must be called every time an openxr resource is acquired to keep track
|
||||||
|
void xrResourceAcquired();
|
||||||
|
|
||||||
|
//! Must be called every time an openxr resource is released to keep track
|
||||||
|
void xrResourceReleased();
|
||||||
|
|
||||||
//! Get poses and fov of both eyes at the predicted time, relative to the given reference space. \note Will throw if predictions are disabled.
|
//! Get poses and fov of both eyes at the predicted time, relative to the given reference space. \note Will throw if predictions are disabled.
|
||||||
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space);
|
std::array<View, 2> getPredictedViews(int64_t predictedDisplayTime, ReferenceSpace space);
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ namespace MWVR
|
||||||
inline XrResult CheckXrResult(XrResult res, const char* originator, const char* sourceLocation) {
|
inline XrResult CheckXrResult(XrResult res, const char* originator, const char* sourceLocation) {
|
||||||
if (XR_FAILED(res)) {
|
if (XR_FAILED(res)) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << sourceLocation << ": OpenXR[" << to_string(res) << "]: " << originator;
|
ss << sourceLocation << ": OpenXR[Error: " << to_string(res) << "][Thread: " << std::this_thread::get_id() << "][DC: " << wglGetCurrentDC() << "][GLRC: " << wglGetCurrentContext() << "]: " << originator;
|
||||||
Log(Debug::Error) << ss.str();
|
Log(Debug::Error) << ss.str();
|
||||||
throw std::runtime_error(ss.str().c_str());
|
throw std::runtime_error(ss.str().c_str());
|
||||||
}
|
}
|
||||||
|
@ -471,39 +471,58 @@ namespace MWVR
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mEventMutex);
|
std::unique_lock<std::mutex> lock(mEventMutex);
|
||||||
|
|
||||||
// React to events
|
xrQueueEvents();
|
||||||
|
|
||||||
while (auto* event = nextEvent())
|
while (auto* event = nextEvent())
|
||||||
{
|
{
|
||||||
Log(Debug::Verbose) << "OpenXR: Event received: " << to_string(event->type);
|
if (!processEvent(event))
|
||||||
switch (event->type)
|
|
||||||
{
|
{
|
||||||
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
|
// Do not consider processing an event optional.
|
||||||
{
|
// Retry once per frame until every event has been successfully processed
|
||||||
const auto* stateChangeEvent = reinterpret_cast<const XrEventDataSessionStateChanged*>(event);
|
return;
|
||||||
HandleSessionStateChanged(*stateChangeEvent);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
|
|
||||||
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
|
|
||||||
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
|
|
||||||
default: {
|
|
||||||
Log(Debug::Verbose) << "OpenXR: Event ignored";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
popEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
const XrEventDataBaseHeader* OpenXRManagerImpl::nextEvent()
|
||||||
OpenXRManagerImpl::HandleSessionStateChanged(
|
{
|
||||||
|
if (mEventQueue.size() > 0)
|
||||||
|
return reinterpret_cast<XrEventDataBaseHeader*> (&mEventQueue.front());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenXRManagerImpl::processEvent(const XrEventDataBaseHeader* header)
|
||||||
|
{
|
||||||
|
Log(Debug::Verbose) << "OpenXR: Event received: " << to_string(header->type);
|
||||||
|
switch (header->type)
|
||||||
|
{
|
||||||
|
case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED:
|
||||||
|
{
|
||||||
|
const auto* stateChangeEvent = reinterpret_cast<const XrEventDataSessionStateChanged*>(header);
|
||||||
|
return handleSessionStateChanged(*stateChangeEvent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING:
|
||||||
|
case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
|
||||||
|
case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Log(Debug::Verbose) << "OpenXR: Event ignored";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
OpenXRManagerImpl::handleSessionStateChanged(
|
||||||
const XrEventDataSessionStateChanged& stateChangedEvent)
|
const XrEventDataSessionStateChanged& stateChangedEvent)
|
||||||
{
|
{
|
||||||
auto oldState = mSessionState;
|
auto oldState = mSessionState;
|
||||||
auto newState = stateChangedEvent.state;
|
auto newState = stateChangedEvent.state;
|
||||||
mSessionState = newState;
|
|
||||||
|
|
||||||
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: state " << to_string(oldState) << "->" << to_string(newState);
|
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: state " << to_string(oldState) << "->" << to_string(newState);
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
switch (newState)
|
switch (newState)
|
||||||
{
|
{
|
||||||
|
@ -517,21 +536,45 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
case XR_SESSION_STATE_STOPPING:
|
case XR_SESSION_STATE_STOPPING:
|
||||||
{
|
{
|
||||||
mSessionRunning = false;
|
if (checkStopCondition())
|
||||||
CHECK_XRCMD(xrEndSession(mSession));
|
{
|
||||||
|
CHECK_XRCMD(xrEndSession(mSession));
|
||||||
|
mSessionStopRequested = false;
|
||||||
|
mSessionRunning = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mSessionStopRequested = true;
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: Ignoring new strate " << to_string(newState);
|
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: Ignoring new state " << to_string(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
mSessionState = newState;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log(Debug::Verbose) << "XrEventDataSessionStateChanged: Conditions for state " << to_string(newState) << " not met, retrying next frame";
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
const XrEventDataBaseHeader*
|
bool OpenXRManagerImpl::checkStopCondition()
|
||||||
OpenXRManagerImpl::nextEvent()
|
|
||||||
{
|
{
|
||||||
XrEventDataBaseHeader* baseHeader = reinterpret_cast<XrEventDataBaseHeader*>(&mEventDataBuffer);
|
return mAcquiredResources == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenXRManagerImpl::xrNextEvent(XrEventDataBuffer& eventBuffer)
|
||||||
|
{
|
||||||
|
XrEventDataBaseHeader* baseHeader = reinterpret_cast<XrEventDataBaseHeader*>(&eventBuffer);
|
||||||
*baseHeader = { XR_TYPE_EVENT_DATA_BUFFER };
|
*baseHeader = { XR_TYPE_EVENT_DATA_BUFFER };
|
||||||
const XrResult result = xrPollEvent(mInstance, &mEventDataBuffer);
|
const XrResult result = xrPollEvent(mInstance, &eventBuffer);
|
||||||
if (result == XR_SUCCESS)
|
if (result == XR_SUCCESS)
|
||||||
{
|
{
|
||||||
if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST) {
|
if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST) {
|
||||||
|
@ -547,6 +590,22 @@ namespace MWVR
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenXRManagerImpl::popEvent()
|
||||||
|
{
|
||||||
|
if (mEventQueue.size() > 0)
|
||||||
|
mEventQueue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OpenXRManagerImpl::xrQueueEvents()
|
||||||
|
{
|
||||||
|
XrEventDataBuffer eventBuffer;
|
||||||
|
while (xrNextEvent(eventBuffer))
|
||||||
|
{
|
||||||
|
mEventQueue.push(eventBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MWVR::Pose fromXR(XrPosef pose)
|
MWVR::Pose fromXR(XrPosef pose)
|
||||||
{
|
{
|
||||||
return MWVR::Pose{ fromXR(pose.position), fromXR(pose.orientation) };
|
return MWVR::Pose{ fromXR(pose.position), fromXR(pose.orientation) };
|
||||||
|
@ -582,6 +641,26 @@ namespace MWVR
|
||||||
return mEnabledExtensions.count(extensionName) != 0;
|
return mEnabledExtensions.count(extensionName) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenXRManagerImpl::frameShouldRender()
|
||||||
|
{
|
||||||
|
return xrSessionRunning() && !xrSessionStopRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenXRManagerImpl::xrResourceAcquired()
|
||||||
|
{
|
||||||
|
mAcquiredResources++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenXRManagerImpl::xrResourceReleased()
|
||||||
|
{
|
||||||
|
mAcquiredResources--;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenXRManagerImpl::xrSessionStopRequested()
|
||||||
|
{
|
||||||
|
return mSessionStopRequested;
|
||||||
|
}
|
||||||
|
|
||||||
void OpenXRManagerImpl::enablePredictions()
|
void OpenXRManagerImpl::enablePredictions()
|
||||||
{
|
{
|
||||||
mPredictionsEnabled = true;
|
mPredictionsEnabled = true;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
namespace MWVR
|
namespace MWVR
|
||||||
{
|
{
|
||||||
|
@ -70,13 +71,22 @@ 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 frameShouldRender();
|
||||||
|
void xrResourceAcquired();
|
||||||
|
void xrResourceReleased();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void LogLayersAndExtensions();
|
void LogLayersAndExtensions();
|
||||||
void LogInstanceInfo();
|
void LogInstanceInfo();
|
||||||
void LogReferenceSpaces();
|
void LogReferenceSpaces();
|
||||||
|
bool xrNextEvent(XrEventDataBuffer& eventBuffer);
|
||||||
|
void xrQueueEvents();
|
||||||
const XrEventDataBaseHeader* nextEvent();
|
const XrEventDataBaseHeader* nextEvent();
|
||||||
void HandleSessionStateChanged(const XrEventDataSessionStateChanged& stateChangedEvent);
|
bool processEvent(const XrEventDataBaseHeader* header);
|
||||||
|
void popEvent();
|
||||||
|
bool handleSessionStateChanged(const XrEventDataSessionStateChanged& stateChangedEvent);
|
||||||
|
bool checkStopCondition();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -94,13 +104,15 @@ namespace MWVR
|
||||||
std::array<XrViewConfigurationView, 2> mConfigViews{ { {XR_TYPE_VIEW_CONFIGURATION_VIEW}, {XR_TYPE_VIEW_CONFIGURATION_VIEW} } };
|
std::array<XrViewConfigurationView, 2> mConfigViews{ { {XR_TYPE_VIEW_CONFIGURATION_VIEW}, {XR_TYPE_VIEW_CONFIGURATION_VIEW} } };
|
||||||
XrSpace mReferenceSpaceView = XR_NULL_HANDLE;
|
XrSpace mReferenceSpaceView = XR_NULL_HANDLE;
|
||||||
XrSpace mReferenceSpaceStage = XR_NULL_HANDLE;
|
XrSpace mReferenceSpaceStage = XR_NULL_HANDLE;
|
||||||
XrEventDataBuffer mEventDataBuffer{ XR_TYPE_EVENT_DATA_BUFFER };
|
|
||||||
XrFrameState mFrameState{};
|
XrFrameState mFrameState{};
|
||||||
XrSessionState mSessionState = XR_SESSION_STATE_UNKNOWN;
|
XrSessionState mSessionState = XR_SESSION_STATE_UNKNOWN;
|
||||||
|
bool mSessionStopRequested = false;
|
||||||
bool mSessionRunning = false;
|
bool mSessionRunning = false;
|
||||||
|
uint32_t mAcquiredResources = 0;
|
||||||
std::mutex mFrameStateMutex{};
|
std::mutex mFrameStateMutex{};
|
||||||
std::mutex mEventMutex{};
|
std::mutex mEventMutex{};
|
||||||
std::set<std::string> mEnabledExtensions;
|
std::set<std::string> mEnabledExtensions;
|
||||||
|
std::queue<XrEventDataBuffer> mEventQueue;
|
||||||
|
|
||||||
std::array<XrCompositionLayerDepthInfoKHR, 2> mLayerDepth;
|
std::array<XrCompositionLayerDepthInfoKHR, 2> mLayerDepth;
|
||||||
};
|
};
|
||||||
|
|
|
@ -165,6 +165,7 @@ namespace MWVR {
|
||||||
|
|
||||||
void OpenXRSwapchainImpl::acquire(osg::GraphicsContext*)
|
void OpenXRSwapchainImpl::acquire(osg::GraphicsContext*)
|
||||||
{
|
{
|
||||||
|
auto xr = Environment::get().getManager();
|
||||||
XrSwapchainImageAcquireInfo acquireInfo{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO };
|
XrSwapchainImageAcquireInfo acquireInfo{ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO };
|
||||||
// I am trusting that the openxr runtime won't diverge these indices so long as these are always called together.
|
// I am trusting that the openxr runtime won't diverge these indices so long as these are always called together.
|
||||||
// If some dumb ass implementation decides to violate this we'll just have to work around that if it actually happens.
|
// If some dumb ass implementation decides to violate this we'll just have to work around that if it actually happens.
|
||||||
|
@ -177,18 +178,23 @@ namespace MWVR {
|
||||||
XrSwapchainImageWaitInfo waitInfo{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO };
|
XrSwapchainImageWaitInfo waitInfo{ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO };
|
||||||
waitInfo.timeout = XR_INFINITE_DURATION;
|
waitInfo.timeout = XR_INFINITE_DURATION;
|
||||||
CHECK_XRCMD(xrWaitSwapchainImage(mSwapchain, &waitInfo));
|
CHECK_XRCMD(xrWaitSwapchainImage(mSwapchain, &waitInfo));
|
||||||
|
xr->xrResourceAcquired();
|
||||||
CHECK_XRCMD(xrWaitSwapchainImage(mSwapchainDepth, &waitInfo));
|
CHECK_XRCMD(xrWaitSwapchainImage(mSwapchainDepth, &waitInfo));
|
||||||
|
xr->xrResourceAcquired();
|
||||||
|
|
||||||
mIsAcquired = true;
|
mIsAcquired = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenXRSwapchainImpl::release(osg::GraphicsContext*)
|
void OpenXRSwapchainImpl::release(osg::GraphicsContext*)
|
||||||
{
|
{
|
||||||
|
auto xr = Environment::get().getManager();
|
||||||
mIsAcquired = false;
|
mIsAcquired = false;
|
||||||
|
|
||||||
XrSwapchainImageReleaseInfo releaseInfo{ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO };
|
XrSwapchainImageReleaseInfo releaseInfo{ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO };
|
||||||
CHECK_XRCMD(xrReleaseSwapchainImage(mSwapchain, &releaseInfo));
|
CHECK_XRCMD(xrReleaseSwapchainImage(mSwapchain, &releaseInfo));
|
||||||
|
xr->xrResourceReleased();
|
||||||
CHECK_XRCMD(xrReleaseSwapchainImage(mSwapchainDepth, &releaseInfo));
|
CHECK_XRCMD(xrReleaseSwapchainImage(mSwapchainDepth, &releaseInfo));
|
||||||
|
xr->xrResourceReleased();
|
||||||
}
|
}
|
||||||
void OpenXRSwapchainImpl::checkAcquired() const
|
void OpenXRSwapchainImpl::checkAcquired() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -113,6 +113,7 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VRSession::isRunning() const {
|
bool VRSession::isRunning() const {
|
||||||
|
return true;
|
||||||
auto* xr = Environment::get().getManager();
|
auto* xr = Environment::get().getManager();
|
||||||
return xr->xrSessionRunning();
|
return xr->xrSessionRunning();
|
||||||
}
|
}
|
||||||
|
@ -124,12 +125,11 @@ namespace MWVR
|
||||||
beginPhase(FramePhase::Swap);
|
beginPhase(FramePhase::Swap);
|
||||||
|
|
||||||
auto* frameMeta = getFrame(FramePhase::Swap).get();
|
auto* frameMeta = getFrame(FramePhase::Swap).get();
|
||||||
|
auto leftView = viewer.getView("LeftEye");
|
||||||
|
auto rightView = viewer.getView("RightEye");
|
||||||
|
|
||||||
if (frameMeta->mShouldRender && isRunning())
|
if (frameMeta->mShouldRender)
|
||||||
{
|
{
|
||||||
auto leftView = viewer.getView("LeftEye");
|
|
||||||
auto rightView = viewer.getView("RightEye");
|
|
||||||
|
|
||||||
viewer.blitEyesToMirrorTexture(gc);
|
viewer.blitEyesToMirrorTexture(gc);
|
||||||
gc->swapBuffersImplementation();
|
gc->swapBuffersImplementation();
|
||||||
leftView->swapBuffers(gc);
|
leftView->swapBuffers(gc);
|
||||||
|
@ -145,6 +145,7 @@ namespace MWVR
|
||||||
|
|
||||||
Log(Debug::Debug) << frameMeta->mFrameNo << ": EndFrame " << std::this_thread::get_id();
|
Log(Debug::Debug) << frameMeta->mFrameNo << ": EndFrame " << std::this_thread::get_id();
|
||||||
xr->endFrame(frameMeta->mPredictedDisplayTime, 1, layerStack);
|
xr->endFrame(frameMeta->mPredictedDisplayTime, 1, layerStack);
|
||||||
|
xr->xrResourceReleased();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -167,7 +168,6 @@ namespace MWVR
|
||||||
}
|
}
|
||||||
|
|
||||||
getFrame(FramePhase::Swap) = nullptr;
|
getFrame(FramePhase::Swap) = nullptr;
|
||||||
mFramesInFlight--;
|
|
||||||
}
|
}
|
||||||
mCondition.notify_one();
|
mCondition.notify_one();
|
||||||
}
|
}
|
||||||
|
@ -292,8 +292,9 @@ namespace MWVR
|
||||||
frame->mPredictedDisplayTime = predictedDisplayTime;
|
frame->mPredictedDisplayTime = predictedDisplayTime;
|
||||||
frame->mFrameNo = mFrames;
|
frame->mFrameNo = mFrames;
|
||||||
frame->mPredictedPoses = predictedPoses;
|
frame->mPredictedPoses = predictedPoses;
|
||||||
frame->mShouldRender = isRunning();
|
frame->mShouldRender = xr->frameShouldRender();
|
||||||
mFramesInFlight++;
|
if (frame->mShouldRender)
|
||||||
|
xr->xrResourceAcquired();
|
||||||
}
|
}
|
||||||
|
|
||||||
const PoseSet& VRSession::predictedPoses(FramePhase phase)
|
const PoseSet& VRSession::predictedPoses(FramePhase phase)
|
||||||
|
|
|
@ -77,7 +77,6 @@ namespace MWVR
|
||||||
osg::Matrix viewMatrix(FramePhase phase, Side side);
|
osg::Matrix viewMatrix(FramePhase phase, Side side);
|
||||||
osg::Matrix projectionMatrix(FramePhase phase, Side side);
|
osg::Matrix projectionMatrix(FramePhase phase, Side side);
|
||||||
|
|
||||||
int mFramesInFlight{ 0 };
|
|
||||||
std::array<std::unique_ptr<VRFrameMeta>, (int)FramePhase::NumPhases> mFrame{ nullptr };
|
std::array<std::unique_ptr<VRFrameMeta>, (int)FramePhase::NumPhases> mFrame{ nullptr };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -57,12 +57,8 @@ namespace MWVR {
|
||||||
|
|
||||||
void VRView::prerenderCallback(osg::RenderInfo& renderInfo)
|
void VRView::prerenderCallback(osg::RenderInfo& renderInfo)
|
||||||
{
|
{
|
||||||
|
if(Environment::get().getSession()->getFrame(VRSession::FramePhase::Draw)->mShouldRender)
|
||||||
if (Environment::get().getManager()->xrSessionRunning())
|
|
||||||
{
|
|
||||||
mSwapchain->beginFrame(renderInfo.getState()->getGraphicsContext());
|
mSwapchain->beginFrame(renderInfo.getState()->getGraphicsContext());
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VRView::InitialDrawCallback::operator()(osg::RenderInfo& renderInfo) const
|
void VRView::InitialDrawCallback::operator()(osg::RenderInfo& renderInfo) const
|
||||||
|
@ -86,18 +82,33 @@ namespace MWVR {
|
||||||
auto* camera = slave._camera.get();
|
auto* camera = slave._camera.get();
|
||||||
auto name = camera->getName();
|
auto name = camera->getName();
|
||||||
|
|
||||||
Side side = Side::RIGHT_SIDE;
|
// Update current cached cull mask of camera if it is active
|
||||||
if (name == "LeftEye")
|
auto mask = camera->getCullMask();
|
||||||
side = Side::LEFT_SIDE;
|
if (mask == 0)
|
||||||
|
camera->setCullMask(mCullMask);
|
||||||
|
else
|
||||||
|
mCullMask = mask;
|
||||||
|
|
||||||
auto* session = Environment::get().getSession();
|
if (Environment::get().getSession()->getFrame(VRSession::FramePhase::Update)->mShouldRender)
|
||||||
auto viewMatrix = view.getCamera()->getViewMatrix();
|
{
|
||||||
|
Side side = Side::RIGHT_SIDE;
|
||||||
|
if (name == "LeftEye")
|
||||||
|
side = Side::LEFT_SIDE;
|
||||||
|
|
||||||
auto modifiedViewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Update, side);
|
auto* session = Environment::get().getSession();
|
||||||
auto projectionMatrix = session->projectionMatrix(VRSession::FramePhase::Update, side);
|
auto viewMatrix = view.getCamera()->getViewMatrix();
|
||||||
|
|
||||||
camera->setViewMatrix(modifiedViewMatrix);
|
auto modifiedViewMatrix = viewMatrix * session->viewMatrix(VRSession::FramePhase::Update, side);
|
||||||
camera->setProjectionMatrix(projectionMatrix);
|
auto projectionMatrix = session->projectionMatrix(VRSession::FramePhase::Update, side);
|
||||||
|
|
||||||
|
camera->setViewMatrix(modifiedViewMatrix);
|
||||||
|
camera->setProjectionMatrix(projectionMatrix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If the session is not active, we do not want to waste resources rendering frames.
|
||||||
|
camera->setCullMask(0);
|
||||||
|
}
|
||||||
slave.updateSlaveImplementation(view);
|
slave.updateSlaveImplementation(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,16 +23,11 @@ namespace MWVR
|
||||||
class UpdateSlaveCallback : public osg::View::Slave::UpdateSlaveCallback
|
class UpdateSlaveCallback : public osg::View::Slave::UpdateSlaveCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UpdateSlaveCallback(osg::ref_ptr<VRView> view, osg::GraphicsContext* gc)
|
|
||||||
: mView(view), mGC(gc)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void updateSlave(osg::View& view, osg::View::Slave& slave) override;
|
void updateSlave(osg::View& view, osg::View::Slave& slave) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<OpenXRManager> mXR;
|
|
||||||
osg::ref_ptr<VRView> mView;
|
osg::ref_ptr<VRView> mView;
|
||||||
osg::ref_ptr<osg::GraphicsContext> mGC;
|
osg::Node::NodeMask mCullMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -107,7 +107,7 @@ namespace MWVR
|
||||||
mViewer->addSlave(camera, true);
|
mViewer->addSlave(camera, true);
|
||||||
auto* slave = mViewer->findSlaveForCamera(camera);
|
auto* slave = mViewer->findSlaveForCamera(camera);
|
||||||
assert(slave);
|
assert(slave);
|
||||||
slave->_updateSlaveCallback = new VRView::UpdateSlaveCallback(view, context);
|
slave->_updateSlaveCallback = new VRView::UpdateSlaveCallback();
|
||||||
|
|
||||||
if (mirror)
|
if (mirror)
|
||||||
mMsaaResolveMirrorTexture[i].reset(new VRFramebuffer(context->getState(),
|
mMsaaResolveMirrorTexture[i].reset(new VRFramebuffer(context->getState(),
|
||||||
|
|
Loading…
Reference in a new issue