Switch to sleep_precise for WaitUntil() which is used for frame timing.

This can improve frame pacing slightly, not just on Windows actually.
This commit is contained in:
Henrik Rydgård 2025-03-01 19:13:06 +01:00
parent 4f8896eb19
commit 1f96c3a2b3
2 changed files with 18 additions and 7 deletions

View file

@ -51,6 +51,7 @@ void TimeInit() {
QpcPerSecond = frequency.QuadPart;
frequencyMult = 1.0 / static_cast<double>(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

View file

@ -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) {