All checks were successful
Intrepid/Prometeu/Runtime/pipeline/pr-master This commit looks good
57 lines
2.9 KiB
Markdown
57 lines
2.9 KiB
Markdown
---
|
|
id: LSN-0033
|
|
ticket: deferred-overlay-and-primitive-composition
|
|
title: Debug Primitives Should Be a Final Overlay, Not Part of Game Composition
|
|
created: 2026-04-18
|
|
tags: [gfx, runtime, render, frame-composer, overlay, primitives, hud, debug]
|
|
---
|
|
|
|
## Context
|
|
|
|
After `FrameComposer.render_frame()` became the canonical game-frame entrypoint, immediate `gfx.*` primitive writes were no longer stable. Scene-backed composition could rebuild the framebuffer after `draw_text(...)` or other debug primitives had already written to it.
|
|
|
|
`DSC-0028` resolved that conflict by moving `gfx.*` primitives into a deferred overlay/debug stage outside `FrameComposer`, drained only after canonical game composition and fades are complete.
|
|
|
|
## Key Decisions
|
|
|
|
### Debug Overlay Must Stay Outside the Canonical Game Pipeline
|
|
|
|
**What:**
|
|
`FrameComposer` keeps ownership of canonical game composition, while debug/text/primitive commands are captured separately and drained later as a final overlay.
|
|
|
|
**Why:**
|
|
Game composition and debug overlay have different purposes. The first must remain canonical and deterministic; the second must remain opportunistic, screen-space, and independent from scene or sprite semantics.
|
|
|
|
**Trade-offs:**
|
|
The renderer needs a second deferred path, but the game pipeline no longer depends on transient debug state.
|
|
|
|
### Final Visual Ordering Matters More Than Immediate Writes
|
|
|
|
**What:**
|
|
Overlay/debug commands are drained after scene composition, sprite composition, and fades, with parity between scene-bound and no-scene frame paths.
|
|
|
|
**Why:**
|
|
The stable user-visible contract is that debug primitives appear on top. Immediate writes were only an implementation detail, and they stopped preserving that contract once frame composition became deferred and canonical.
|
|
|
|
**Trade-offs:**
|
|
This changes primitive semantics from "write now" to "show at frame end," but it produces the behavior users actually rely on.
|
|
|
|
## Patterns and Algorithms
|
|
|
|
- Separate canonical composition state from debug-overlay state even when both reuse the same raster backend.
|
|
- Capture primitives as commands first, then drain them at the final stage where visual priority is unambiguous.
|
|
- Preserve the same overlay semantics whether a scene is bound or not.
|
|
- Keep implementation reuse internal while maintaining a clear semantic boundary in the public model.
|
|
|
|
## Pitfalls
|
|
|
|
- Treating debug primitives as part of HUD or scene composition will eventually couple tooling/debug behavior to gameplay pipeline rules.
|
|
- Draining overlay before fades or before final frame composition breaks the visible "always on top" contract.
|
|
- Reusing `FrameComposer` storage for overlay state collapses the ownership split that prevents these bugs.
|
|
|
|
## Takeaways
|
|
|
|
- Immediate framebuffer writes are not a reliable contract once final composition is orchestrated elsewhere.
|
|
- Debug primitives work best as a dedicated final overlay layer.
|
|
- Ownership separation is what keeps debug behavior stable while the canonical render pipeline evolves.
|