From b5675b7525bc5bb3f76cdefd491fce3b39bf91d7 Mon Sep 17 00:00:00 2001 From: Mads Buvik Sandvei Date: Tue, 21 Jul 2020 14:36:11 +0200 Subject: [PATCH] Configuration option for oculus prediction time workaround --- apps/openmw/mwvr/vrsession.cpp | 33 ++++++++++++++------------------- apps/openmw/mwvr/vrsession.hpp | 1 + files/settings-default.cfg | 6 +++++- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwvr/vrsession.cpp b/apps/openmw/mwvr/vrsession.cpp index 83f0fa66e..8aac92bbe 100644 --- a/apps/openmw/mwvr/vrsession.cpp +++ b/apps/openmw/mwvr/vrsession.cpp @@ -19,6 +19,7 @@ #include +#include #include #include #include @@ -56,6 +57,10 @@ namespace MWVR return; } Log(Debug::Verbose) << "Using openxr sync phase " << syncPhase; + + mUseSteadyClock = Settings::Manager::getBool("use steady clock", "VR"); + if (mUseSteadyClock) + Log(Debug::Verbose) << "Using chrono::steady_clock instead of openxr predicted display times."; } VRSession::~VRSession() @@ -236,32 +241,22 @@ namespace MWVR auto* xr = Environment::get().getManager(); xr->handleEvents(); - //auto frameState = xr->impl().frameState(); - // auto predictedDisplayTime = frameState.predictedDisplayTime; - // if (predictedDisplayTime == 0) - // { - // // First time, need to invent a frame time since openxr won't help us without a call to waitframe. - // predictedDisplayTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - // } - // else - // { - // // Predict display time based on real framerate - // float intervalsf = static_cast(mLastFrameInterval.count()) / static_cast(mLastPredictedDisplayPeriod); - // int intervals = std::max((int)std::roundf(intervalsf), 1); - // predictedDisplayTime = mLastPredictedDisplayTime + intervals * (mFrames - mLastRenderedFrame) * mLastPredictedDisplayPeriod; - // } + auto epochTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + auto predictedDisplayTime = std::max(xr->getLastPredictedDisplayTime(), epochTime); + auto predictedDisplayPeriod = std::max(xr->getLastPredictedDisplayPeriod(), (long long)1000000); + float intervalsf = static_cast(mLastFrameInterval.count()) / static_cast(predictedDisplayPeriod); //////////////////////// OCULUS BUG - //////////////////// Oculus will suddenly start monotonically increasing their predicted display time by precisely 1 second + //////////////////// Oculus will suddenly start increasing their predicted display time by precisely 1 second per frame //////////////////// regardless of real time passed, causing predictions to go crazy due to the time difference. //////////////////// Therefore, for the time being, i ignore oculus' predicted display time altogether. - long long predictedDisplayTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + if(mUseSteadyClock) + predictedDisplayTime = epochTime; + if (mFrames > 1) { - auto framePeriod = xr->getLastPredictedDisplayPeriod(); - float intervalsf = static_cast(mLastFrameInterval.count()) / static_cast(framePeriod); int intervals = std::max((int)std::roundf(intervalsf), 1); - predictedDisplayTime = predictedDisplayTime + intervals * (mFrames - mLastRenderedFrame) * framePeriod; + predictedDisplayTime = predictedDisplayTime + intervals * (mFrames - mLastRenderedFrame) * predictedDisplayPeriod; } diff --git a/apps/openmw/mwvr/vrsession.hpp b/apps/openmw/mwvr/vrsession.hpp index 80e53ef0d..c3e099106 100644 --- a/apps/openmw/mwvr/vrsession.hpp +++ b/apps/openmw/mwvr/vrsession.hpp @@ -84,6 +84,7 @@ namespace MWVR std::condition_variable mCondition{}; FramePhase mXrSyncPhase{ FramePhase::Cull }; + bool mUseSteadyClock{ false }; long long mFrames{ 0 }; long long mLastRenderedFrame{ 0 }; long long mLastPredictedDisplayTime{ 0 }; diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 8e20e3b72..4f05f2192 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -916,4 +916,8 @@ realistic combat maximum swing velocity = 4.0 haptics enabled = true # Flip the order of eyes in the mirror texture (to allow cross eyed view) -flip mirror texture order = false \ No newline at end of file +flip mirror texture order = false + +# Work around for some preview openxr runtimes whose display time predictions do not work +# Use this if tracking seems crazy. +use steady clock = true \ No newline at end of file