* fix(app): book inline steps on the vblank grid, not on swap returns (#1141)
Inline mode with the swap interval at 1 fed the pacer the real time between steps.
A step starts when its swap returned plus whatever the loop did since, which is
0.3-1 ms of jitter on a quiet host. With the 60.05 Hz core's backlog phase creeping
across a period boundary every ~18 s, that jitter flipped takes near each boundary:
bursts of repeats and dropped frames that tracked frame cost and host state
(Cybermorph 16 -> 22-25 repeats a minute once #1117 made its frames cheaper,
51-62 on a loaded host).
SwapGrid (pacing.h) tracks the display's vblank grid from swaps that blocked, as
LateLatch does for the threaded loop. It hands stepEmulation a correction, so the
backlog gains the time between the swaps' vblanks. The tracked phase follows the
real vblanks, so the sum stays real time: no speed change, a 59.94 Hz panel
announced as 60 Hz included. When not locked (vsync off or released, non-blocking
swaps, VRR) the correction is 0, as before. The threaded path is untouched.
Tests: pacing_test gains swap-return jitter in its simulated loop (real time vs
grid, 60 / 59.94 / 120 Hz, PAL) and unit tests for SwapGrid's lock, unlock,
telescoping corrections and relock.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(app): keep the inline grid log inside the inline branch (no_threaded_limits)
The log line added a 53rd 'am I threaded?' check to app.cpp; it now sits in
the inline branch that already holds the grid update.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>