A default-QoS pthread is scheduled onto efficiency cores when the host is
busy, which put the render thread, now on every frame's critical path,
behind the emulation thread it is supposed to relieve.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One frame behind is the normal pipelined state when the render thread is
the slower side; skipping on it dropped nearly every present at 4K
widescreen. rt_frames_ahead() counts the complete frames queued after
the one being replayed; the backend skips only at two, where the
emulation thread is at the in-flight bound waiting on the render thread.
The unit test checks the count never exceeds the bound and that both
cases occur under a slow consumer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Backend-neutral core for the opt-in [video] render_thread: the emulation
thread appends records to a single-producer/single-consumer ring and the
render thread replays them in order with the graphics context current.
rt_frame_end bounds closed frames in flight (backpressure), the render
thread can tell a frame is stale, and rt_acquire is the sync point:
drain, then move the context to the emulation thread until rt_release.
No lock is held while a record executes.
render_thread_test drives it with a fake executor and context token:
ordering and payload integrity across ring wraps, oversize refusal, the
in-flight bound under a slow consumer, stale detection, randomized
acquire/release interleaving and stop while held (TSan clean).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>