From 1f96c3a2b3c97ea8e2856673f78e0f0f5f330c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 1 Mar 2025 19:13:06 +0100 Subject: [PATCH] Switch to sleep_precise for WaitUntil() which is used for frame timing. This can improve frame pacing slightly, not just on Windows actually. --- Common/TimeUtil.cpp | 14 ++++++++------ Core/FrameTiming.cpp | 11 ++++++++++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Common/TimeUtil.cpp b/Common/TimeUtil.cpp index b1a1798136..1f16898d18 100644 --- a/Common/TimeUtil.cpp +++ b/Common/TimeUtil.cpp @@ -51,6 +51,7 @@ void TimeInit() { QpcPerSecond = frequency.QuadPart; frequencyMult = 1.0 / static_cast(frequency.QuadPart); + // The timer will be automatically deleted on process destruction. Don't need to CloseHandle. Timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); #if !PPSSPP_PLATFORM(UWP) TIMECAPS caps; @@ -264,11 +265,13 @@ void sleep_ms(int ms, const char *reason) { #endif } -// Precise Windows sleep function from: https://github.com/blat-blatnik/Snippets/blob/main/precise_sleep.c -// Described in: https://blog.bearcats.nl/perfect-sleep-function/ - void sleep_precise(double seconds) { + if (seconds <= 0.0) { + return; + } #ifdef _WIN32 + // Precise Windows sleep function from: https://github.com/blat-blatnik/Snippets/blob/main/precise_sleep.c + // Described in: https://blog.bearcats.nl/perfect-sleep-function/ LARGE_INTEGER qpc; QueryPerformanceCounter(&qpc); INT64 targetQpc = (INT64)(qpc.QuadPart + seconds * QpcPerSecond); @@ -302,15 +305,14 @@ void sleep_precise(double seconds) { YieldProcessor(); QueryPerformanceCounter(&qpc); } -#else -#if defined(HAVE_LIBNX) + // On other platforms, we just do a conversion with more input precision than in sleep_ms which is restricted to whole milliseconds. +#elif defined(HAVE_LIBNX) svcSleepThread((int64_t)(seconds * 1000000000.0)); #elif defined(__EMSCRIPTEN__) emscripten_sleep(seconds * 1000.0); #else usleep(seconds * 1000000.0); #endif -#endif } // Return the current time formatted as Minutes:Seconds:Milliseconds diff --git a/Core/FrameTiming.cpp b/Core/FrameTiming.cpp index 1d1d84c8ed..b42c70f19a 100644 --- a/Core/FrameTiming.cpp +++ b/Core/FrameTiming.cpp @@ -19,6 +19,7 @@ // * Frame skipping. This gets complicated. // * The game not actually asking for flips, like in static loading screens +#include "ppsspp_config.h" #include "Common/Profiler/Profiler.h" #include "Common/Log.h" #include "Common/TimeUtil.h" @@ -35,7 +36,13 @@ FrameTiming g_frameTiming; void WaitUntil(double now, double timestamp, const char *reason) { -#ifdef _WIN32 +#if 1 + // Use precise timing. + sleep_precise(timestamp - now); +#else + +#if PPSSPP_PLATFORM(WINDOWS) + // Old method. TODO: Should we make an option? while (time_now_d() < timestamp) { sleep_ms(1, reason); // Sleep for 1ms on this thread } @@ -45,6 +52,8 @@ void WaitUntil(double now, double timestamp, const char *reason) { usleep((long)(left * 1000000)); } #endif + +#endif } inline Draw::PresentMode GetBestImmediateMode(Draw::PresentMode supportedModes) {