mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:53:52 +00:00
steady clock prediction was not quite right
This commit is contained in:
parent
cea73ead09
commit
9e16e592e8
7 changed files with 30 additions and 20 deletions
|
@ -45,10 +45,11 @@ namespace MWVR
|
|||
return impl().handleEvents();
|
||||
}
|
||||
|
||||
void OpenXRManager::waitFrame()
|
||||
long long OpenXRManager::waitFrame()
|
||||
{
|
||||
if (realized())
|
||||
return impl().waitFrame();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenXRManager::beginFrame()
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace MWVR
|
|||
bool realized();
|
||||
|
||||
//! Forward call to xrWaitFrame()
|
||||
void waitFrame();
|
||||
long long waitFrame();
|
||||
|
||||
//! Forward call to xrBeginFrame()
|
||||
void beginFrame();
|
||||
|
|
|
@ -317,7 +317,7 @@ namespace MWVR
|
|||
Log(Debug::Verbose) << ss.str();
|
||||
}
|
||||
|
||||
void
|
||||
long long
|
||||
OpenXRManagerImpl::waitFrame()
|
||||
{
|
||||
XrFrameWaitInfo frameWaitInfo{ XR_TYPE_FRAME_WAIT_INFO };
|
||||
|
@ -325,6 +325,7 @@ namespace MWVR
|
|||
|
||||
CHECK_XRCMD(xrWaitFrame(mSession, &frameWaitInfo, &frameState));
|
||||
mFrameState = frameState;
|
||||
return frameState.predictedDisplayTime;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace MWVR
|
|||
OpenXRManagerImpl(void);
|
||||
~OpenXRManagerImpl(void);
|
||||
|
||||
void waitFrame();
|
||||
long long waitFrame();
|
||||
void beginFrame();
|
||||
void endFrame(int64_t displayTime, int layerCount, const std::array<CompositionLayerProjectionView, 2>& layerStack);
|
||||
bool xrSessionRunning() const { return mSessionRunning; }
|
||||
|
|
|
@ -149,7 +149,7 @@ namespace MWVR
|
|||
layerStack[(int)Side::RIGHT_SIDE].fov = frameMeta->mPredictedPoses.view[(int)Side::RIGHT_SIDE].fov;
|
||||
|
||||
Log(Debug::Debug) << frameMeta->mFrameNo << ": EndFrame " << std::this_thread::get_id();
|
||||
xr->endFrame(frameMeta->mPredictedDisplayTime, 1, layerStack);
|
||||
xr->endFrame(frameMeta->mXrPredictedDisplayTime, 1, layerStack);
|
||||
xr->xrResourceReleased();
|
||||
}
|
||||
|
||||
|
@ -161,6 +161,8 @@ namespace MWVR
|
|||
mLastFrameInterval = std::chrono::duration_cast<std::chrono::nanoseconds>(now - mLastRenderedFrameTimestamp);
|
||||
mLastRenderedFrameTimestamp = now;
|
||||
mLastRenderedFrame = getFrame(FramePhase::Swap)->mFrameNo;
|
||||
mLastPredictedDisplayTime = getFrame(FramePhase::Swap)->mXrPredictedDisplayTime;
|
||||
mLastPredictedDisplayPeriod = xr->getLastPredictedDisplayPeriod();;
|
||||
|
||||
// Using this to track framerate over the course of gameplay, rather than just seeing the instantaneous
|
||||
auto seconds = std::chrono::duration_cast<std::chrono::duration<double>>(now - mStart).count();
|
||||
|
@ -206,10 +208,12 @@ namespace MWVR
|
|||
// For example, shadows do some draw calls during cull an as such phase should be "Cull" or earlier with shadows enabled.
|
||||
// But may be "Draw" without shadows.
|
||||
if (phase == mXrSyncPhase && getFrame(phase)->mShouldRender)
|
||||
doFrameSync();
|
||||
{
|
||||
getFrame(phase)->mXrPredictedDisplayTime = doFrameSync();
|
||||
}
|
||||
}
|
||||
|
||||
void VRSession::doFrameSync()
|
||||
long long VRSession::doFrameSync()
|
||||
{
|
||||
auto begin = std::chrono::steady_clock::now();
|
||||
{
|
||||
|
@ -222,7 +226,7 @@ namespace MWVR
|
|||
auto condEnd = std::chrono::steady_clock::now();
|
||||
auto* xr = Environment::get().getManager();
|
||||
Log(Debug::Debug) << mFrames << ": WaitFrame " << std::this_thread::get_id();
|
||||
xr->waitFrame();
|
||||
auto predictedDisplayTime = xr->waitFrame();
|
||||
Log(Debug::Debug) << mFrames << ": BeginFrame " << std::this_thread::get_id();
|
||||
xr->beginFrame();
|
||||
auto xrSyncEnd = std::chrono::steady_clock::now();
|
||||
|
@ -231,6 +235,7 @@ namespace MWVR
|
|||
auto xrSyncTime = std::chrono::duration_cast<std::chrono::milliseconds>(xrSyncEnd - condEnd);
|
||||
Log(Debug::Debug) << "condTime: " << condTime.count() << ", xrSyncTime: " << xrSyncTime.count();
|
||||
|
||||
return predictedDisplayTime;
|
||||
}
|
||||
|
||||
std::unique_ptr<VRSession::VRFrameMeta>& VRSession::getFrame(FramePhase phase)
|
||||
|
@ -249,25 +254,27 @@ namespace MWVR
|
|||
xr->handleEvents();
|
||||
|
||||
auto epochTime = std::chrono::duration_cast<std::chrono::nanoseconds>(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<double>(mLastFrameInterval.count()) / static_cast<double>(predictedDisplayPeriod);
|
||||
auto predictedDisplayTime = mLastPredictedDisplayTime;
|
||||
auto predictedDisplayPeriod = mLastPredictedDisplayPeriod;
|
||||
double intervalsf = static_cast<double>(mLastFrameInterval.count()) / static_cast<double>(predictedDisplayPeriod);
|
||||
int intervals = std::max((int)std::roundf(intervalsf), 1);
|
||||
|
||||
if (predictedDisplayTime == 0)
|
||||
predictedDisplayTime = epochTime;
|
||||
|
||||
//////////////////////// OCULUS BUG
|
||||
//////////////////// 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.
|
||||
if(mUseSteadyClock)
|
||||
predictedDisplayTime = epochTime;
|
||||
|
||||
if (mFrames > 1)
|
||||
if (mUseSteadyClock)
|
||||
{
|
||||
predictedDisplayTime = epochTime + intervals * predictedDisplayPeriod;
|
||||
}
|
||||
else
|
||||
{
|
||||
int intervals = std::max((int)std::roundf(intervalsf), 1);
|
||||
predictedDisplayTime = predictedDisplayTime + intervals * (mFrames - mLastRenderedFrame) * predictedDisplayPeriod;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PoseSet predictedPoses{};
|
||||
|
||||
xr->enablePredictions();
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace MWVR
|
|||
{
|
||||
long long mFrameNo{ 0 };
|
||||
long long mPredictedDisplayTime{ 0 };
|
||||
long long mXrPredictedDisplayTime{ 0 };
|
||||
PoseSet mPredictedPoses{};
|
||||
bool mShouldRender{ false };
|
||||
};
|
||||
|
@ -60,7 +61,7 @@ namespace MWVR
|
|||
void prepareFrame();
|
||||
|
||||
//! Synchronize with openxr
|
||||
void doFrameSync();
|
||||
long long doFrameSync();
|
||||
|
||||
//! Angles to be used for overriding movement direction
|
||||
void movementAngles(float& yaw, float& pitch);
|
||||
|
|
|
@ -926,4 +926,4 @@ 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
|
||||
use steady clock = false
|
Loading…
Reference in a new issue