[hal] Fix Java sim timing on Windows (#6910)

Also set power throttling options correctly.
This commit is contained in:
Ryan Blue
2024-08-02 21:56:58 -04:00
committed by GitHub
parent 5ff68079e2
commit ecfd3861e8

View File

@@ -13,6 +13,7 @@
#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);
@@ -371,6 +372,19 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
// Set Timer Precision to 0.5ms on Windows
#ifdef _WIN32
// Use timeGetDevCaps as well to prevent Java from interfering
TIMECAPS tc;
if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) {
UINT target = (std::max)(static_cast<UINT>(1), tc.wPeriodMin);
timeBeginPeriod(target);
std::atexit([]() {
TIMECAPS tc;
if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) {
UINT target = (std::max)(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, &current) == 0) {
@@ -385,31 +399,33 @@ HAL_Bool HAL_Initialize(int32_t timeout, int32_t mode) {
// 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.
// 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;
const auto PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION = 0x4U;
#endif
PROCESS_POWER_THROTTLING_STATE PowerThrottling{};
// Try both at once, and if that doesn't succeed, only set HighQoS
PROCESS_POWER_THROTTLING_STATE PowerThrottling{};
PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
PowerThrottling.ControlMask =
PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION |
PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
PowerThrottling.StateMask = 0;
auto status =
SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling,
&PowerThrottling, sizeof(PowerThrottling));
// setting both failed, fall back to HighQoS only
if (status == 0) {
PowerThrottling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
PowerThrottling.ControlMask =
PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
PowerThrottling.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
PowerThrottling.StateMask = 0;
SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling,