Fix regression with vsync timing on Windows introduced in 11ee3fa

This commit is contained in:
Herman S.
2025-10-03 23:06:31 +09:00
parent 7f631aa954
commit eff0ee1ecb
+47
View File
@@ -163,11 +163,57 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
1000.0 / static_cast<double>(
normalized_framerate_limit))
: 1.0;
uint64_t last_frame_time = Clock::QueryGuestTickCount();
// Sleep for 90% of the vblank duration on Windows, spin for 10%
// Linux uses full sleep duration due to scheduler quantum issues
#if XE_PLATFORM_WIN32
constexpr double duration_scalar = 0.90;
#endif
#if XE_PLATFORM_LINUX
constexpr double duration_scalar = 1.0;
#endif
while (frame_limiter_worker_running_) {
register_file()->values[XE_GPU_REG_D1MODE_V_COUNTER] +=
GetInternalDisplayResolution().second;
#if XE_PLATFORM_WIN32
if (cvars::vsync) {
const uint64_t current_time = Clock::QueryGuestTickCount();
const uint64_t tick_freq = Clock::guest_tick_frequency();
const uint64_t time_delta = current_time - last_frame_time;
const double elapsed_d =
static_cast<double>(time_delta) /
(static_cast<double>(tick_freq) / 1000.0);
if (elapsed_d >= vsync_duration_d) {
last_frame_time = current_time;
MarkVblank();
const uint64_t estimated_nanoseconds = static_cast<uint64_t>(
(vsync_duration_d * 1000000.0) *
duration_scalar); // 1000 microseconds = 1 ms
threading::NanoSleep(estimated_nanoseconds);
}
}
if (!cvars::vsync) {
MarkVblank();
if (normalized_framerate_limit > 0) {
// framerate_limit is over 0, vsync disabled
// - No VSYNC + limited frames defined by user
uint64_t framerate_limited_sleep_time =
1000000000 / normalized_framerate_limit;
xe::threading::NanoSleep(framerate_limited_sleep_time);
} else {
// framerate_limit is 0, vsync disabled
// - No VSYNC + unlimited frames
xe::threading::Sleep(std::chrono::milliseconds(1));
}
}
#endif
#if XE_PLATFORM_LINUX
// Linux: Use simplified timing logic to avoid oversleeping
MarkVblank();
if (cvars::vsync || normalized_framerate_limit > 0) {
@@ -180,6 +226,7 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
} else {
xe::threading::Sleep(std::chrono::milliseconds(1));
}
#endif
}
return 0;
},