162 lines
5.0 KiB
Markdown
162 lines
5.0 KiB
Markdown
---
|
||
id: PLN-0013
|
||
ticket: scene-bank-and-viewport-cache-refactor
|
||
title: Plan - Scene Viewport Resolver and Rematerialization
|
||
status: accepted
|
||
created: 2026-04-13
|
||
completed:
|
||
tags: [gfx, tilemap, runtime, render]
|
||
---
|
||
|
||
## Objective
|
||
|
||
Implement `SceneViewportResolver` as the owner of master anchor, per-layer anchors, drift, hysteresis, clamp, cache update decisions, and per-layer copy instrumentation metadata.
|
||
|
||
## Background
|
||
|
||
`DEC-0013` makes the resolver the owner of movement policy between camera input and viewport cache updates. `PLN-0011` already fixed the canonical source as `SceneBank` and renamed per-layer movement metadata to `motion_factor`. This plan isolates the decision logic before final renderer migration.
|
||
|
||
## Scope
|
||
|
||
### Included
|
||
- Define `SceneViewportResolver`.
|
||
- Implement master anchor and per-layer derived anchors.
|
||
- Implement drift and hysteresis.
|
||
- Implement clamp behavior.
|
||
- Implement cache-update triggering and copy instrumentation metadata.
|
||
|
||
### Excluded
|
||
- actual framebuffer copy execution
|
||
- sprite/HUD/fade composition logic
|
||
- broad renderer migration
|
||
|
||
## Execution Steps
|
||
|
||
### Step 1 - Define resolver state and inputs
|
||
|
||
**What:**
|
||
Create the resolver state model and its public input surface.
|
||
|
||
**How:**
|
||
- Define resolver state to own:
|
||
- master anchor
|
||
- per-layer derived anchors
|
||
- viewport dimensions
|
||
- hysteresis thresholds
|
||
- clamp-relevant scene bounds
|
||
- Define the external entry point that accepts camera position input.
|
||
|
||
**File(s):**
|
||
- New resolver module(s), likely under HAL or drivers depending on final ownership
|
||
|
||
### Step 2 - Implement master-to-layer totem derivation
|
||
|
||
**What:**
|
||
Make layer motion derive from the master anchor using each layer’s `motion_factor`.
|
||
|
||
**How:**
|
||
- Compute per-layer effective motion from the master anchor.
|
||
- Preserve support for normal layers (`1.0`) and parallax/background-like layers (`!= 1.0`).
|
||
- Keep the derivation explicit and testable per axis.
|
||
|
||
**File(s):**
|
||
- Resolver module(s)
|
||
- Any math/helper module(s) needed for factor handling
|
||
|
||
### Step 3 - Implement drift, hysteresis, and clamp
|
||
|
||
**What:**
|
||
Translate camera motion into discrete anchor advancement safely.
|
||
|
||
**How:**
|
||
- Implement drift calculation in pixel space against anchor centers in tile space.
|
||
- Implement hysteresis with:
|
||
- internal safe band
|
||
- external trigger band
|
||
- Implement clamp against scene bounds.
|
||
- Ensure edge behavior is explicitly asymmetric when clamped.
|
||
|
||
**File(s):**
|
||
- Resolver module(s)
|
||
|
||
### Step 4 - Connect resolver decisions to cache update requests
|
||
|
||
**What:**
|
||
Turn resolver state changes into concrete cache update requests.
|
||
|
||
**How:**
|
||
- Emit requests for:
|
||
- line refresh
|
||
- column refresh
|
||
- area/region refresh for corner updates
|
||
- Ensure no duplicate work is scheduled for already-covered cache content.
|
||
- Keep the resolver in charge of “what to refresh,” not “how cache storage performs it.”
|
||
|
||
**File(s):**
|
||
- Resolver module(s)
|
||
- Shared request/command structs between resolver and cache
|
||
|
||
### Step 5 - Add copy instrumentation outputs for later renderer use
|
||
|
||
**What:**
|
||
Make the resolver capable of describing which cache slice/region should be copied for each layer.
|
||
|
||
**How:**
|
||
- Define a per-layer copy request/instrumentation type.
|
||
- Include enough information for a later compositor to copy from cache into `back` without re-deciding viewport math.
|
||
- Do not execute the copy here.
|
||
|
||
**File(s):**
|
||
- Resolver module(s)
|
||
- Shared copy-request types
|
||
|
||
### Step 6 - Add focused resolver tests
|
||
|
||
**What:**
|
||
Protect resolver correctness before renderer integration.
|
||
|
||
**How:**
|
||
- Add tests for:
|
||
- master anchor updates
|
||
- per-layer motion-factor derivation
|
||
- hysteresis stability
|
||
- repeated high-speed movement
|
||
- clamp at scene edges
|
||
- corner-trigger conversion into region refresh requests
|
||
|
||
**File(s):**
|
||
- Tests colocated with resolver modules
|
||
|
||
## Test Requirements
|
||
|
||
### Unit Tests
|
||
- Hysteresis prevents edge flick/thrash.
|
||
- Anchor movement occurs discretely in tile steps.
|
||
- Per-layer anchors follow the master according to `motion_factor`.
|
||
- Clamp behavior is correct near scene edges.
|
||
|
||
### Integration Tests
|
||
- Resolver outputs valid update requests consumable by `SceneViewportCache`.
|
||
|
||
### Manual Verification
|
||
- Instrument logs or debug traces to confirm no unnecessary refresh churn during back-and-forth movement near edges.
|
||
|
||
## Acceptance Criteria
|
||
|
||
- [ ] `SceneViewportResolver` exists with the full state required by `DEC-0013`.
|
||
- [ ] Master and per-layer anchors are derived correctly.
|
||
- [ ] Hysteresis and clamp are implemented and tested.
|
||
- [ ] Cache refresh requests are emitted by line, column, and region as required.
|
||
- [ ] Copy instrumentation metadata is available for later renderer use.
|
||
|
||
## Dependencies
|
||
|
||
- Depends on `PLN-0011` and `PLN-0012`.
|
||
- Source decision: `DEC-0013`
|
||
|
||
## Risks
|
||
|
||
- Resolver logic can become hard to reason about if movement, clamp, and copy instrumentation are not clearly separated.
|
||
- Parallax factor derivation can introduce subtle off-by-one or drift mismatch issues per layer.
|
||
- Region-update scheduling can duplicate work if X/Y corner movement is not normalized carefully.
|