Files
VoxelForge/WORK-NEXT.md
T
Fr0zkaandClaude Opus 5 58bdfb32de docs: WORK-NEXT.md -- the queue after Sol's read-only audit
Ordered by importance then size. Sol (read-only, xhigh) audited experimental @ aa62971
against main and delivered the two-sentence diagnosis this queue is built on:

  "The operator abstraction leaked into the innermost loop, and streaming treats
   'work submitted/applied' as 'safe to stand on.'"

Two corrections it made to us, both recorded in the doc:

- The fall-through is NOT a removed correctness barrier. main has no spawn gate
  either, marks tiles loaded before applying, and collides only LOD0. It was fast
  enough to hide the race. The owner's evidence was real; the inference was not.
- The loop inversion did not recover the 8x because it traded PER-SAMPLE
  short-circuiting (~70% of deep-solid samples skipped the cave suite) for per-block
  pruning. The fix is lowering the operator graph into a fused evaluator, not more
  dispatch removal.

It also found that RMC cooks collision ASYNCHRONOUSLY and we never record
cook-complete -- apply_s ends at submission, so nothing we have ever measured says
when physics could actually collide.

Reading Plugins/RealtimeMeshComponent is now permitted for item 1, READ ONLY, by the
owner's decision.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aheo2crrZmHuYtPpdY2Cb
2026-09-11 22:01:47 +02:00

5.8 KiB
Raw Blame History

WORK-NEXT — the queue after the read-only audit (2026-09-11)

Ordered by importance, then by size. Everything here comes from Sol's read-only audit of experimental @ aa62971, checked against main.

The audit's two-sentence verdict:

The operator abstraction leaked into the innermost loop, and streaming treats "work submitted/applied" as "safe to stand on."

Standing rules for every item: determinism is absolute (same build + same seed = same world on every machine); output may change between builds; nothing is deleted to go fast; capability before speed (player-fit 20,830 / walk-reachable 10,909 — do not drop below); scope is Plugins\VoxelForge only, no links, absolute -out= paths under the plugin's own Saved\.


1. Collision-ready before player-ready · CORRECTNESS · medium

The player falls through the world. There is no invariant that a tile you occupy has collision. main has no such barrier either — it was simply fast enough to hide the race.

  • apply_s ends at mesh submission. RMC cooks collision asynchronously and we never record cook-complete. We have never measured when physics can actually collide.
  • A tile enters LoadedTiles before its apply path completes (VoxelWorld.cpp:1532).
  • Only LOD0 carries collision (VoxelWorld.cpp:3109), so visible coarse terrain can exist while the collidable tile is still queued.

Do: record cook-complete; gate the pawn (spawn and movement) on the supporting tile being collidable, not merely applied.

📖 Reading Plugins/RealtimeMeshComponent is permitted for this item — READ ONLY. Find whether a cook-complete delegate/flag exists. ⛔ No edits, no builds against it: the owner's copy carries custom modifications and was destroyed once by an over-broad delete.

2. Lower the operator graph into a fused evaluator · PERFORMANCE · large

This is where the ~8× lives (pre-op-stack 34f06df did 128³ in 0.130 s; we are at ~1.04 s).

A LOD0 tile samples 42,875 positions. The old path short-circuited the whole cave suite per sample when bNearCaveSurface was false — roughly 70% of deep-solid samples. We now allocate a rich FVoxelOpSample per position, run each active operator across the entire block, use scalar fallbacks for most operators, copy scratch in and out, and still call scalar GetDensityAt per grid point.

An operator whose interval intersects the surface anywhere in the block runs across the whole block; the old path could decide per sample that expensive detail work was irrelevant.

Do: keep the authored operator graph, but compile/lower it into a fused evaluator that restores per-sample short-circuiting and stops spilling FVoxelOpSample through memory per operator. ⚠️ Byte-identical geometry is the acceptance test. Stage it so the tree never breaks.

Note: the D-floors/terracing features are only ~17% of the penalty — not the 8×.

3. Cancel obsolete work, and prioritise the floor · BOTH · medium

Nothing aborts a tile when the player moves and it stops being desired. Work is distance-sorted from an artificial chunk centre, not the pawn, with no collision-critical priority (VoxelWorld.cpp:1864). Up to 14 workers can be busy with stale coarse tiles while the player's LOD0 floor waits.

Do: abort no-longer-desired tiles; sort from the true pawn position; give the occupied tile and the next tile along the heading absolute priority.

4. Collapse the duplicated field semantics · MAINTENANCE · medium-large

The effective field now lives in three places: the operator stack, the classifier's parallel interval logic, and a post-stack repair tail in GetDensityAt (origin floors, passage structure, passage floors, room floors). FRoomGraphSource evaluates the room graph then traverses tunnels again for metadata (VoxelDensityOpStack.cpp:4234).

The audit calls this "the clearest sign of overengineering": later fixes compensating for where an operation sits in the pipeline. It also makes interval proofs harder to trust.

Do: make the stack the single semantic source of truth. Likely overlaps heavily with item 2.

5. Prove the verdict cache earns its place, or remove it · small

Zero outer hits in both traces. Global lock, linear scan, 512 entries, keyed on sample step so it barely reuses across LODs. It helped a deliberately repeated commandlet case, which is not how a moving player streams.

Do: measure nested/outer calls, hits and evictions on a real session. If it is neutral or negative, take it out and reclaim the memory.

6. Three small, sharp ones · tiny

  • The zero-position guard. Streaming only starts when GetPlayerPosition() is not exactly FVector::ZeroVector (VoxelWorld.cpp:1167, :1359) — a pawn at the world origin is indistinguishable from "no pawn", and the owner spawns at (0,0).
  • ApplyMeshToTile has no success return (VoxelWorld.cpp:3064). If runtime-mesh init fails the tile stays recorded as loaded and never retries — a permanent hole.
  • Whole-tile uniform verdicts are trusted without exact validation. Block verdicts get checked against the full grid when meshing; an outer AllAir/AllSolid verdict has no equivalent safety net.

7. Deferred, with reasons

  • Coarse-first LOD refinement — blocked until coarse tiles can carry collision, or item 1 lands.
  • GPU evaluation — right hardware, but bit-exactness across vendors/drivers is unproven and determinism is absolute. Item 2 is the honest prerequisite either way.
  • The origin spawn room — the owner considers it a design mistake that should not exist. Design conversation, not a fix.

Open design questions for the owner

  • All five strate slots resolve to DA_Strate3. Intended?
  • Should a composer roll be allowed to overwrite an explicitly authored value?