research: Astra design review of the ~1 s whole-view goal (read-only)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
90378a585f
commit
2dfe599148
2 files changed
+270
No files matched your search
@@ -0,0 +1,133 @@
|
||||
# VoxelForge — design review: how do we get a cold whole view from ~2.5–4.6 s to ~1 s?
|
||||
|
||||
You're reviewing a voxel terrain generator's performance architecture. **Read and reason only.** Don't edit,
|
||||
build, run tests, commit or stash. You may read any file in this repository and search the web.
|
||||
|
||||
We've spent about 15 rounds finding and fixing hot spots, and the gains are shrinking. We want fresh eyes on the
|
||||
*approach*, not another micro-optimisation. Question our framing where it's wrong.
|
||||
|
||||
## The system (summary, so you don't have to rediscover it)
|
||||
|
||||
**VoxelForge** is a UE5 plugin for underground density-field terrain. Generation lives in a standalone C++
|
||||
library, "Core" (`Standalone/Core/`), that Unreal calls through an adapter
|
||||
(`Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp`).
|
||||
- **The field.** Density is a *function*, not stored data: negative = solid. Core voxels are 25 cm. Tiles hold
|
||||
32³ voxels.
|
||||
- **Clipmap.** LOD0–8; each LOD doubles the voxel step. A "whole view" is about 2,250–2,850 tiles across all LODs
|
||||
around one camera.
|
||||
- **Meshing.** Marching cubes per tile (about 35³ samples per LOD0/1 tile with borders), plus normals and skirts.
|
||||
- **The world is a vertical stack of "strates".** Each is ceiling → content → bedrock, with its own generator:
|
||||
- SurfaceWorld (SW): heightfield, native path;
|
||||
- FloatingIslands (FI), TunnelNetwork (TN) and VerticalShafts (VS): the "legacy compiled-analytic" path.
|
||||
- **The owner's test world** stacks four of them: SW 512 m, FI 240 m, TN 128 m, VS 128 m tall.
|
||||
- **Passages.** Walkable, winding, natural-looking tunnels near (0,0) connect each strate to the next. They're
|
||||
carved by a shared "composer" that also adds support treads, boundary bands and mouth shaping.
|
||||
- **Multiplayer.** No geometry is replicated. Every peer regenerates from the seed, the layout and a diff of
|
||||
player edits. That's why peer determinism is mandatory.
|
||||
|
||||
## The goal and constraints
|
||||
|
||||
- **Goal:** about 1 s cold whole view at any strate arrival on the owner's PC (Ryzen 5800X3D, 8 cores/16 threads,
|
||||
7900 XTX). Streaming must stay smooth in VR (Quest 3) and at high travel speed.
|
||||
- **Must hold:**
|
||||
- peer determinism (same inputs → same world on every machine);
|
||||
- no visible quality regression;
|
||||
- passages stay walkable from arrival mouth to departure mouth (capsule, support and grade audits exist);
|
||||
- no game-thread hitches.
|
||||
- **Not required:** byte-identical output with earlier versions. The owner accepts that perf passes change the
|
||||
world's shape slightly, as long as every peer gets the same result and quality holds. (We have tended to treat
|
||||
hash equality as a gate anyway; it's a convenience, not a rule.)
|
||||
- **On the shelf, not a speed excuse:** a disk mesh cache is an accepted feature, but perf is judged cold.
|
||||
|
||||
## Measurements (owner world, measured on an i9-12900H with 8 workers, headless unless stated)
|
||||
|
||||
**Whole view now** (it was 2.6 / 7.2 / 6.0 / 2.7 s a week ago):
|
||||
|
||||
| Strate | Whole view |
|
||||
|---|---:|
|
||||
| SW | 2.4 s |
|
||||
| FI | 4.6 s |
|
||||
| TN | 4.3 s |
|
||||
| VS | 2.5 s |
|
||||
|
||||
**In Unreal (SW arrival):**
|
||||
- Core work equals headless;
|
||||
- initial set ready at 3.74 s vs headless 2.41 s, the extra being scheduling;
|
||||
- walkable ring 0.4–1.8 s.
|
||||
|
||||
**Where the time goes:**
|
||||
- **L73:** field evaluation inside grid fill is about 40 of FI's 46 worker-seconds (TN 33 of 39). LOD0/1 tiles
|
||||
evaluate about 44k density samples each.
|
||||
- **L74/L75:** sound whole-tile skip proofs now certify about 22–26% of tile visits.
|
||||
- Ceiling: 46–82% of LOD0–2 tiles are truly uniform, and 90–97% of samples lie in uniform 8³ blocks.
|
||||
- Dominant remaining veto: tiles crossing a strate boundary.
|
||||
- Legacy sub-tile (block) proofs were unsound once (missed passage wall/floor relief), then sound but slower
|
||||
than they saved.
|
||||
- **L76, per legacy sample:**
|
||||
- passage/support composer ≈ **1.05 µs**;
|
||||
- primitive scan ≈ 0.19 µs (0.25 primitive distance evaluations per sample, binned);
|
||||
- boundary band ≈ 0.06 µs;
|
||||
- noise ≈ 0.01 µs.
|
||||
|
||||
**About 75% of field time is the passage composer, even far from passages.**
|
||||
- Per-tile passage culling was tried and changed 612 density samples / 24 mesh tiles. It was rejected only for
|
||||
breaking hash equality, which is a convenience, not a rule; nobody checked whether that change was harmless.
|
||||
|
||||
**Tried and rejected:**
|
||||
- the native FI generator (fails passage walk audits on this plan);
|
||||
- deeper Unreal queues (done: 4.78 → 3.74 s).
|
||||
|
||||
**Trap we fell into once:** a diagnostic hash mode silently disabled the skips and doubled the timings. Measure the
|
||||
production path.
|
||||
|
||||
## What to reason about (open; don't limit yourself to these)
|
||||
|
||||
1. **Is "evaluate a density function at ~44k points per tile, then march cubes" the right shape** for this world?
|
||||
Consider, for example:
|
||||
- sparse/hierarchical evaluation (octree or brick refinement driven by interval or Lipschitz bounds, as in
|
||||
libfive/Fidget/MPR-style implicit rendering);
|
||||
- reusing samples across nested clipmap LODs;
|
||||
- evaluating smooth large-scale terms coarsely and interpolating;
|
||||
- narrow-band evaluation near the surface only.
|
||||
2. **The passages are a few winding tubes.** Why does every sample pay 1 µs for them? What representation would
|
||||
make "far from any passage" free and "near a passage" cheap? For example:
|
||||
- bake each passage once at plan time into a sparse distance/brick structure;
|
||||
- a spatial index of segments with a conservative distance early-out;
|
||||
- a per-tile passage candidate list built once.
|
||||
|
||||
What would a correct per-tile culling need so that it doesn't change the result? And if it changes the result,
|
||||
how should we judge whether that change is acceptable?
|
||||
3. **Which work is needed for "ready in 1 s"?** Maybe the target should be redefined: walkable ring first,
|
||||
progressive LOD refinement, far LODs from cheaper representations or impostors, fewer tiles. What do comparable
|
||||
engines do (Voxel Plugin, Teardown, Dreams, No Man's Sky, Minecraft-style streaming, Nanite-era voxel work)?
|
||||
4. **Hardware.** 8 CPU cores plus a 7900 XTX that's mostly idle during load. An earlier GPU port was closed, and
|
||||
determinism across GPU vendors is a concern. Is there a deterministic way to use it, e.g. integer/fixed-point
|
||||
evaluation or a CPU-authoritative plus GPU-display split? Is SIMD (AVX2) evaluation of the legacy field
|
||||
realistic?
|
||||
5. **Anything in our process or measurement** that hides the real bottleneck.
|
||||
|
||||
## How to work efficiently
|
||||
|
||||
- **Trust the numbers above; don't re-measure or re-derive them.** Spend your effort on thinking.
|
||||
- **Read code only to check whether a specific idea fits.** Entry points:
|
||||
- `CODEMAP.md` (navigation) and `ARCHITECTURE.md` §8.10 (performance invariants);
|
||||
- `Standalone/Core/src/ShapeWorldInternal.h`: composer, `AnalyticDensityAt`, `ClassifyBoxDetailed`, passage
|
||||
terms;
|
||||
- `Standalone/Core/src/VoxelForgeCore.cpp`: tile generation and skips;
|
||||
- reports in `Standalone/Research/WorldAssemblerM3/`: `Linux73`–`Linux76`, `Research36`, and R38–R40 notes
|
||||
inside `Linux73/` and `Linux76/`.
|
||||
- **Use the web** for prior art and techniques, and cite them.
|
||||
- **Go broad first** (many approaches, one or two lines each), then deep on the best three.
|
||||
|
||||
## Output
|
||||
|
||||
At most ~2,500 words, plain language, **ranked recommendations first**. For each of the top three:
|
||||
- what changes, and where in this codebase (file and function);
|
||||
- expected gain, with arithmetic from the numbers above;
|
||||
- what it risks: determinism, quality, walkability;
|
||||
- effort;
|
||||
- **a cheap experiment that would prove it wrong** before anyone builds it fully.
|
||||
|
||||
Then the shorter list of other ideas, then any questions only the owner can answer (e.g. what "ready" must mean).
|
||||
Mark claims as [CODE] (read in this repo), [MEASURED] (from the numbers above), [PRIOR ART] (cited) or
|
||||
[INFERENCE].
|
||||
Reference in new issue
Block a user