From cc60814334667ff724cbbe167c8ef44cbdc34f0b Mon Sep 17 00:00:00 2001 From: GoaLitiuM Date: Sat, 29 May 2021 19:46:37 +0300 Subject: [PATCH] Increase accuracy of Windows Sleep function Windows 10 version 1803 (build 17134) and later versions support high-resolution waitable timer, which offers much better accuracy over Sleep function without the need of increasing the global timer resolution. For older versions of Windows, we reduce the timer resolution to 1ms and use normal waitable timer for sleeping. --- Source/Engine/Platform/Win32/Win32Platform.cpp | 16 +++++++++++++++- .../Engine/Platform/Windows/WindowsPlatform.cpp | 7 +++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Platform/Win32/Win32Platform.cpp b/Source/Engine/Platform/Win32/Win32Platform.cpp index 31c0f4a36..9d2041547 100644 --- a/Source/Engine/Platform/Win32/Win32Platform.cpp +++ b/Source/Engine/Platform/Win32/Win32Platform.cpp @@ -456,7 +456,21 @@ void Win32Platform::SetThreadAffinityMask(uint64 affinityMask) void Win32Platform::Sleep(int32 milliseconds) { - ::Sleep(static_cast(milliseconds)); + static thread_local HANDLE timer = NULL; + if (timer == NULL) + { + // Attempt to create high-resolution timer for each thread (Windows 10 build 17134 or later) + timer = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); + if (timer == NULL) // fallback for older versions of Windows + timer = CreateWaitableTimer(NULL, TRUE, NULL); + } + + // Negative value is relative to current time, minimum waitable time is 10 microseconds + LARGE_INTEGER dueTime; + dueTime.QuadPart = -int64_t(milliseconds) * 10000; + + SetWaitableTimerEx(timer, &dueTime, 0, NULL, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); } double Win32Platform::GetTimeSeconds() diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 1c87c19cb..89e050267 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -18,6 +18,7 @@ #include "../Win32/IncludeWindowsHeaders.h" #include #include +#include #include #include #if CRASH_LOG_ENABLE @@ -579,6 +580,12 @@ bool WindowsPlatform::Init() return true; } + // Set lowest possible timer resolution for previous Windows versions + if (VersionMajor < 10 || (VersionMajor == 10 && VersionBuild < 17134)) + { + timeBeginPeriod(1); + } + DWORD tmp; Char buffer[256];