prometeu-runtime/discussion/workflow/plans/PLN-0018-sprite-controller-and-frame-emission-model.md

128 lines
4.0 KiB
Markdown

---
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.