--- id: PLN-0018 ticket: render-all-scene-cache-and-camera-integration title: Plan - SpriteController and Frame Emission Model status: accepted created: 2026-04-14 completed: tags: [gfx, runtime, render, sprites, frame-composer] --- ## Objective Replace the slot-first sprite model with a `FrameComposer`-owned `SpriteController` that emits sprites per frame instead of relying on `Sprite.active` and caller-provided indices. ## Background `DEC-0014` removes `Sprite.active` from the canonical operational model and locks sprite submission to a frame-emission model owned by `SpriteController`. ## Scope ### Included - Introduce `SpriteController`. - Remove the operational dependence on `Sprite.active`. - Remove caller-owned sprite indices from the canonical submission path. - Add layer + priority ordering with FIFO tie-breaking. - Preserve the capacity cap of `512` sprites per frame. ### Excluded - HUD integration - scene binding - cache refresh logic ## Execution Steps ### Step 1 - Redefine the sprite operational model **What:** Move canonical sprite submission semantics from slot-first to frame-emission. **How:** - Update `Sprite` and adjacent APIs so the canonical path no longer depends on `active`. - Keep layer numeric and aligned with the scene layer reference type. - Preserve `priority` as the within-layer ordering field. **File(s):** - `crates/console/prometeu-hal/src/sprite.rs` - any adjacent driver-side sprite helpers ### Step 2 - Implement `SpriteController` **What:** Create the owned sprite subsystem under `FrameComposer`. **How:** - Add a `SpriteController` type with: - storage capacity `512` - frame counter - per-layer buckets - stable FIFO semantics for equal priority - Add `begin_frame()` behavior that clears counters and buckets. - Add `emit_sprite(...)` behavior that appends to the next internal slot. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` - optional dedicated `sprite_controller.rs` ### Step 3 - Handle overflow and logging semantics **What:** Implement overflow behavior without turning it into a hard runtime failure. **How:** - Ignore sprites emitted after capacity is reached. - Leave explicit room for system logging / telemetry. - Do not add a special reset API beyond the normal frame lifecycle. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` - related telemetry/log hooks if needed ### Step 4 - Remove stale slot-first sprite entrypoints **What:** Retire the old “set sprite by explicit index” path from the canonical model. **How:** - Identify the current caller-facing `Gfx` sprite mutation surface. - Migrate it toward `FrameComposer`-owned submission. - Keep transitional shims only if required to preserve buildability for the next plan. **File(s):** - `crates/console/prometeu-drivers/src/gfx.rs` - `crates/console/prometeu-hal/src/gfx_bridge.rs` - `crates/console/prometeu-drivers/src/frame_composer.rs` ## Test Requirements ### Unit Tests - `begin_frame()` resets sprite count and buckets. - `emit_sprite(...)` appends without caller-provided index. - lower `priority` renders first within a layer. - equal `priority` resolves FIFO by registration order. - overflow drops excess sprites without panicking. ### Integration Tests - `FrameComposer` can emit sprites and provide ordered sprite state for rendering. ### Manual Verification - Confirm no canonical submission path requires `Sprite.active` or explicit slot index anymore. ## Acceptance Criteria - [ ] `SpriteController` exists under `FrameComposer`. - [ ] `Sprite.active` is no longer required by the canonical frame path. - [ ] Caller-provided sprite indices are retired from the canonical submission path. - [ ] Layer/priority/FIFO ordering is implemented and tested. - [ ] Overflow is ignored with space left for logging. ## Dependencies - Depends on `PLN-0017` - Source decision: `DEC-0014` ## Risks - Keeping compatibility shims too long can leave the codebase in a dual sprite model. - Removing index-based APIs too early may break callsites before `FrameComposer` integration is ready.