From c78f091efefa34977ce8176bd871322ee193ba01 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 20 Apr 2026 09:54:24 +0100 Subject: [PATCH] [PERF] Host Desktop Frame Pacing and Presentation --- ...-and-host-invalidation-must-be-separate.md | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 discussion/lessons/DSC-0010-perf-host-desktop-frame-pacing-and-presentation/LSN-0036-frame-publication-and-host-invalidation-must-be-separate.md diff --git a/discussion/lessons/DSC-0010-perf-host-desktop-frame-pacing-and-presentation/LSN-0036-frame-publication-and-host-invalidation-must-be-separate.md b/discussion/lessons/DSC-0010-perf-host-desktop-frame-pacing-and-presentation/LSN-0036-frame-publication-and-host-invalidation-must-be-separate.md new file mode 100644 index 00000000..62d3bde9 --- /dev/null +++ b/discussion/lessons/DSC-0010-perf-host-desktop-frame-pacing-and-presentation/LSN-0036-frame-publication-and-host-invalidation-must-be-separate.md @@ -0,0 +1,62 @@ +--- +id: LSN-0036 +ticket: perf-host-desktop-frame-pacing-and-presentation +title: Frame Publication and Host Invalidation Must Be Separate +created: 2026-04-20 +tags: [performance, host, desktop, presentation, frame-pacing, debug] +--- + +# 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.