wip(assembler): round S8 -- region rebuilds no longer stall admission; result backlog capped

voxel.CoreRegionConcurrentAdmission (default on): tiles independent of the
entering region keep submitting while a region page compiles; pages are
immutable shared_ptr owners so running readers survive eviction. 6 m/s: 11
whole-pass skips -> 0, walkable ring ready at every centre change.
voxel.StreamingResultBacklogCap=256 bounds finished results (slow-apply worst
case 125 -> 76 MB). Spawn unchanged at ~7.7 s: LOD8 is 46% of worker time.
At 60 m/s + teleport the collision ring is outrun (102/113 centres).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-19 09:43:03 +02:00
1 parent 5eb9ee76ff
commit 8440adc742
10 files changed
+1011 -78

No files matched your search

+44
View File
@@ -584,6 +584,13 @@ driven by `EditorBrush*` props.
admission count. `voxel.StreamingDynamicNearReserve=1` holds the authored near reserve while moving
or before the walkable gate, then releases it to coarse work after the stationary ring is ready.
Stationary player ≈ free. (Old per-frame O(loaded×desired) scan = 22ms.)
Core region compilation is a separate resource gate. With the default
`voxel.CoreRegionConcurrentAdmission=1`, tile keys that need the pending region are withheld, while
independent keys may use remaining worker slots. `0` restores the all-admission wait. Region pages
are built off the lookup map, published as immutable shared pages, and reclaimed when the final
reader releases its shared owner. `voxel.StreamingResultBacklogCap=256` independently bounds queued
result payloads plus active tile tasks and held prequeue results; `0` disables this memory backstop.
Result count is not used as a worker-slot count.
- **LOD** changes HOT-SWAP (`LoadTile` only, never unload-first) → no holes. LOD
reconciliation lives in the PERSISTENT per-frame submit loop (same loop as new-chunk loads),
NOT as a one-shot on the boundary-cross frame — a one-shot drops every chunk past the task
@@ -1565,6 +1572,43 @@ the recipe version remains unchanged. Null-RHI runs do not prove player-visible
[`Standalone/Research/WorldAssemblerM3/Round11/REPORT.md`](Standalone/Research/WorldAssemblerM3/Round11/REPORT.md)
for the audit counts, RMC review, quality matrix, commands and binary hashes.
### 8.29 Concurrent region admission and bounded result backlog — World Assembler S8 / M3 Round 12
The S7 moving trace found `bCoreRegionCompilePending` returning before all tile submissions. Each
such update could leave most slots unused while a new player center requested a region page. The
default `voxel.CoreRegionConcurrentAdmission=1` lets `LoadCoreTile` continue for keys outside the
pending and in-flight region sets. Keys that need those sets wait for publication; setting the CVar
to `0` restores the old all-admission gate for an A/B control. This changes scheduling only.
`World::compileTileRegion` builds region pages without mutating pages already in use, then publishes
them under the region-map lock. `generateTile` copies a `shared_ptr` while holding the map's shared
lock and keeps it for the whole mesh read. Evicting or replacing a map entry therefore cannot free a
page under an existing worker. The actor's shared `WorldLock` prevents a world edit/reset while a
tile reader or region compiler is active; `EndPlay` waits for the shared active-task count before
destroying the actor's UObject state.
The result backlog has its own backpressure control. `voxel.StreamingResultBacklogCap=256` counts
queued MPSC results, active tile-generation tasks and held visible-LOD0 prequeue results. Reaching
the cap stops new tile admissions until apply drains results or active tasks retire. It does not make
finished results consume worker slots in the normal admission count. `0` is the uncapped negative
control; the Core-off legacy test also exercises the default cap.
On the 25 cm owner SurfaceWorld plan, the matched 6 m/s CVar-off/on runs both completed 11 region
requests (one initial desired set plus ten center moves). The old gate recorded 11 global scheduler
skips; concurrent admission recorded none and submitted 110 unrelated tiles with no dependent-key
declines. All eleven changing support centers had the nine-tile walkable ring ready immediately.
Accumulated pending windows were about 0.43 s, but measured compiler wall time totaled about 11 ms.
At 60 m/s with a 400 m teleport, the trace recorded 113 region requests, 782 independent submissions
and 983 dependent-key declines. Most support centers advanced before their nine-tile ring could
become ready, so the high-speed gate still fails its travel-time target.
The shared result trace now records `queued_peak`, peak payload bytes, the configurable cap, and cap
stops. A slow-apply teleport stress run peaked at 256 results / 76.2 MB with the default cap; the
uncapped control reached 1,577 / 125.1 MB. Payload bytes exclude queue-node and allocator overhead.
The cap kept the observed backlog finite without reinstating the S6/S7 finished-result worker-slot
decline. Full timings, per-center records, quality checks and hashes are in
[`Standalone/Research/WorldAssemblerM3/Round12/REPORT.md`](Standalone/Research/WorldAssemblerM3/Round12/REPORT.md).
## 9. Multiplayer model (listen-server first, dedicated-friendly)
> **Status: transport is DESIGN ONLY — nothing is networked in-tree yet** (no `Replicated`/`HasAuthority`/RPCs; a