steady clock prediction was not quite right

pull/615/head
Mads Buvik Sandvei 5 years ago
parent cea73ead09
commit 9e16e592e8

@ -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…
Cancel
Save