diff --git a/Core/FrameTiming.cpp b/Core/FrameTiming.cpp index 8a9b10e63d..f89119daef 100644 --- a/Core/FrameTiming.cpp +++ b/Core/FrameTiming.cpp @@ -32,6 +32,17 @@ FrameTiming g_frameTiming; +void WaitUntil(double now, double timestamp) { +#ifdef _WIN32 + while (time_now_d() < timestamp) { + sleep_ms(1); // Sleep for 1ms on this thread + } +#else + const double left = timestamp - now; + usleep((long)(left * 1000000)); +#endif +} + inline Draw::PresentMode GetBestImmediateMode(Draw::PresentMode supportedModes) { if (supportedModes & Draw::PresentMode::MAILBOX) { return Draw::PresentMode::MAILBOX; @@ -50,6 +61,22 @@ void FrameTiming::Reset(Draw::DrawContext *draw) { } } +void FrameTiming::DeferWaitUntil(double until, double *curTimePtr) { + _dbg_assert_(until > 0.0); + waitUntil_ = until; + curTimePtr_ = curTimePtr; +} + +void FrameTiming::PostSubmit() { + if (waitUntil_ != 0.0) { + WaitUntil(time_now_d(), waitUntil_); + if (curTimePtr_) { + *curTimePtr_ = waitUntil_; + } + waitUntil_ = 0.0; + } +} + Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval) { Draw::PresentMode mode = Draw::PresentMode::FIFO; diff --git a/Core/FrameTiming.h b/Core/FrameTiming.h index 04e938e898..3a3048db50 100644 --- a/Core/FrameTiming.h +++ b/Core/FrameTiming.h @@ -8,14 +8,23 @@ namespace Draw { class DrawContext; } -struct FrameTiming { +class FrameTiming { +public: + void DeferWaitUntil(double until, double *curTimePtr); + void PostSubmit(); + void Reset(Draw::DrawContext *draw); + // Some backends won't allow changing this willy nilly. Draw::PresentMode presentMode; int presentInterval; - void Reset(Draw::DrawContext *draw); +private: + double waitUntil_; + double *curTimePtr_; }; extern FrameTiming g_frameTiming; Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval); + +void WaitUntil(double now, double timestamp); diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 234d7e5d1c..671b096589 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -440,15 +440,7 @@ static void DoFrameTiming(bool throttle, bool *skipFrame, float scaledTimestep, // Wait until we've caught up. // TODO: This is the wait we actually move to after the frame. // But watch out, curFrameTime below must be updated correctly - I think. - - while (time_now_d() < nextFrameTime) { -#ifdef _WIN32 - sleep_ms(1); // Sleep for 1ms on this thread -#else - const double left = nextFrameTime - curFrameTime; - usleep((long)(left * 1000000)); -#endif - } + WaitUntil(curFrameTime, nextFrameTime); } curFrameTime = time_now_d(); } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 6d9ca17bf8..63e19abed1 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1117,6 +1117,7 @@ void NativeFrame(GraphicsContext *graphicsContext) { // This, between EndFrame and Present, is where we should actually wait to do present time management. // There might not be a meaningful distinction here for all backends.. + g_frameTiming.PostSubmit(); if (renderCounter < 10 && ++renderCounter == 10) { // We're rendering fine, clear out failure info.