[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.
This commit is contained in:
Joshua Ashton 2022-08-16 08:57:40 +00:00 committed by Philip Rebohle
parent d1e2b89282
commit cf9e217e7b
2 changed files with 16 additions and 2 deletions

View File

@ -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
}
}

View File

@ -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<int64_t, std::ratio<1, 10000000>>;
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();