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

4.0 KiB

id ticket title status created completed tags
PLN-0018 render-all-scene-cache-and-camera-integration Plan - SpriteController and Frame Emission Model accepted 2026-04-14
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.