Files
smoothlife/plans/09_delayed_time_backend.md

5.7 KiB
Raw Blame History

Macrostep 09 — Delayed-time backend

Objective

Implement the distance-dependent delayed-time experiment as a deterministic, configurable 2-D backend with explicit history indexing, CPU oracle, accelerated GPU path, history diagnostics, and decoupled simulation/window resolution.

Dependencies

Macrosteps 0006 complete; follow the roadmap order after Macrostep 08.

Phase 9.1 — Explicit history model

Substep 9.1.1 — Storage and indexing

Represent history as depth × height × width with default depth 16 and a circular head denoting the next layer to overwrite. Define helpers:

latest = wrap(head-1, depth)
sample(distance) = wrap(latest-floor(distance+0.5), depth)

Tests, UI, and shader must use the same integer helpers. Spatial x/y addressing is periodic. Window resize never changes simulation resolution by default.

Substep 9.1.2 — Causal policy

Use one policy only: delay zero reads latest, and increasing rounded distance walks backward from it. Smooth dynamics also use latest as their base. The historical next-overwrite-head anomaly is discarded and is not configurable.

Use explicit integer layer selection; do not blur time through normalized 3-D texture interpolation.

Phase 9.2 — Delayed neighborhood oracle

Substep 9.2.1 — Stencil

Implement:

ri = ra/3
inner width = outer width = 1
search radius = ceil(ra+0.5)

For each spatial offset, precompute:

  • (dx,dy);
  • Euclidean distance;
  • integer delay layer offset;
  • disk and ring weights.

Normalize by numerically summing this exact discrete stencil, not analytic area.

Substep 9.2.2 — CPU evaluation

For each output point, wrap x/y, choose the causal history layer, accumulate M/N, evaluate the shared rule, then:

discrete: next = clamp(S)
smooth:   next = clamp(history[latest] + 0.1*(2S-1))

Commit next into history[head], then advance head. Separate preview() from commit() so pause semantics are explicit.

Substep 9.2.3 — Pause and reset

Pause freezes output and head. Reset initializes every layer; recompute-without-commit and stale/undefined storage are not supported.

Phase 9.3 — Initialization and interaction

Provide deterministic modes:

  • all layers zero;
  • one seeded frame replicated to all layers;
  • independently seeded layers;
  • populate one layer as an explicit analysis operation;
  • source-inspired seeded boxes applied through a documented all-layer policy;
  • import a restart state under an explicit layer-fill policy;
  • import/export an exact checkpoint containing all history layers, head, generation, run descriptor, and RNG state.

The seeded box initializer uses width/height in 10..19 and one documented boundary policy, then initializes all layers explicitly. Keep reset and later overlay actions distinct; do not retain gradual history filling.

Phase 9.4 — GPU history representation

Substep 9.4.1 — Choose after capability spike

Preferred portable path is a tiled 2-D history atlas (default 4×4) plus separate output/current targets. A texture array is an optional optimized path behind the same tested index abstraction.

Atlas requirements:

  • integer tile/texel fetch;
  • no interpolation bleed;
  • dimensions preflighted against maximum texture size;
  • clear ownership of padding;
  • distinct read and write targets.

Substep 9.4.2 — Rule pass and commit

Run the direct stencil pass using precomputed offsets/weights/delays (uniform buffer, lookup texture, or generated shader according to measured limits). Copy/blit output into the head tile only after all reads complete, then rotate the logical head. Never sample the atlas tile while writing it.

Substep 9.4.3 — CPU/GPU parity

Read back M, N, output, and selected history tiles for small tests. Initial one-step max-error target: ≤1e-3.

Phase 9.5 — Workbench integration

Add:

  • current committed state and computed preview;
  • history timeline with selectable layer, age, and physical tile;
  • radial delay map showing which distance uses which age;
  • M/N/S/increment inspection;
  • head/latest indicators;
  • history initialization controls;
  • direct/smooth mode selector;
  • DT preset browser and model-resolution controls independent of window size.

Parameter edits state whether they preserve or reinitialize history. Rule-only edits may preserve state but must produce a reproducible run descriptor; radius or depth changes are cold rebuilds.

Phase 9.6 — Verification

History tests

  1. Fill each layer with its index and verify every radial delay.
  2. Test boundaries around distance=n±0.5.
  3. Test head wrap 15→0.
  4. Verify smooth base is head-1.
  5. Place one layer impulse and observe only the expected radial shell.
  6. Verify x/y wrapping at all edges/corners.
  7. Verify pause leaves head/state unchanged.
  8. Verify every reset initializes all layers.
  9. Verify atlas and CPU layouts select identical values.

Performance target

At 512² and ra≈12, target p95 GPU step below 33 ms on the designated machine after offset/weight/delay precomputation. Keep CPU for correctness and reduced-resolution fallback. High-resolution cost limits must be visible before allocation.

Deliverables

  • CPU delayed-history oracle and GPU backend.
  • One explicit causal indexing policy.
  • Newly authored deterministic DT presets with stable names and identities.
  • History/radial-delay workbench views, restart-state export, and exact continuation checkpoints.

Exit gate

  • All layer, radial shell, wrap, pause, and reset tests pass.
  • CPU/GPU one-step tolerance passes.
  • Window resize does not reset history.
  • No atlas bleed, uninitialized layer, or read/write alias exists.
  • Every DT preset uses the causal latest-relative delay policy and is reproducible.