fix(launcher): continuous vsync-paced present for stable VRR
The 60fps cap still left 16ms gaps with no present; on windowed G-Sync/FreeSync DWM keeps moving the window in and out of the VRR path across those gaps and the refresh rate swings, which the panel shows as flicker. Render continuously (request_repaint every frame) with vsync on so the window stays continuously in VRR at the display's own variable refresh.
This commit is contained in:
+9
-9
@@ -1804,15 +1804,15 @@ impl LauncherApp {
|
||||
|
||||
impl eframe::App for LauncherApp {
|
||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||
// Present at a steady ~60 FPS while the window is open. egui is normally
|
||||
// reactive and would idle at ~2 FPS (a 500 ms repaint), but on a G-Sync /
|
||||
// FreeSync (VRR) display that sits below the VRR floor: the panel engages
|
||||
// low-framerate compensation, and every hover/animation briefly spikes the
|
||||
// rate and drops back, so the refresh rate keeps swinging and the panel
|
||||
// visibly flickers. A constant, in-range cadence gives VRR a single rate to
|
||||
// lock onto and removes the flicker. 16 ms is monitor-independent and cheap
|
||||
// for a UI this small; vsync (on by default) keeps present times regular.
|
||||
ctx.request_repaint_after(std::time::Duration::from_millis(16));
|
||||
// Render continuously (present every vsync) instead of reactively. egui
|
||||
// normally idles at a low, bursty repaint rate; on a G-Sync / FreeSync
|
||||
// (VRR) display a windowed app that presents in bursts with idle gaps
|
||||
// makes DWM keep moving the window in and out of the VRR path and the
|
||||
// refresh rate swing — which the panel shows as flicker. Presenting on
|
||||
// every frame keeps the window continuously in VRR at the display's own
|
||||
// (variable) refresh, which is stable. vsync (on by default) paces this to
|
||||
// the monitor rather than spinning uncapped.
|
||||
ctx.request_repaint();
|
||||
self.drive_restart_queue();
|
||||
|
||||
egui::TopBottomPanel::top("header")
|
||||
|
||||
@@ -22,6 +22,9 @@ fn main() -> eframe::Result<()> {
|
||||
.with_icon(app_icon())
|
||||
.with_inner_size([1040.0, 720.0])
|
||||
.with_min_inner_size([880.0, 600.0]),
|
||||
// Pair vsync with the display's VRR (G-Sync + Vsync is the recommended
|
||||
// combination): frames present on the monitor's own variable refresh.
|
||||
vsync: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user