Direct per-tile trace on the BuildHost actor (owner plan, 2,578 keys): full set 17.4 s legacy; gated coarse-first (after the 9-tile walkable ring) 11.7 s with the ring still at 0.63 s, but full LOD0 slips 2.3 -> 10.2 s. Startup apply boost changed nothing (0.4%). 37.6 worker-s over 17.4 s on 10 slots = ~3.3 busy: the floor is admission/work supply. S5's 251 ms staircase was the trace sampler. Fixed CVar parsing in headless BeginPlay and the 60 m/s crossing instrument. All three knobs stay opt-in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
219 lines
15 KiB
Markdown
219 lines
15 KiB
Markdown
# World assembler S6 / M3 Round 10 — in-game cold-view time
|
||
|
||
**Result:** the 251 ms staircase was trace sampling cadence, not a scheduler tick. On the staged
|
||
2,578-key SurfaceWorld actor, the default legacy path reached full residency in 17.412 s. Gated
|
||
coarse-first admission reached it in 11.704 s while the walkable ring time stayed at 0.627 s versus
|
||
0.632 s. A 12-mesh / 14 ms startup apply budget did not improve the legacy timeline. The remaining
|
||
floor is on worker-side work supply/admission, not the game-thread apply budget; the trace does not
|
||
isolate why available worker slots stay idle. The 1.57 s aim remains unmet.
|
||
This is null-RHI residency evidence, not rendered enclosure proof.
|
||
|
||
## 1. Cadence and comparison with S5
|
||
|
||
`AVoxelWorld::UpdateChunksAroundPosition` emits `streaming_sample` only when at least 0.25 s has
|
||
elapsed since its previous sample. S5’s near-251 ms per-LOD staircase was quantized by that observer;
|
||
it was not a one-LOD-per-tick scheduler throttle. S6 records direct tile-result/apply timestamps and
|
||
per-frame `ProcessPendingChunks` samples, so the completion table below does not depend on that
|
||
sampler.
|
||
|
||
S5 reported 3.352–6.367 s for its per-LOD residency samples. The Round 9 report did not retain the
|
||
exact BuildHost command line, executable hash, or raw direct-tile trace for that run. S6 uses the
|
||
same staged `DA_Settings` SurfaceWorld plan, 25 cm Core scale, 2,578 desired keys, 12-task host setup,
|
||
and legacy-order controls, but its direct full-set result is 17.412 s. The 250 ms sampling interval
|
||
cannot explain this larger difference. Treat S5’s 3.35–6.37 s values as a different/unidentified
|
||
measurement route, not a matched baseline; S6 preserves the direct command lines and hashes below.
|
||
The Standalone 3.58–3.64 s S5 measurement was CPU-only over 2,553 keys, so it is also not a matched
|
||
BuildHost apply/collision measurement.
|
||
|
||
## 2. Matched BuildHost actor runs
|
||
|
||
Fresh sequential processes used the staged owner plan, `CoreVoxelSizeCm=25`, 2,578 desired tiles,
|
||
`-corelimit=12` (10 active task slots in the actor trace), null RHI, a manually ticked `UWorld` with
|
||
a 16 ms step, and a +Y 600 cm/s move beginning at 30 s. There was no overlapping Unreal process or
|
||
build. Full-set time is the actor’s initial desired-set milestone. “LOD0 full” means all 512 visual
|
||
LOD0 keys, separate from the 9/9 collision walkable gate.
|
||
|
||
| Configuration | Full set ready | Walkable ring 9/9 | Full 512-key LOD0 | Count-cap frames / backlog frames | Visible meshes/frame p95/max | Apply CPU p95/max | `UWorld::Tick` spawn p95/max | `UWorld::Tick` walk p95/max |
|
||
|---|---:|---:|---:|---:|---:|---:|---:|---:|
|
||
| Legacy order, authored 4 / 2 ms budget | 17.412 s | 0.632 s | 2.252 s | 78 / 22 | 4 / 4 | 0.77 / 1.62 ms | 1.406 / 5.059 ms | 1.771 / 29.247 ms |
|
||
| Legacy order, startup boost on (12 / 14 ms) | 17.346 s | 0.611 s | 2.190 s | 0 / 0 | 4 / 6 | 0.70 / 1.49 ms | 1.301 / 5.429 ms | 1.798 / 28.489 ms |
|
||
| Coarse-first after ring gate, authored 4 / 2 ms | **11.704 s** | **0.627 s** | 10.201 s | 118 / 48 | 4 / 4 | 0.82 / 1.44 ms | 1.396 / 5.027 ms | 1.911 / 28.276 ms |
|
||
|
||
Coarse-first shortened the full desired-set tail by 5.708 s (32.8%) without a walkable-gate
|
||
regression. It did not make all near detail ready sooner: full LOD0 moved from 2.252 s to 10.201 s.
|
||
The option therefore stays opt-in pending a rendered view/enclosure check. The apply boost removed
|
||
cap frames but changed full-set time by only 66 ms (0.4%), so it also stays opt-in. Normal play
|
||
continues to use the authored 4 visible-mesh / 2 ms limit. These are `UWorld::Tick` CPU samples in a
|
||
manual null-RHI harness, not full rendered frame times. Walk p95 stayed below 2 ms, but the observed
|
||
~28–29 ms maxima remain and were not isolated to a single subsystem. Per-frame apply maxima were
|
||
1.62 ms legacy and 1.44 ms gated coarse-first.
|
||
|
||
### Per-LOD cold set
|
||
|
||
Each pair is **legacy → gated coarse-first**, from direct tile completion events up to the initial
|
||
desired-set milestone. Queue values are cumulative tile-seconds, not elapsed wall seconds. The
|
||
initial set contains 2,578 tile results; empty results are included in the result count and apply
|
||
time.
|
||
|
||
| LOD | Last tile apply (s) | Worker task (s) | Worker queue (tile-s) | Result queue (tile-s) | GT apply (ms) / results |
|
||
|---:|---:|---:|---:|---:|---:|
|
||
| 0 | 2.252 → 10.201 | 3.39 → 3.39 | 0.028 → 0.033 | 5.94 → 5.87 | 27.9 → 35.0 / 512 |
|
||
| 1 | 4.785 → 11.765 | 3.21 → 3.05 | 0.007 → 0.006 | 4.43 → 4.79 | 17.0 → 20.4 / 448 |
|
||
| 2 | 6.609 → 8.567 | 0.70 → 0.71 | 0.012 → 0.006 | 4.77 → 4.90 | 10.9 → 13.0 / 320 |
|
||
| 3 | 8.162 → 7.460 | 1.81 → 1.78 | 0.005 → 0.005 | 2.86 → 3.07 | 10.5 → 11.8 / 272 |
|
||
| 4 | 10.317 → 6.530 | 6.02 → 6.08 | 0.004 → 0.006 | 2.16 → 2.62 | 26.5 → 24.9 / 272 |
|
||
| 5 | 11.494 → 5.182 | 1.42 → 1.42 | 0.003 → 0.003 | 2.20 → 2.40 | 18.4 → 15.9 / 208 |
|
||
| 6 | 12.483 → 4.438 | 1.85 → 1.90 | 0.002 → 0.002 | 1.58 → 1.65 | 15.2 → 12.8 / 144 |
|
||
| 7 | 13.198 → 3.852 | 1.74 → 1.75 | 0.001 → 0.001 | 0.88 → 1.02 | 16.7 → 13.5 / 96 |
|
||
| 8 | 17.476 → 3.432 | 17.50 → 19.29 | 0.005 → 0.465 | 2.59 → 2.62 | 95.0 → 87.0 / 306 |
|
||
|
||
Per-frame visible mesh counts and the largest per-LOD apply sample were:
|
||
|
||
| LOD | Visible meshes/frame p95/max, legacy → coarse | Max LOD apply/frame, legacy → coarse |
|
||
|---:|---:|---:|
|
||
| 0 | 2 / 4 → 3 / 4 | 0.762 → 0.934 ms |
|
||
| 1 | 1 / 4 → 1 / 4 | 0.630 → 0.809 ms |
|
||
| 2 | 0 / 4 → 1 / 4 | 0.533 → 0.639 ms |
|
||
| 3 | 0 / 4 → 1 / 4 | 0.515 → 0.570 ms |
|
||
| 4 | 2 / 4 → 3 / 4 | 0.605 → 1.354 ms |
|
||
| 5 | 1 / 3 → 2 / 4 | 1.272 → 0.742 ms |
|
||
| 6 | 0 / 4 → 1 / 4 | 0.687 → 0.708 ms |
|
||
| 7 | 0 / 4 → 0 / 4 | 0.974 → 0.732 ms |
|
||
| 8 | 2 / 4 → 3 / 4 | 1.625 → 1.439 ms |
|
||
|
||
The 10-task-slot slack estimate was 132.1 slot-seconds on legacy order and 73.3 on coarse-first,
|
||
computed as ten slots × (first request to full-set ready) minus measured worker-task seconds. The
|
||
shared pool averaged 3.27 / 4.21 running workers on frames with estimated pending results; one
|
||
legacy backlog frame had no running worker, versus none in the coarse-first run. Idle worker time
|
||
and apply-cap frames are shared-pool/world properties, so a per-LOD split would double-count them.
|
||
Legacy used 37.64 worker-seconds and coarse-first 39.36; pre-start worker-queue wait was only
|
||
0.067 / 0.527 tile-seconds. Result-queue wait summed to 27.41 / 28.94 tile-seconds. Game-thread
|
||
tile-apply time was about 0.24 / 0.23 seconds for the cold set. The boost run had no apply-cap or
|
||
result-backlog frames and still took 17.346 s. Thus the apply cap is not the end-to-end floor. The
|
||
remaining floor is worker-side work supply/admission; the trace does not isolate why available
|
||
worker slots stay idle or identify a safe single worker-side change for this round.
|
||
|
||
Collision is currently required only on the LOD0 path. The trace captured 60 body-update events in
|
||
each cold run; 60 of 125 collision-desired entries were ready by the full-set milestone, while
|
||
non-required/empty entries were classified separately. RealtimeMesh submit-to-body-update latency
|
||
(not isolated Chaos CPU cooking) was legacy p50/p95/max 17.02 / 17.89 / 18.04 ms, boost 16.80 /
|
||
17.51 / 17.70 ms, and coarse-first 17.08 / 18.01 / 18.30 ms. The nine required ring tiles were ready
|
||
at the gate times above. LOD1–8 had no collision-ready events in this trace.
|
||
|
||
## 3. Shared change and standalone crossing instrument
|
||
|
||
`voxel.StreamingCoarseFirst=1` now starts far-level admissions only after all nine required
|
||
walkable-ring collision gates are ready. `voxel.StreamingDynamicNearReserve=1` keeps the authored
|
||
near reserve while moving or before that gate; after a stationary gate it lets coarse work use the
|
||
reserved slots. Both are explicit, default-off controls. `voxel.StreamingStartupApplyBoost=1` allows
|
||
12 visible-mesh applies / 14 ms during the initial desired-set and walkable-ring phase, with a 30 s
|
||
ceiling; zero keeps the authored budget. It is not preemptive within one apply, so it remains opt-in.
|
||
This behavior is in shared `AVoxelWorld::UpdateChunksAroundPosition` / `ProcessPendingChunks` and
|
||
does not change density, tile output, or collision policy.
|
||
|
||
The standalone 60 m/s flight instrument now counts forward +Y chunk crossings using the actual
|
||
center delta, including multi-chunk jumps. The valid viewer route completed 250/250 center samples,
|
||
with 226 center updates and max forward delta +2. It reports `crossing_deltas=forward-+Y`,
|
||
resident 2,553/2,553 and no missing tiles. Latency still **fails**: nearest-ready p50/p95/max was
|
||
9.087 / 20.594 / 128.785 ms and maximum crossing wall time 42.931 s. The earlier
|
||
`--stream-benchmark` and `--stream-pipeline` invocations emitted no Flight markers; only the viewer
|
||
route is used for this result.
|
||
|
||
## 4. Hashes, regression checks and async audit
|
||
|
||
Standalone W1/W8/W16 fresh processes produced identical full-world and all nine per-LOD hashes;
|
||
all match S5. Full world identity: density `c10697a8f48380c7`, mesh `430d2be2bdd8b988`, payload
|
||
`b7b33e14092225c9`, topology `c5c46d66606a819e`.
|
||
|
||
- Core-off legacy at 12.5 cm: **PASS**, `VOXELFORGE_CORE_OFF_LEGACY_PASS`.
|
||
- M2 V1 and V2: **PASS**, five fixtures plus same-LOD border for each.
|
||
- SurfaceWorld and FloatingIslands BuildHost at 25 cm: **PASS**. FloatingIslands W1/W8/W16
|
||
matched Standalone; the final Standalone W1/W8/W16 matrix also matched across all nine LODs and S5.
|
||
- S4 cap census/agreement and ray coverage: **PASS**; 551 requested/emitted cap bands, 1,584/1,584
|
||
coverage rays, 128-point cap agreement max 0.0504 cm against 2 cm tolerance, negative control
|
||
detected.
|
||
- S3 ground and S4 LOD7/8 ground agreement: **PASS**; max ground delta 0.0427 cm, cross-LOD 0.0 cm,
|
||
and the negative control was detected.
|
||
- Water remains fixed for the season; player carve/fill stays unrestricted.
|
||
|
||
Diff audit: `GenerationEpoch` is carried and stale epochs are rejected; the four result queues remain
|
||
`EQueueMode::Mpsc`; `EndPlay` sets shutdown, waits for active work and drains the queues; workers
|
||
check `bShuttingDown`; `ModsLock` behavior is unchanged; all UObject/RealtimeMesh component creation
|
||
and mutation stays on the game thread. No density-sign or determinism path changed. The added C++
|
||
comments are French and English. No generated header, `Binaries/`, or `Intermediate/` source edits.
|
||
|
||
## 5. Exact commands, binaries and run ledger
|
||
|
||
BuildHost actor runs used `E:\Program Files\Epic Games\UE_5.7\Engine\Binaries\Win64\UnrealEditor-Cmd.exe`
|
||
with `-nullrhi -unattended -corelimit=12 -run=VoxelForgeExplore -seed=0 -archetype=TunnelNetwork
|
||
-coreworldtest=1 -corevoxelsizecm=25 -settingsref=/Game/VoxelForge/DA_Settings.DA_Settings
|
||
-coreworldstreamtrace=1 -voxel.TestMove=1 -voxel.TestMoveSpeedCmPerSecond=600
|
||
-voxel.TestMoveStartSeconds=30 -voxel.TestMoveDirection=0,1,0
|
||
-voxel.StartupTraceUntilEndPlay=1 -voxel.CollisionGate=0`. The exact expanded `LogInit: Command Line:`
|
||
including project, DDC, trace and output paths is preserved verbatim in each [legacy run](../../../../Saved/BuildHost/HostProject/Plugins/VoxelForge/Saved/CoreWorldValidation/Logs/CoreWorldValidation-owner_surface_stream_trace_only_applyboost_0_legacy_order_trace.stdout.log),
|
||
[boost run](../../../../Saved/BuildHost/HostProject/Plugins/VoxelForge/Saved/CoreWorldValidation/Logs/CoreWorldValidation-owner_surface_stream_trace_only_applyboost_1_legacy_order_trace.stdout.log),
|
||
and [gated coarse run](../../../../Saved/BuildHost/HostProject/Plugins/VoxelForge/Saved/CoreWorldValidation/Logs/CoreWorldValidation-owner_surface_stream_trace_only_applyboost_0_coarse_first_trace.stdout.log).
|
||
Their CVar overrides were respectively:
|
||
|
||
| Run | `StreamingCoarseFirst` | `StreamingDynamicNearReserve` | `StreamingStartupApplyBoost` |
|
||
|---|---:|---:|---:|
|
||
| Legacy negative control | 0 | 0 | 0 |
|
||
| Apply-budget A/B | 0 | 0 | 1 |
|
||
| Gated coarse-first | 1 | 1 | 0 |
|
||
|
||
Standalone 60 m/s exact command (also in [commands.txt](../../../../Saved/BuildHost/S6/standalone/commands.txt)):
|
||
|
||
```text
|
||
Standalone\bin\VoxelForgeCoreStandalone.exe --world-assembler-prototype --force-generate --workers=12 --clip-radius=3 --max-clip-level=8 --camera=0,-35,-487.94,0,-22 --test-flight-crossings=250 --flight-speed-mps=60 --process-priority=Normal --process-affinity=4095 --frame-limit=60
|
||
```
|
||
|
||
| Executable / module | SHA-256 |
|
||
|---|---|
|
||
| BuildHost `UnrealEditor-Cmd.exe` | `ECCE9996191F7F7E69B3D104EECDD0E678AE69176FDCCD79828C3E75A0654D6D` |
|
||
| BuildHost `UnrealEditor-VoxelForge.dll` | `1C083446ED360FBD798EAE4C4D3CA9E5994E906770B5017A51418BFEF46C30FA` |
|
||
| BuildHost `UnrealEditor-VoxelForgeCore.dll` | `54259552340FE81EA05640C622E9E5E5C0AC68C95F87DC718326D25EF133B2AC` |
|
||
| Standalone `VoxelForgeCoreStandalone.exe` | `1F445760AFDE264E2F28F8F2FB4CB68DBD0C8988AACD5A493B065E74C1827529` |
|
||
|
||
BuildHost UBT passed twice at 12 actions / Normal priority. `& .\Standalone\Build.ps1 -Target All
|
||
-CompileWorkers 12 -BuildPriority Normal` passed. Existing vswhere/C4838 warnings did not fail the
|
||
Standalone build. The S6 hash and 60 m/s logs are in [Saved/BuildHost/S6/standalone](../../../../Saved/BuildHost/S6/standalone/).
|
||
|
||
Failed/retried attempts, including setup failures:
|
||
|
||
- An earlier full actor attempt reached its 600 s timeout in the Standalone-reference preamble; it
|
||
left a partial trace. A first trace-only command omitted its required startup-trace output path
|
||
and exited before the actor run; the helper now makes `StreamingTraceOnly` imply trace output.
|
||
- Two fresh-shell memory preflights lacked the local `Add-Type` helper and stopped before launching
|
||
Unreal. The corrected `GlobalMemoryStatusEx` preflight ran before later launches.
|
||
- Early coarse-first attempts did not parse the requested CVar in headless `BeginPlay`; trace values
|
||
showed legacy LOD0-first order. Explicit CVar parsing fixed the A/B. An ungated coarse-first run
|
||
then delayed the walkable gate to 1.653 s; admission was changed to wait for 9/9 and rerun.
|
||
- FloatingIslands at 25 cm hit its 120 s test timeout; the bounded 600 s retry passed in 192 s.
|
||
- The first `--stream-benchmark` and `--stream-pipeline` sprint commands emitted no Flight markers.
|
||
The corrected viewer command above produced valid crossing deltas, with the latency failure
|
||
reported rather than hidden.
|
||
- Unsupported `-RunName`, a fresh-shell type reuse, and one PowerShell metric-parser expression
|
||
failed before/after measurement without changing an Unreal run. The corrected command/parser
|
||
produced the data above.
|
||
|
||
Every Unreal launch was sequential, with more than 17 GiB free memory at the final launch checks;
|
||
actor-harness peak was about 3.5 GiB and all measured processes stayed under 8 GiB. No run returned
|
||
`0xC0000142`. Crash audit found no new UECC folder; the only folder is the pre-existing
|
||
`UECC-Windows-F1A3EFD5469F5DD62E68EBBACAC84376_0000` dated 2026-09-17. Test stdout and JSONL traces
|
||
remain under `Saved/BuildHost/...`; none were copied into `Research/`.
|
||
|
||
## 6. Files and compile spots
|
||
|
||
No new C++ source file was added. Modified source files and likely compile spots:
|
||
|
||
- `Source/VoxelForge/Private/VoxelWorld.cpp`, `Source/VoxelForge/Public/VoxelWorld.h`,
|
||
`Source/VoxelForge/Private/VoxelStartupTrace.cpp`,
|
||
`Source/VoxelForge/Public/VoxelStartupTrace.h` — VoxelForge runtime module; BuildHost UBT.
|
||
- `Source/VoxelForgeEditor/Private/VoxelForgeExploreCommandlet.cpp` — editor module; BuildHost UBT.
|
||
- `Standalone/Source/StandaloneViewer.cpp` — `Standalone/Build.ps1 -Target All`.
|
||
- `Tools/TestVoxelForgeCoreWorldHost.ps1` — harness argument/default changes; no C++ compile.
|
||
- `CODEMAP.md` §3, `ARCHITECTURE.md` §8.27, this report, and
|
||
`Standalone/Research/OwnerShapeWorld/gpu_field_port/LUNA_DIALOGUE.md` — documentation.
|
||
|
||
No owner file or asset was touched; no commit, push or stash was made.
|