From 4dc26a2bb27fb09edae8d5cb10ddb8f1311ecbcc Mon Sep 17 00:00:00 2001 From: Shokunin <30949000+tetrisgm@users.noreply.github.com> Date: Tue, 6 Oct 2026 00:48:50 -0700 Subject: [PATCH] Render thread: never skip two presents in a row R4 races present new content every other vblank, so at a saturated 4K widescreen frame two vblanks behind was common and about half the presents were dropped. Skipping is a catch-up step, not a frame-rate policy: one skipped present is always followed by a shown one. Co-Authored-By: Claude Opus 5.5 --- runtime/src/gpu_gl_renderer.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/runtime/src/gpu_gl_renderer.c b/runtime/src/gpu_gl_renderer.c index 5dfcd009..5300847d 100644 --- a/runtime/src/gpu_gl_renderer.c +++ b/runtime/src/gpu_gl_renderer.c @@ -9283,15 +9283,20 @@ static int rth_record_present(uint16_t op, int n, const int32_t *v) { static void rth_replay_present(const RtCmd *c, const uint8_t *p) { RthOvHdr hd; memcpy(&hd, p, sizeof hd); - if (rt_frames_ahead() >= 2) { + static int skipped_last = 0; + if (rt_frames_ahead() >= 2 && !skipped_last) { /* Two later frames are already recorded, so the emulation thread is * at (or near) the in-flight bound waiting on us. Showing this frame * would only delay those; skip its present (its drawing has been * replayed and stays). One frame behind is the normal pipelined - * state and still presents every frame. */ + * state and still presents every frame, and never two presents in a + * row are skipped, so a saturated render thread keeps showing at + * least every other frame. */ s_rth_presents_stale++; + skipped_last = 1; return; } + skipped_last = 0; const uint8_t *q = p + sizeof hd; memset(&s_rth_ov, 0, sizeof s_rth_ov); s_rth_ov.valid = 1;