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