From 57fe5117e0cf5c214fb8bd2124f6fe8dccfda74e Mon Sep 17 00:00:00 2001 From: AshishRibbon Date: Mon, 25 May 2026 23:14:04 -0700 Subject: [PATCH] Fix: TargetFrameRate setter used stale value and ignored vsync (#59) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two distinct bugs in the FPS settings path: Bug A — TargetFrameRate setter read S_TargetFrameRate before storing the new value, so the limiter target was always one step behind the slider. Rewrote the setter to store value first, use Math.Max for parity with InitalizeFPSThings, and respect UncappedFPS. Bug B — InitalizeFPSThings explicitly disabled the rate limiter when vsync was on, trusting vsync alone to cap FPS. On setups where vsync silently fails to cap (G-Sync / FreeSync / certain windowed configs) this leaves FPS uncapped at startup — closes #59. Made the rate limiter a safety net: enabled whenever UncappedFPS && TargetFrameRate >= 60, regardless of vsync. UseVSync setter updated to match so the two apply paths stay consistent. Updated the V-Sync menu description to reflect the new semantics (and fixed the "Verticaly" typo). --- DuckGame/AddedContent/DGRSettings.cs | 31 +++++++--------------------- DuckGame/src/MonoTime/Options.cs | 2 +- 2 files changed, 8 insertions(+), 25 deletions(-) diff --git a/DuckGame/AddedContent/DGRSettings.cs b/DuckGame/AddedContent/DGRSettings.cs index 05db001d..1a793ade 100644 --- a/DuckGame/AddedContent/DGRSettings.cs +++ b/DuckGame/AddedContent/DGRSettings.cs @@ -314,19 +314,10 @@ public static bool UseVSync set { MonoMain.graphics.SynchronizeWithVerticalRetrace = value; - //when vsync is ON we never want to use the draw rate limiter because vsync will do that - if (value) - { - Program.main.UseDrawRateLimiter = false; - } - //when vsync is OFF we only want to use the rate limiter if: - //Uncapped FPS is on && The user has set a target fps that is not 0 - else - { - Program.main.UseDrawRateLimiter = (UncappedFPS && TargetFrameRate != 0); - } - S_UseVSync = value; + // Rate limiter is also applied as a safety net: vsync silently fails to cap on some + // setups (G-Sync / FreeSync / certain windowed configs), so honor FPS Target regardless. + Program.main.UseDrawRateLimiter = UncappedFPS && TargetFrameRate >= 60; MonoMain.graphics.ApplyChanges(); } } @@ -343,17 +334,9 @@ public static int TargetFrameRate } set { - if (value >= 60) - { - Program.main.DrawRateLimiterTarget = S_TargetFrameRate; - Program.main.UseDrawRateLimiter = true; - S_TargetFrameRate = value; - } - else - { - Program.main.UseDrawRateLimiter = false; - S_TargetFrameRate = 0; - } + S_TargetFrameRate = value >= 60 ? value : 0; + Program.main.DrawRateLimiterTarget = Math.Max(S_TargetFrameRate, 60); + Program.main.UseDrawRateLimiter = UncappedFPS && S_TargetFrameRate >= 60; } } @@ -362,7 +345,7 @@ public static void InitalizeFPSThings() MonoMain.graphics.SynchronizeWithVerticalRetrace = UseVSync; Program.main.UnFixedDraw = UncappedFPS; Program.main.DrawRateLimiterTarget = Math.Max(TargetFrameRate,60); - Program.main.UseDrawRateLimiter = !UseVSync && UncappedFPS && TargetFrameRate >= 60; + Program.main.UseDrawRateLimiter = UncappedFPS && TargetFrameRate >= 60; Program.main.TargetElapsedTime = TimeSpan.FromTicks(163934); // Default to 61ups -Lucky diff --git a/DuckGame/src/MonoTime/Options.cs b/DuckGame/src/MonoTime/Options.cs index 534273b6..1aac87bf 100644 --- a/DuckGame/src/MonoTime/Options.cs +++ b/DuckGame/src/MonoTime/Options.cs @@ -534,7 +534,7 @@ public static UIMenu CreateDGRGraphicsMenu(UIMenu pPrev) }); menu.Add(new UIMenuItemToggle("Use V-Sync", field: new FieldBinding(typeof(DGRSettings), nameof(DGRSettings.UseVSync))) { - dgrDescription = "Verticaly synced drawing, overrides FPS target (REQUIRES RESTART)" + dgrDescription = "Vertically synced drawing. Works alongside FPS Target as a cap (REQUIRES RESTART)" }); menu.Add(new UIMenuItemNumber("FPS Target", field: new FieldBinding(typeof(DGRSettings), nameof(DGRSettings.TargetFrameRate), 0, 1000, 60), step: 60)