From 53c63b6dc2dc0662a4f8da6ec7a817c19184a771 Mon Sep 17 00:00:00 2001 From: 0x1Nawaf Date: Fri, 23 Oct 2026 15:43:52 +0000 Subject: [PATCH 1/2] fix: keep a slightly early vsync tick for frame pacing --- app/src/main/cpp/waylandcomp/src/compositor.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/app/src/main/cpp/waylandcomp/src/compositor.c b/app/src/main/cpp/waylandcomp/src/compositor.c index 95a8bf83a..fb15d50c3 100644 --- a/app/src/main/cpp/waylandcomp/src/compositor.c +++ b/app/src/main/cpp/waylandcomp/src/compositor.c @@ -807,11 +807,21 @@ static uint32_t nominal_refresh_ns(void) { return (uint32_t)(1000000000000LL / (int64_t)mhz); } +/* Gamescope paces from this timestamp (#717). The Choreographer tick is often still + * slightly ahead of this thread, because the UI thread queues the callback, and that + * used to throw the tick away (render_ns < tick) and report the draw time instead. + * Keep a tick within one refresh of the draw, ahead or behind. A missing tick, or one + * more than a refresh away, falls back to the draw time. Never report the next refresh: + * gamescope would wake a frame late. */ static int64_t presented_ns(int64_t render_ns) { - if (!g_tick_vsync_ns || render_ns - g_last_vsync_ns > (int64_t)nominal_refresh_ns() || - render_ns < g_tick_vsync_ns) + int64_t tick = g_tick_vsync_ns; + int64_t refresh = (int64_t)nominal_refresh_ns(); + if (!tick || render_ns - g_last_vsync_ns > refresh) return render_ns; - return g_tick_vsync_ns; + int64_t delta = render_ns - tick; + if (delta > refresh || -delta > refresh) + return render_ns; + return tick; } static void feedback_present_all(struct wl_list *list, int64_t t) { From 06946fe8ae7fddff9e68ece65e23458f4595f6f8 Mon Sep 17 00:00:00 2001 From: maxjivi05 Date: Fri, 23 Oct 2026 16:01:41 -0400 Subject: [PATCH 2/2] chore: drop comments --- app/src/main/cpp/waylandcomp/src/compositor.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/src/main/cpp/waylandcomp/src/compositor.c b/app/src/main/cpp/waylandcomp/src/compositor.c index fb15d50c3..1be637a7b 100644 --- a/app/src/main/cpp/waylandcomp/src/compositor.c +++ b/app/src/main/cpp/waylandcomp/src/compositor.c @@ -807,12 +807,6 @@ static uint32_t nominal_refresh_ns(void) { return (uint32_t)(1000000000000LL / (int64_t)mhz); } -/* Gamescope paces from this timestamp (#717). The Choreographer tick is often still - * slightly ahead of this thread, because the UI thread queues the callback, and that - * used to throw the tick away (render_ns < tick) and report the draw time instead. - * Keep a tick within one refresh of the draw, ahead or behind. A missing tick, or one - * more than a refresh away, falls back to the draw time. Never report the next refresh: - * gamescope would wake a frame late. */ static int64_t presented_ns(int64_t render_ns) { int64_t tick = g_tick_vsync_ns; int64_t refresh = (int64_t)nominal_refresh_ns();