diff --git a/hal/src/main/native/sim/HAL.cpp b/hal/src/main/native/sim/HAL.cpp index 000ad8f80d1..e08e69cae1f 100644 --- a/hal/src/main/native/sim/HAL.cpp +++ b/hal/src/main/native/sim/HAL.cpp @@ -13,7 +13,6 @@ #ifdef _WIN32 #include -#pragma comment(lib, "Winmm.lib") #endif // _WIN32 #include "ErrorsInternal.h" @@ -27,6 +26,14 @@ #include "hal/simulation/SimCallbackRegistry.h" #include "mockdata/RoboRioDataInternal.h" +#ifdef _WIN32 +extern "C" NTSYSAPI NTSTATUS NTAPI NtSetTimerResolution( + ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution); +extern "C" NTSYSAPI NTSTATUS NTAPI +NtQueryTimerResolution(PULONG MinimumResolution, PULONG MaximumResolution, + PULONG CurrentResolution); +#endif // _WIN32 + using namespace hal; namespace { @@ -364,19 +371,50 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) { initialized = true; -// Set Timer Precision to 1ms on Windows +// Set Timer Precision to 0.5ms on Windows #ifdef _WIN32 - TIMECAPS tc; - if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) { - UINT target = (std::min)(static_cast(1), tc.wPeriodMin); - timeBeginPeriod(target); - std::atexit([]() { - TIMECAPS tc; - if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) { - UINT target = (std::min)(static_cast(1), tc.wPeriodMin); - timeEndPeriod(target); - } - }); + // https://stackoverflow.com/questions/3141556/how-to-setup-timer-resolution-to-0-5-ms + ULONG min, max, current; + NtQueryTimerResolution(&min, &max, ¤t); + + static ULONG currentRes; + NtSetTimerResolution(max, TRUE, ¤tRes); + std::atext([]() { + ULONG ignore; + NtSetTimerResolution(currentRes, TRUE, &ignore); + }); + + // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setprocessinformation + // Enable HighQoS to achieve maximum performance, and turn off power saving. + { + PROCESS_POWER_THROTTLING_STATE PowerThrottling{}; + PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION; + PowerThrottling.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED; + PowerThrottling.StateMask = 0; + + SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, + &PowerThrottling, sizeof(PowerThrottling)); + } + + // https://forums.oculusvr.com/t5/General/SteamVR-has-fixed-the-problems-with-Windows-11/td-p/956413 + // Always honor Timer Resolution Requests. This is to ensure that the timer + // resolution set-up above sticks through transitions of the main window (eg: + // minimization). + { + // This setting was introduced in Windows 11 and the definition is not + // available in older headers. +#ifndef PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION + const auto PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION = 0x4U; +#endif + + PROCESS_POWER_THROTTLING_STATE PowerThrottling{}; + PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION; + PowerThrottling.ControlMask = + PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION; + PowerThrottling.StateMask = 0; + + SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, + &PowerThrottling, sizeof(PowerThrottling)); } #endif // _WIN32