mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[hal] Windows sim: enable High QOS and honor timer resolution requests (#6908)
By default on Windows 11, power throttling will increase timer resolution if a window is occluded. Disable that behavior. Also enable high QOS to achieve maximum performance and turn off power saving. Also use internal APIs to set timer precision to 500 us if available.
This commit is contained in:
@@ -13,7 +13,12 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
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
|
||||
|
||||
#include "ErrorsInternal.h"
|
||||
@@ -364,19 +369,51 @@ 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<UINT>(1), tc.wPeriodMin);
|
||||
timeBeginPeriod(target);
|
||||
std::atexit([]() {
|
||||
TIMECAPS tc;
|
||||
if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) {
|
||||
UINT target = (std::min)(static_cast<UINT>(1), tc.wPeriodMin);
|
||||
timeEndPeriod(target);
|
||||
}
|
||||
});
|
||||
// https://stackoverflow.com/questions/3141556/how-to-setup-timer-resolution-to-0-5-ms
|
||||
ULONG min, max, current;
|
||||
if (NtQueryTimerResolution(&min, &max, ¤t) == 0) {
|
||||
ULONG currentRes;
|
||||
if (NtSetTimerResolution(max, TRUE, ¤tRes) == 0) {
|
||||
std::atexit([]() {
|
||||
ULONG currentRes;
|
||||
NtSetTimerResolution(0, FALSE, ¤tRes);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user