From f8cb4807797949532fb708839e897f408bc79c07 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 4 Dec 2022 15:40:46 +1000 Subject: [PATCH] Timer: Improve SleepUntil() --- src/common/timer.cpp | 14 +++++++------- src/core/host_display.cpp | 7 ++++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/common/timer.cpp b/src/common/timer.cpp index 41ffbde81..73805b787 100644 --- a/src/common/timer.cpp +++ b/src/common/timer.cpp @@ -1,4 +1,5 @@ #include "timer.h" +#include "types.h" #include #include @@ -109,20 +110,19 @@ void Timer::SleepUntil(Value value, bool exact) } else { - const std::int64_t diff = static_cast(value - GetCurrentValue()); + const s64 diff = static_cast(value - GetCurrentValue()); if (diff <= 0) return; HANDLE timer = GetSleepTimer(); if (timer) { - FILETIME ft; - GetSystemTimeAsFileTime(&ft); + const u64 one_hundred_nanos_diff = static_cast(ConvertValueToNanoseconds(diff) / 100.0); + if (one_hundred_nanos_diff == 0) + return; LARGE_INTEGER fti; - fti.LowPart = ft.dwLowDateTime; - fti.HighPart = ft.dwHighDateTime; - fti.QuadPart += diff; + fti.QuadPart = -static_cast(one_hundred_nanos_diff); if (SetWaitableTimer(timer, &fti, 0, nullptr, nullptr, FALSE)) { @@ -132,7 +132,7 @@ void Timer::SleepUntil(Value value, bool exact) } // falling back to sleep... bad. - Sleep(static_cast(static_cast(diff) / 1000000)); + Sleep(static_cast(static_cast(diff) / 1000000)); } } diff --git a/src/core/host_display.cpp b/src/core/host_display.cpp index 36e05526a..79e2d6620 100644 --- a/src/core/host_display.cpp +++ b/src/core/host_display.cpp @@ -124,12 +124,17 @@ void HostDisplay::ThrottlePresentation() const u64 sleep_period = Common::Timer::ConvertNanosecondsToValue(1e+9f / static_cast(throttle_rate)); const u64 current_ts = Common::Timer::GetCurrentValue(); - if (current_ts >= m_last_frame_displayed_time) + // Allow it to fall behind/run ahead up to 2*period. Sleep isn't that precise, plus we need to + // allow time for the actual rendering. + const u64 max_variance = sleep_period * 2; + if (static_cast(std::abs(static_cast(current_ts - m_last_frame_displayed_time))) > max_variance) m_last_frame_displayed_time = current_ts + sleep_period; else m_last_frame_displayed_time += sleep_period; + Common::Timer tt; Common::Timer::SleepUntil(m_last_frame_displayed_time, false); + Log_WarningPrintf("sleep time %.2f ms", tt.GetTimeMilliseconds()); } bool HostDisplay::GetHostRefreshRate(float* refresh_rate)