- Macrostep 00: Model contract and retained historical options. - Macrostep 01: Project foundation and configuration, including schema, presets, CLI, and CI setup. - Macrostep 02: Mathematical core implementation and deterministic oracles. - Macrostep 03: CPU-based planar simulation engine, FFT backend, and headless runner. Provides exhaustive objectives, phase breakdowns, validation policies, and deliverables for each macrostep.
5.7 KiB
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 00–06 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/incrementinspection;- 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
- Fill each layer with its index and verify every radial delay.
- Test boundaries around
distance=n±0.5. - Test head wrap
15→0. - Verify smooth base is
head-1. - Place one layer impulse and observe only the expected radial shell.
- Verify x/y wrapping at all edges/corners.
- Verify pause leaves head/state unchanged.
- Verify every reset initializes all layers.
- 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.
- Imported DT catalogue with named presets.
- 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.