From cf9e217e7b1cf78b949b52d7a2f6d38ca9d43d85 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Tue, 16 Aug 2022 08:57:40 +0000 Subject: [PATCH] [util] Support for fps limiter on non-Windows platforms Defaults to a sleep granularity of 0.5ms, which is slightly on the cautious side. Calls through to std::this_thread::sleep_for directly, which calls through to nanosleep. --- src/util/util_fps_limiter.cpp | 9 +++++++++ src/util/util_fps_limiter.h | 9 +++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/util/util_fps_limiter.cpp b/src/util/util_fps_limiter.cpp index 9354d6634..f7255a2d4 100644 --- a/src/util/util_fps_limiter.cpp +++ b/src/util/util_fps_limiter.cpp @@ -140,6 +140,7 @@ namespace dxvk { void FpsLimiter::updateSleepGranularity() { +#ifdef _WIN32 HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); if (ntdll) { @@ -166,10 +167,15 @@ namespace dxvk { // Assume 1ms sleep granularity by default m_sleepGranularity = TimerDuration(1ms); } +#else + // Assume 0.5ms sleep granularity by default + m_sleepGranularity = TimerDuration(500us); +#endif } void FpsLimiter::performSleep(TimerDuration sleepDuration) { +#ifdef _WIN32 if (NtDelayExecution) { LARGE_INTEGER ticks; ticks.QuadPart = -sleepDuration.count(); @@ -178,6 +184,9 @@ namespace dxvk { } else { std::this_thread::sleep_for(sleepDuration); } +#else + std::this_thread::sleep_for(sleepDuration); +#endif } } diff --git a/src/util/util_fps_limiter.h b/src/util/util_fps_limiter.h index 94890c2ce..a45f3c0e9 100644 --- a/src/util/util_fps_limiter.h +++ b/src/util/util_fps_limiter.h @@ -60,10 +60,17 @@ namespace dxvk { using TimePoint = dxvk::high_resolution_clock::time_point; +#ifdef _WIN32 + // On Windows, we use NtDelayExecution which has units of 100ns. using TimerDuration = std::chrono::duration>; using NtQueryTimerResolutionProc = UINT (WINAPI *) (ULONG*, ULONG*, ULONG*); using NtSetTimerResolutionProc = UINT (WINAPI *) (ULONG, BOOL, ULONG*); using NtDelayExecutionProc = UINT (WINAPI *) (BOOL, LARGE_INTEGER*); + NtDelayExecutionProc NtDelayExecution = nullptr; +#else + // On other platforms, we use the std library, which calls through to nanosleep -- which is ns. + using TimerDuration = std::chrono::nanoseconds; +#endif dxvk::mutex m_mutex; @@ -78,8 +85,6 @@ namespace dxvk { TimerDuration m_sleepGranularity = TimerDuration::zero(); TimerDuration m_sleepThreshold = TimerDuration::zero(); - NtDelayExecutionProc NtDelayExecution = nullptr; - TimePoint sleep(TimePoint t0, TimerDuration duration); void initialize();