3.5 KiB
| id | ticket | title | created | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| LSN-0036 | perf-host-desktop-frame-pacing-and-presentation | Frame Publication and Host Invalidation Must Be Separate | 2026-04-20 |
|
Frame Publication and Host Invalidation Must Be Separate
Context
The desktop host was waking aggressively with ControlFlow::Poll, requesting redraw continuously, and converting the full RGB565 framebuffer to RGBA8 on every redraw even when the machine had not published a new logical frame.
That design hid real presentation cost, wasted CPU on stable screens, and blurred an important boundary: the runtime owns logical frame production, while the host owns window invalidation, overlays, and debugger presentation.
Key Decisions
Published logical frames are the canonical machine-side redraw trigger
What: The host presentation loop now treats "a new logical frame was published" as the primary reason to redraw the machine image.
Why: PROMETEU portability and timing depend on logical frames, not on a host polling loop. If the host redraws just to discover whether a frame changed, presentation cost stops reflecting actual machine behavior.
Trade-offs: This requires an explicit or at least stable host-side way to observe frame publication. The extra state tracking is worth it because it keeps redraw policy honest and testable.
Host-only invalidation is a separate redraw cause
What: Resize, expose, overlay toggle, and debugger-visible transitions remain valid redraw causes, but they are treated as host-owned invalidation rather than machine frame production.
Why: The host still has to repair or recomposite its visible surface when the OS window changes or a technical HUD becomes visible. That need is real, but it must not be confused with "the machine emitted another frame."
Trade-offs: The host needs separate invalidation bookkeeping. In return, paused or stable machine state no longer forces continuous framebuffer conversion.
Patterns and Algorithms
- Use two independent signals in presentation code:
- latest published logical frame;
- host-owned surface invalidation.
- Request redraw only when one of those signals changes and only once per pending update.
- After presentation completes, mark the current logical frame as presented and clear host invalidation.
- When the machine is running, wait until the next logical deadline instead of spinning continuously.
- When the machine is paused or waiting for debugger start, allow low-frequency host wakeups or OS events, but keep the last valid image until a real invalidation occurs.
Pitfalls
- Do not use redraw polling as a substitute for a missing publication signal. That only hides the architectural gap.
- Do not let host overlays imply extra logical frame production. Host HUDs may change the visible surface without changing machine state.
- Do not promote host-only invalidation into guest-visible ABI. The runtime-host handshake may need internal state, but the cartridge contract does not.
- Do not reopen render-backend architecture just to fix pacing. Dirty regions or GPU offload are separate optimization questions.
Takeaways
- A stable screen is a first-class state and should not cost continuous presentation work.
- Frame production and host invalidation are different events and should remain different in code.
- Event-driven redraw policy is easier to test, cheaper to run, and more faithful to the machine contract than polling-driven presentation.