171 lines
8.8 KiB
Markdown
171 lines
8.8 KiB
Markdown
---
|
|
id: PLN-0036
|
|
ticket: perf-host-desktop-frame-pacing-and-presentation
|
|
title: Plan - Host Desktop Frame Pacing and Presentation
|
|
status: done
|
|
created: 2026-04-20
|
|
completed: 2026-04-20
|
|
tags: [perf, host, desktop, frame-pacing, presentation, debug]
|
|
---
|
|
|
|
## Briefing
|
|
|
|
Implement `DEC-0019` by removing unconditional desktop redraw polling, introducing a canonical host-side frame-publication trigger, preserving the last visible frame during paused or idle states, and updating the normative specs to reflect the locked contract.
|
|
|
|
## Decisions de Origem
|
|
|
|
- `DEC-0019` - Host Desktop Frame Pacing and Presentation
|
|
|
|
## Alvo
|
|
|
|
Deliver a host desktop execution path where:
|
|
|
|
- the winit loop no longer uses continuous polling by default;
|
|
- redraw happens only after logical frame publication or explicit host-owned invalidation events;
|
|
- RGB565 to RGBA8 conversion remains full-frame but only runs on demand;
|
|
- paused, debugger-waiting, and no-cartridge states keep the last valid image without continuous redraw;
|
|
- specs and tests match the accepted decision.
|
|
|
|
## Escopo
|
|
|
|
- Update the desktop host loop in `crates/host/prometeu-host-desktop-winit/src/runner.rs`.
|
|
- Introduce or stabilize a canonical "new frame published" signal at the runtime-host boundary.
|
|
- Track host-owned invalidation causes for overlay, debugger, and window events.
|
|
- Update the relevant runtime specs under `docs/specs/runtime/`.
|
|
- Add or extend automated tests for redraw gating and paused-state behavior.
|
|
|
|
## Fora de Escopo
|
|
|
|
- Dirty-region framebuffer conversion.
|
|
- GPU/shader-based presentation paths.
|
|
- New guest-visible ABI or debug surface.
|
|
- Redesign of overlay visuals or debugger protocol beyond invalidation signaling.
|
|
- Reopening the architecture covered by `DEC-0019`.
|
|
|
|
## Plano de Execucao
|
|
|
|
### Step 1 - Establish the canonical frame-publication trigger
|
|
|
|
**What:** Define the single host-consumable signal that indicates a new logical frame has been published.
|
|
|
|
**How:** Inspect the current buffer swap/publication point in the desktop runtime path and choose the existing internal publication event, dirty flag, or monotonic frame counter that can become the canonical trigger required by `DEC-0019`. If no stable signal exists, add a host-internal publication marker that changes exactly once per newly published logical frame and is not guest-visible.
|
|
|
|
**File(s):**
|
|
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
|
|
- any directly related runtime/firmware module discovered as the current frame-publication owner
|
|
|
|
**Depends on:** none
|
|
|
|
### Step 2 - Replace unconditional redraw requests with invalidation-driven scheduling
|
|
|
|
**What:** Remove the unconditional redraw call from the idle loop and gate presentation on frame publication or host-owned invalidation.
|
|
|
|
**How:** Refactor `about_to_wait()` and redraw scheduling in `runner.rs` so the host requests redraw only when:
|
|
|
|
- a new logical frame was published since the last presentation;
|
|
- the window receives a visible invalidation event such as resize/expose;
|
|
- overlay state toggles or changes a visible host-owned layer;
|
|
- debugger-visible state changes require host-side recomposition.
|
|
|
|
Introduce explicit host-owned invalidation state if needed so redraw causes are tracked instead of inferred by polling.
|
|
|
|
**File(s):**
|
|
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
|
|
|
|
**Depends on:** Step 1
|
|
|
|
### Step 3 - Move the event loop from default `Poll` to deadline/event waiting
|
|
|
|
**What:** Change the normal desktop control flow so the host waits for the next logical deadline or external event instead of spinning continuously.
|
|
|
|
**How:** Update `resumed()` and any related loop control code in `runner.rs` to stop using `ControlFlow::Poll` as the default. Use `WaitUntil` when a next logical tick deadline is known and `Wait` when the host is effectively idle with no immediate timing deadline. Keep any aggressive polling path behind an explicit profiling-only switch rather than as baseline behavior.
|
|
|
|
**File(s):**
|
|
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
|
|
- `crates/host/prometeu-host-desktop-winit/src/main.rs` if a profiling-only opt-in flag is wired at startup
|
|
|
|
**Depends on:** Step 2
|
|
|
|
### Step 4 - Preserve the last valid frame during paused, breakpoint, and no-cart states
|
|
|
|
**What:** Ensure non-running machine states do not cause repeated conversion/presentation work while still allowing host-owned UI recomposition when something visible changes.
|
|
|
|
**How:** Separate "machine produced a new frame" from "host-owned layer needs redraw". Keep the last presented RGBA output available for reuse, avoid logical buffer swaps during pause-only overlay activity, and ensure debugger waiting and no-cartridge states do not schedule continuous redraws. If overlay or debugger content changes while the machine is paused, redraw only the host-owned composition layer on explicit invalidation.
|
|
|
|
**File(s):**
|
|
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
|
|
- `crates/host/prometeu-host-desktop-winit/src/overlay.rs`
|
|
- `crates/host/prometeu-host-desktop-winit/src/debugger.rs`
|
|
|
|
**Depends on:** Step 2
|
|
|
|
### Step 5 - Update the normative specs
|
|
|
|
**What:** Propagate the accepted decision into the canonical runtime specs.
|
|
|
|
**How:** Update the portability and debug chapters so they explicitly state that desktop presentation observes published logical frames, that host-owned overlay/debug redraw is event-driven rather than continuously polled, and that stable host HUD state does not justify perpetual redraw. Keep the text aligned with the locked decision and do not introduce new architecture.
|
|
|
|
**File(s):**
|
|
- `docs/specs/runtime/10-debug-inspection-and-profiling.md`
|
|
- `docs/specs/runtime/11-portability-and-cross-platform-execution.md`
|
|
|
|
**Depends on:** Step 1
|
|
|
|
### Step 6 - Add regression tests and evidence
|
|
|
|
**What:** Add automated coverage for the redraw contract and document manual evidence where platform events are hard to model.
|
|
|
|
**How:** Extend or add tests in the desktop host crate to cover:
|
|
|
|
- no redraw request when no new frame and no host invalidation occurred;
|
|
- redraw request after a newly published logical frame;
|
|
- redraw request after overlay toggle or equivalent host-owned invalidation;
|
|
- no continuous redraw in paused/debugger-waiting/no-cart states;
|
|
- preservation of last visible frame semantics while paused.
|
|
|
|
Where direct winit event simulation is difficult, factor logic into testable state transitions and keep any remaining platform verification in a short manual checklist.
|
|
|
|
**File(s):**
|
|
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
|
|
- `crates/host/prometeu-host-desktop-winit/src/overlay.rs` if overlay invalidation helpers become testable
|
|
- `crates/host/prometeu-host-desktop-winit/src/debugger.rs` if debugger invalidation hooks are exposed
|
|
|
|
**Depends on:** Steps 2, 3, 4
|
|
|
|
## Criterios de Aceite
|
|
|
|
- The default desktop event loop no longer runs in continuous `ControlFlow::Poll`.
|
|
- The host requests redraw only after canonical frame publication or explicit host-owned invalidation.
|
|
- Full-frame RGB565 to RGBA8 conversion remains in place but is not executed continuously while the visible machine frame is unchanged.
|
|
- Paused, breakpoint, debugger-waiting, and no-cartridge states preserve the last valid image without continuous redraw.
|
|
- Overlay or debugger changes can still trigger targeted host-owned redraw when visually necessary.
|
|
- No guest-visible ABI is added for this feature.
|
|
- The relevant runtime specs state the same redraw and presentation contract as `DEC-0019`.
|
|
- Automated tests cover the main redraw gating paths and paused-state behavior.
|
|
|
|
## Tests / Validacao
|
|
|
|
### Unit Tests
|
|
|
|
- Add focused tests for redraw scheduling state transitions in the desktop host runner.
|
|
- Add tests for any helper that tracks frame-publication state or host-owned invalidation causes.
|
|
|
|
### Integration Tests
|
|
|
|
- Extend host crate tests to verify frame publication and debugger/overlay invalidation do not regress redraw policy.
|
|
- Run `cargo test -p prometeu-host-desktop-winit --lib`.
|
|
|
|
### Manual Verification
|
|
|
|
- Launch the desktop host with overlay disabled and confirm CPU usage drops when the machine is visually stable.
|
|
- Toggle overlay on and off and confirm redraw happens on the visible transition without restoring continuous polling.
|
|
- Pause execution or wait for debugger start and confirm the last frame remains visible without repeated redraw.
|
|
- Resize or expose the window and confirm the surface is recomposed correctly.
|
|
|
|
## Riscos
|
|
|
|
- The actual frame-publication point may be less explicit than assumed, requiring a small host-internal contract addition before redraw gating can be made reliable.
|
|
- winit waiting semantics can introduce timing regressions if the next logical deadline is computed incorrectly.
|
|
- Overlay or debugger code may currently assume redraw is always free, which can surface hidden invalidation bugs after polling is removed.
|
|
- Manual verification may still be needed for some window-system invalidation behavior that is cumbersome to model in tests.
|