From a37e74fb4dae670546658e54cbad41956813d181 Mon Sep 17 00:00:00 2001 From: mchughalex <25671999+mchughalex@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:33:52 +0100 Subject: [PATCH] render: derive the auto frame cap from a refresh-scaled margin (SDK bump) --- src/skate3_native_render.cpp | 26 ++++++++++++++++---------- third_party/rexglue-sdk | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/skate3_native_render.cpp b/src/skate3_native_render.cpp index 69ae6e6..2d070de 100644 --- a/src/skate3_native_render.cpp +++ b/src/skate3_native_render.cpp @@ -47,13 +47,18 @@ REXCVAR_DEFINE_DOUBLE(skate3_guest_fps_cap, 0.0, "Skate 3", .lifecycle(rex::cvar::Lifecycle::kHotReload); REXCVAR_DEFINE_BOOL(skate3_guest_fps_cap_auto, true, "Skate 3", "Derive the guest frame cap from the display the window is on: " - "cap at (refresh rate - 4) fps, the VRR recipe above, without " - "hand-tuning per monitor. Above the display refresh the extra " - "frames cannot be shown anyway; refreshes beat-sample the " - "frame stream and steady motion judders (measured: a " - "mathematically perfect synthetic pan judders at 330 fps on a " - "144 Hz panel and is smooth capped below it). Overrides " - "skate3_guest_fps_cap while the display refresh is known.") + "cap a safety margin below the refresh rate (4 fps or 5%, " + "whichever is larger; see rex::ui::Window::AutoFrameCapHz), " + "the VRR recipe above, without hand-tuning per monitor. Above " + "the display refresh the extra frames cannot be shown anyway; " + "refreshes beat-sample the frame stream and steady motion " + "judders (measured: a mathematically perfect synthetic pan " + "judders at 330 fps on a 144 Hz panel and is smooth capped " + "below it). The margin must also absorb swap-to-present " + "jitter: presents run with tearing allowed, so a present " + "landing inside the panel's minimum refresh period tears even " + "under VRR. Overrides skate3_guest_fps_cap while the display " + "refresh is known.") .lifecycle(rex::cvar::Lifecycle::kHotReload); namespace skate3::native_render { @@ -228,9 +233,10 @@ void PaceGuestFrame() { if (REXCVAR_GET(skate3_guest_fps_cap_auto)) { // Refresh-derived cap (see the cvar). Falls through to the explicit cap // while the platform hasn't reported a refresh rate. - const double hz = double(rex::ui::Window::CachedDisplayRefreshHz()); - if (hz >= 30.0) { - cap = hz - 4.0; + const double auto_cap = double(rex::ui::Window::AutoFrameCapHz( + rex::ui::Window::CachedDisplayRefreshHz())); + if (auto_cap > 0.0) { + cap = auto_cap; } } static std::chrono::steady_clock::time_point s_next{}; diff --git a/third_party/rexglue-sdk b/third_party/rexglue-sdk index 79761cb..9100b27 160000 --- a/third_party/rexglue-sdk +++ b/third_party/rexglue-sdk @@ -1 +1 @@ -Subproject commit 79761cbdd5752e43422e93f0903ef604ef7e4650 +Subproject commit 9100b278b70c4f0994a47639eb11107c570ee76d