docs+cleanup: CURRENT-STATE.md and dead L86/L88 ablation switches removed (L131)
One current-state page (shipping behaviour, references with sources, gaps, verification, closed lines), linked from CLAUDE.md. Removes the L86/L88 passage/boundary ablation switches and the unused legacy route-grade audit; inventory of every kept switch in the report. Output identical: 24/24 + 18/18 hashes, fast tier, walk/seam audits, UE host build; timing unchanged (-0.2%, CI spans 0). No Source/ changes. 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
cbbfd46bd3
commit
81071969fc
11 files changed
+404
-147
No files matched your search
+8
-7
@@ -1522,11 +1522,12 @@ collision ring became walkable at 0.632 s. `voxel.StreamingCoarseFirst=1` with
|
|||||||
residency by about one third on the staged plan, but null-RHI residency does not prove rendered
|
residency by about one third on the staged plan, but null-RHI residency does not prove rendered
|
||||||
enclosure. Keep coarse-first opt-in until that view is checked in a rendered owner-plan run.
|
enclosure. Keep coarse-first opt-in until that view is checked in a rendered owner-plan run.
|
||||||
|
|
||||||
The separate `voxel.StreamingStartupApplyBoost` switch stays default-off. At `1`, it temporarily allows
|
The separate `voxel.StreamingStartupApplyBoost` switch is default-on in the current code. At `1`, it
|
||||||
12 visible mesh submissions / 14 ms while the initial desired set and walkable ring are incomplete,
|
temporarily allows up to 24 visible mesh submissions / 14 ms while the initial desired set and
|
||||||
with a 30 second ceiling; at `0`, the authored budget is unchanged. On the matched legacy-order test,
|
walkable ring are incomplete, with a 30 second ceiling; at `0`, the authored budget is unchanged.
|
||||||
the boost changed full-set readiness from 17.412 s to 17.346 s and removed count-cap frames, but did
|
The historical matched S6 run changed full-set readiness from 17.412 s to 17.346 s and removed
|
||||||
not improve end-to-end residency. Keep the normal 4 / 2 ms guard for play.
|
count-cap frames, but did not improve end-to-end residency. These current defaults are defined in
|
||||||
|
`Source/VoxelForge/Private/VoxelWorld.cpp`; the S6 measurement remains historical context.
|
||||||
|
|
||||||
The S6 trace found the shared pool was not saturated: its 10-slot idle estimate was about 132
|
The S6 trace found the shared pool was not saturated: its 10-slot idle estimate was about 132
|
||||||
slot-seconds on legacy order and 73 on gated coarse-first, while game-thread tile applies totaled only
|
slot-seconds on legacy order and 73 on gated coarse-first, while game-thread tile applies totaled only
|
||||||
@@ -1556,8 +1557,8 @@ by its RAII guard when the worker lambda exits. This still counts queued and run
|
|||||||
results do not consume an admission slot. `voxel.StreamingLegacyPendingResultCap=1` restores the old
|
results do not consume an admission slot. `voxel.StreamingLegacyPendingResultCap=1` restores the old
|
||||||
`PendingTiles` accounting; the test harness's `NearReserveMode=Legacy` also sets
|
`PendingTiles` accounting; the test harness's `NearReserveMode=Legacy` also sets
|
||||||
`voxel.StreamingDynamicNearReserve=0`, reproducing the S6 path. `StreamingDynamicNearReserve` now
|
`voxel.StreamingDynamicNearReserve=0`, reproducing the S6 path. `StreamingDynamicNearReserve` now
|
||||||
defaults to `1`; `StreamingCoarseFirst` remains `0`, and the apply boost remains `0` in the matched
|
defaults to `1`; `StreamingCoarseFirst` remains `0`. That historical S6 matched measurement disabled
|
||||||
measurement.
|
the startup apply boost (`voxel.StreamingStartupApplyBoost=0`); the current default is on (§8.27).
|
||||||
|
|
||||||
On the 2,578-key owner SurfaceWorld trace, the old-path control reached the full set in 17.527 s,
|
On the 2,578-key owner SurfaceWorld trace, the old-path control reached the full set in 17.527 s,
|
||||||
walkable ring in 0.650 s, and full LOD0 in 2.281 s. Dynamic admission reached them in 7.780 s,
|
walkable ring in 0.650 s, and full LOD0 in 2.281 s. Dynamic admission reached them in 7.780 s,
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ then wait for his results / pasted errors. Same for in-editor checks — ask for
|
|||||||
try to run anything.
|
try to run anything.
|
||||||
|
|
||||||
## Read first (in order, load only what the task needs)
|
## Read first (in order, load only what the task needs)
|
||||||
|
- **[CURRENT-STATE.md](CURRENT-STATE.md) — current shipping snapshot and verification entry point.**
|
||||||
- **[CODEMAP.md](CODEMAP.md) — ALWAYS.** Navigation: what it is, data-flow (§2), symbol→`file:line`
|
- **[CODEMAP.md](CODEMAP.md) — ALWAYS.** Navigation: what it is, data-flow (§2), symbol→`file:line`
|
||||||
index (§3), "I want to change X → go here" (§5), conventions & gotchas (§6). Trust **symbol names
|
index (§3), "I want to change X → go here" (§5), conventions & gotchas (§6). Trust **symbol names
|
||||||
over line numbers** (lines drift).
|
over line numbers** (lines drift).
|
||||||
|
|||||||
+2
-2
@@ -388,7 +388,7 @@ casse cette arithmetique *structurellement* — `BeginPlay` loggue une **Error**
|
|||||||
| `AdvanceHeadlessDigMotionTest` / `RecordHeadlessDigMotionFrame` | 3060 / 3217 | Explicit `-voxel.TestDigMotion=1` repro: optional near digs, then repeats underfoot digs and samples `Generator->GetDensityAt` immediately after each edit, on its first subsequent simulated frame, and on every following observation frame. `-voxel.TestDigMotionFieldOverride=1` is a measurement-only prototype that clears `CurrentFloor` and switches CMC to falling when the sampled post-edit density is air; it is inactive by default. The test counts false support, false air and downward velocity beyond one gravity step. `-voxel.TestDigMotionUnderfootDigCount` is clamped to 1–100; `-voxel.TestDigMotionUnderfootIntervalSeconds=0` performs per-frame rapid edits. The accompanying gap audit is scoped to the dig session. |
|
| `AdvanceHeadlessDigMotionTest` / `RecordHeadlessDigMotionFrame` | 3060 / 3217 | Explicit `-voxel.TestDigMotion=1` repro: optional near digs, then repeats underfoot digs and samples `Generator->GetDensityAt` immediately after each edit, on its first subsequent simulated frame, and on every following observation frame. `-voxel.TestDigMotionFieldOverride=1` is a measurement-only prototype that clears `CurrentFloor` and switches CMC to falling when the sampled post-edit density is air; it is inactive by default. The test counts false support, false air and downward velocity beyond one gravity step. `-voxel.TestDigMotionUnderfootDigCount` is clamped to 1–100; `-voxel.TestDigMotionUnderfootIntervalSeconds=0` performs per-frame rapid edits. The accompanying gap audit is scoped to the dig session. |
|
||||||
| `MaybeFinishHeadlessStreamingTest` | — | The existing `voxel.TestExitSeconds` diagnostic emits `VoxelForgeStreamingExitDiag` at most every 30 elapsed seconds, including threshold and early-return test flags; no output when the timer is unconfigured. |
|
| `MaybeFinishHeadlessStreamingTest` | — | The existing `voxel.TestExitSeconds` diagnostic emits `VoxelForgeStreamingExitDiag` at most every 30 elapsed seconds, including threshold and early-return test flags; no output when the timer is unconfigured. |
|
||||||
| `UpdateVisualStalenessAudit` | 5034 | Test-only camera-frustum coverage audit: tracks up to 24 real pre-skirt isosurface points per visible component, then counts frames where no visible tile component covers a previously visible, still-desired point (excluding edited bounds). `voxel.TestVisualGapInjectEarlyHide=1` hides a valid component for three frames and must be caught. `voxel.TestGapAuditLegacyHandoff=1` restores old handoff culling for A/B baselines. |
|
| `UpdateVisualStalenessAudit` | 5034 | Test-only camera-frustum coverage audit: tracks up to 24 real pre-skirt isosurface points per visible component, then counts frames where no visible tile component covers a previously visible, still-desired point (excluding edited bounds). `voxel.TestVisualGapInjectEarlyHide=1` hides a valid component for three frames and must be caught. `voxel.TestGapAuditLegacyHandoff=1` restores old handoff culling for A/B baselines. |
|
||||||
| `ProcessPendingChunks` | 7435 | Drains `CriticalProcessQueue`, `EditedProcessQueue`, `NearProcessQueue`, then `ProcessQueue`; applies under the authored 4-mesh/2 ms budget during normal play and the bounded shared startup budget (12 meshes/14 ms) until the initial desired set and walkable ring are ready. `voxel.StreamingStartupApplyBoost=0` restores the authored budget. `startup_apply_config` traces the actor-read CVar and both budgets; `startup_apply_budget` records activation/end. Reads per-request cancellation before removing its map entry, traces stale/obsolete/aborted discards with epoch and ordinal, then applies via `ApplyTileResult`. Step 1 prequeue still releases here and emits `VFStep1UploadCorpusReleased`. |
|
| `ProcessPendingChunks` | 7435 | Drains `CriticalProcessQueue`, `EditedProcessQueue`, `NearProcessQueue`, then `ProcessQueue`; applies under the authored 4-mesh/2 ms budget during normal play and the default-on bounded startup budget (24 meshes/14 ms, at most 30 s) until the initial desired set and walkable ring are ready. `voxel.StreamingStartupApplyBoost=0` restores the authored budget. `startup_apply_config` traces the actor-read CVar and both budgets; `startup_apply_budget` records activation/end. Reads per-request cancellation before removing its map entry, traces stale/obsolete/aborted discards with epoch and ordinal, then applies via `ApplyTileResult`. Step 1 prequeue still releases here and emits `VFStep1UploadCorpusReleased`. |
|
||||||
| `ApplyTileResult` | — | **Shared game-thread apply** for one `FChunkResult` (async drain + sync carve): discards stale generation epochs and keys no longer desired, marks loaded, ingests capture, EMPTY releases the tile's existing component (a re-gen can flip content→empty on band change — old geometry must not linger), else `ApplyMeshToTile`. Returns true iff a visible mesh uploaded (counts the budget). Doesn't touch `PendingTiles` (caller's). |
|
| `ApplyTileResult` | — | **Shared game-thread apply** for one `FChunkResult` (async drain + sync carve): discards stale generation epochs and keys no longer desired, marks loaded, ingests capture, EMPTY releases the tile's existing component (a re-gen can flip content→empty on band change — old geometry must not linger), else `ApplyMeshToTile`. Returns true iff a visible mesh uploaded (counts the budget). Doesn't touch `PendingTiles` (caller's). |
|
||||||
| `FVoxelStackSampler` / `FScopedVoxelStackRegistration` (`VoxelStackSampler.h/.cpp`) | — | **Diagnostic raw stack sampler, off by default.** A sampler thread captures registered generation workers' stacks (`CaptureThreadStackBackTrace`) every N µs and tags each with the tile's LOD. It writes bounded raw PCs to CSV plus a symbolization-free summary under `Saved/`; symbol resolution is deferred until after process exit so the measured process never initializes/calls DbgHelp for this diagnostic. Lifecycle teardown is serialized and registration TLS is session-tagged. Registration is per tile TASK in `LoadTile` (and the export's tasks), never per sample; disabled costs one relaxed atomic load. Game `-voxel.SampleStacks=<us>`, commandlet `-samplestacks[=us]`. |
|
| `FVoxelStackSampler` / `FScopedVoxelStackRegistration` (`VoxelStackSampler.h/.cpp`) | — | **Diagnostic raw stack sampler, off by default.** A sampler thread captures registered generation workers' stacks (`CaptureThreadStackBackTrace`) every N µs and tags each with the tile's LOD. It writes bounded raw PCs to CSV plus a symbolization-free summary under `Saved/`; symbol resolution is deferred until after process exit so the measured process never initializes/calls DbgHelp for this diagnostic. Lifecycle teardown is serialized and registration TLS is session-tagged. Registration is per tile TASK in `LoadTile` (and the export's tasks), never per sample; disabled costs one relaxed atomic load. Game `-voxel.SampleStacks=<us>`, commandlet `-samplestacks[=us]`. |
|
||||||
| Room-cache performance (2026-09-13): `VF_FindPlayerFitPointForRoomMemoized` / `GPlayerFitMemo` (`VoxelCaveMorphology.cpp`), `voxel.TileCacheWindow` + `VoxelGenLOD::TileOriginVoxels/TileCellsPerAxis` (`VoxelGenerator.h`), `FChunkSDFSpatialIndex` | — | **Player-fit memo:** exact 97-word key, process-wide, `voxel.PlayerFitMemo`. **Tile cache window:** the room cache covers the requesting tile's footprint plus a fixed collect margin. It is set via `TGuardValue` in `GenerateMesh`/classify, and is window-invariant by construction (the margin does not grow with the tile). **LOD-gated:** fused path at LOD ≥ `voxel.TileCacheWindowMinLOD` (3), op-stack at LOD ≥ `voxel.TileCacheWindowOpStackMinLOD` (4); lower LODs keep the 4-chunk worker window, because the tile window slowed LOD0 evaluation ~6%. Strates whose authored terrain ops exceed the proven 256-voxel extent (or are malformed/unloaded) fall back to the legacy window (`VF_ComputeTerrainOpEnvelope`). `voxel.SpatialIndex` is -1 auto (off at fused LOD0, on elsewhere), 0 or 1. **Spatial index:** ordered XY buckets over cache primitives, exact rejection. The `static_assert` in `VoxelStrateTypes.h` ties `VF_STRATE_PARAM_FIELDS` to `FStrateGenerationParams` (83 fields + 8 B padding). |
|
| Room-cache performance (2026-09-13): `VF_FindPlayerFitPointForRoomMemoized` / `GPlayerFitMemo` (`VoxelCaveMorphology.cpp`), `voxel.TileCacheWindow` + `VoxelGenLOD::TileOriginVoxels/TileCellsPerAxis` (`VoxelGenerator.h`), `FChunkSDFSpatialIndex` | — | **Player-fit memo:** exact 97-word key, process-wide, `voxel.PlayerFitMemo`. **Tile cache window:** the room cache covers the requesting tile's footprint plus a fixed collect margin. It is set via `TGuardValue` in `GenerateMesh`/classify, and is window-invariant by construction (the margin does not grow with the tile). **LOD-gated:** fused path at LOD ≥ `voxel.TileCacheWindowMinLOD` (3), op-stack at LOD ≥ `voxel.TileCacheWindowOpStackMinLOD` (4); lower LODs keep the 4-chunk worker window, because the tile window slowed LOD0 evaluation ~6%. Strates whose authored terrain ops exceed the proven 256-voxel extent (or are malformed/unloaded) fall back to the legacy window (`VF_ComputeTerrainOpEnvelope`). `voxel.SpatialIndex` is -1 auto (off at fused LOD0, on elsewhere), 0 or 1. **Spatial index:** ordered XY buckets over cache primitives, exact rejection. The `static_assert` in `VoxelStrateTypes.h` ties `VF_STRATE_PARAM_FIELDS` to `FStrateGenerationParams` (83 fields + 8 B padding). |
|
||||||
@@ -396,7 +396,7 @@ casse cette arithmetique *structurellement* — `BeginPlay` loggue une **Error**
|
|||||||
| `RecordTileHash` / `WriteTileHashDump` | — | Headless `-voxel.TileHashDump=<absolute path>` parity instrument. Records the exact `FVoxelMeshData` used by the streaming result, including empty/classified tiles, then writes sorted absolute tile keys, LOD step/cells, content-band limits, settings digest context, and the shared `VoxelGeometryHash` at `EndPlay`. |
|
| `RecordTileHash` / `WriteTileHashDump` | — | Headless `-voxel.TileHashDump=<absolute path>` parity instrument. Records the exact `FVoxelMeshData` used by the streaming result, including empty/classified tiles, then writes sorted absolute tile keys, LOD step/cells, content-band limits, settings digest context, and the shared `VoxelGeometryHash` at `EndPlay`. |
|
||||||
| `SyncRemeshTile` | — | **INSTANT DIG**: level-0 same-frame re-mesh on the game thread. Uses `PreEditDensityCache` when the tile is resident in the bounded local cache, replays the current DiffLayer over that exact procedural lattice, then meshes/applies inline so a carve is visible THIS frame. A cache miss uses normal generation; it captures the unedited lattice if the tile needs meshing, while uniform-tile proofs remain enabled. |
|
| `SyncRemeshTile` | — | **INSTANT DIG**: level-0 same-frame re-mesh on the game thread. Uses `PreEditDensityCache` when the tile is resident in the bounded local cache, replays the current DiffLayer over that exact procedural lattice, then meshes/applies inline so a carve is visible THIS frame. A cache miss uses normal generation; it captures the unedited lattice if the tile needs meshing, while uniform-tile proofs remain enabled. |
|
||||||
| `PreEditDensityCache` / `VoxelForgePreEditDensityCache::BuildEditedGrid` | — | Per-world cache of the pawn's current L0 tile: exact 35³ pre-edit samples, max **171,500 bytes**. It is pruned when the pawn crosses chunk boundaries and cleared on `RegenerateAllChunks`. `BuildEditedGrid` snapshots touched diff chunks once and reproduces `GetDensityAt`'s final `pre-edit - EvaluateMods` operation before the per-call shared-grid mesher path. |
|
| `PreEditDensityCache` / `VoxelForgePreEditDensityCache::BuildEditedGrid` | — | Per-world cache of the pawn's current L0 tile: exact 35³ pre-edit samples, max **171,500 bytes**. It is pruned when the pawn crosses chunk boundaries and cleared on `RegenerateAllChunks`. `BuildEditedGrid` snapshots touched diff chunks once and reproduces `GetDensityAt`'s final `pre-edit - EvaluateMods` operation before the per-call shared-grid mesher path. |
|
||||||
| `UpdateChunksAroundPosition` / `GetGenerationAdmissionCount` | 10990 / 10971 | Shared Core/legacy scheduler. Builds the desired set and delta-culls leavers; admits the occupied/support tile plus collision-required LOD0 tiles in the pawn's 3×3 XY ring as `CollisionCritical`. S5 coarse-first admission stays opt-in (`voxel.StreamingCoarseFirst=1`). `voxel.StreamingDynamicNearReserve=1` is now the default: it keeps the authored near reserve while moving or until the stationary walkable ring is ready, then makes those slots available to coarse work. Admission counts submitted queued/running tasks, not completed results waiting in the MPSC result queues; `voxel.StreamingLegacyPendingResultCap=1` restores the old `PendingTiles`-based cap for the negative control. `PendingTiles` still lasts through game-thread apply for duplicate suppression and result bookkeeping. The clipmap stays non-overlapping and load-before-unload / `TransitionHold` reconciliation remains authoritative. Standalone has no mirror of this actor scheduler. §8.10 + §8.26–8.28. |
|
| `UpdateChunksAroundPosition` / `GetGenerationAdmissionCount` | 10990 / 10971 | Shared Core/legacy scheduler. Builds the desired set and delta-culls leavers; admits the occupied/support tile plus collision-required LOD0 tiles in the pawn's 3×3 XY ring as `CollisionCritical`. S5 coarse-first admission stays opt-in (`voxel.StreamingCoarseFirst=1`). `voxel.StreamingDynamicNearReserve=1` is the default: it keeps the authored near reserve while moving or until the stationary walkable ring is ready, then makes those slots available to coarse work. Admission counts submitted queued/running tasks, not completed results waiting in the MPSC result queues; `voxel.StreamingLegacyPendingResultCap=1` restores the old `PendingTiles`-based cap for the negative control. `voxel.StreamingFarApplySupplement=1` is the default L121 lane: after the visible-apply cap, at most one far result is admitted when under half the apply-time budget and startup boost is inactive. `PendingTiles` still lasts through game-thread apply for duplicate suppression and result bookkeeping. The clipmap stays non-overlapping and load-before-unload / `TransitionHold` reconciliation remains authoritative. Standalone has no mirror of this actor scheduler. §8.10 + §8.26–8.28. |
|
||||||
| `AdvanceHeadlessCollisionGateStressTest` / `ObserveHeadlessCollisionGateStressTest` / `MaybeFinishHeadlessCollisionGateStressTest` / `MeasureHeadlessCollisionGateStressTerrain` | — | Explicit `-voxel.TestCollisionGateStress=1` harness only. The normal spawn-height cvar offsets from the measured density surface; `voxel.TestCollisionGateStressDeepDrop=1` carves a process-local box shaft from above the top to just above the floor tile, extending along the post-landing route so the pawn does not run into the shaft sidewall, temporarily raises only the transient test DiffLayer brush-radius allowance for that fixture, removes only the local pawn's redundant streaming anchor for this isolated repro, proves every sample in two complete outside-ring level-0 tiles is air before seeding their known-empty status, prewarms the known-empty in-ring column, and asserts that the support walk reaches the in-layout floor outside the aligned level-0 render ring before the pawn drops. The log reports whether the fixed gate retains that otherwise out-of-ring target. Other streaming anchors remain active. The fixture rejects a target or floor outside the layout, a non-air empty-tile proof, or a floor inside the aligned level-0 ring. The `GetDensityAt` column at capsule feet defines the local air/solid surface; the deep-drop column crossing is cached after its first exact scan. Each frame records actor position, velocity, direct foot tile and gate support readiness, gate state, signed feet clearance, and a ≤0.5-voxel sweep between positions. PASS requires no measured clearance below −5 cm; deep-drop gate-on also requires horizontal travel during a hold. Result logs include the terminal density column, first crossing below spawn height, hold count/time, and gated horizontal progress. |
|
| `AdvanceHeadlessCollisionGateStressTest` / `ObserveHeadlessCollisionGateStressTest` / `MaybeFinishHeadlessCollisionGateStressTest` / `MeasureHeadlessCollisionGateStressTerrain` | — | Explicit `-voxel.TestCollisionGateStress=1` harness only. The normal spawn-height cvar offsets from the measured density surface; `voxel.TestCollisionGateStressDeepDrop=1` carves a process-local box shaft from above the top to just above the floor tile, extending along the post-landing route so the pawn does not run into the shaft sidewall, temporarily raises only the transient test DiffLayer brush-radius allowance for that fixture, removes only the local pawn's redundant streaming anchor for this isolated repro, proves every sample in two complete outside-ring level-0 tiles is air before seeding their known-empty status, prewarms the known-empty in-ring column, and asserts that the support walk reaches the in-layout floor outside the aligned level-0 render ring before the pawn drops. The log reports whether the fixed gate retains that otherwise out-of-ring target. Other streaming anchors remain active. The fixture rejects a target or floor outside the layout, a non-air empty-tile proof, or a floor inside the aligned level-0 ring. The `GetDensityAt` column at capsule feet defines the local air/solid surface; the deep-drop column crossing is cached after its first exact scan. Each frame records actor position, velocity, direct foot tile and gate support readiness, gate state, signed feet clearance, and a ≤0.5-voxel sweep between positions. PASS requires no measured clearance below −5 cm; deep-drop gate-on also requires horizontal travel during a hold. Result logs include the terminal density column, first crossing below spawn height, hold count/time, and gated horizontal progress. |
|
||||||
| `BuildDesiredTiles` | 6482 | Builds `DesiredSorted`+`DesiredStamped` (player clipmap shells), then adds streaming anchors and the pending player's collision-only support column before the leaver sweep. It orders from the true local pawn position and builds `CriticalDesiredTiles` for the unresolved support target, occupied/support and heading tiles. Also rebuilds `DesiredTransitionDescendants` (ancestor → desired descendants, including face/edge-touching replacements) for the reconcile pass. |
|
| `BuildDesiredTiles` | 6482 | Builds `DesiredSorted`+`DesiredStamped` (player clipmap shells), then adds streaming anchors and the pending player's collision-only support column before the leaver sweep. It orders from the true local pawn position and builds `CriticalDesiredTiles` for the unresolved support target, occupied/support and heading tiles. Also rebuilds `DesiredTransitionDescendants` (ancestor → desired descendants, including face/edge-touching replacements) for the reconcile pass. |
|
||||||
| `CollisionGateDesiredTiles` / `RequestCollisionGateSupportTile` | 5062 | Retains an unresolved support target and up to three level-0 tiles below it across desired-set rebuilds. The additional keys are hidden collision-only tiles, queued ahead of ordinary streaming, and pruned once resolved or outside the active column. |
|
| `CollisionGateDesiredTiles` / `RequestCollisionGateSupportTile` | 5062 | Retains an unresolved support target and up to three level-0 tiles below it across desired-set rebuilds. The additional keys are hidden collision-only tiles, queued ahead of ordinary streaming, and pruned once resolved or outside the active column. |
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# VoxelForge current state
|
||||||
|
|
||||||
|
As of 2026-10-31. The L130 baseline is on `assembler/world` as `044cd6d`; this L131 work branch starts at `cbbfd46`. Current-state claims below point to their code or measured report.
|
||||||
|
|
||||||
|
## What ships today
|
||||||
|
|
||||||
|
- **Core:** evaluator version **227**. Unreal's `AVoxelWorld::bUseVoxelForgeCore` is opt-in and defaults to `false`; the legacy generator remains the default runtime path. [Core version](Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h), [runtime switch](Source/VoxelForge/Public/VoxelWorld.h), [L130 report](Standalone/Research/WorldAssemblerM3/Linux130/REPORT.md).
|
||||||
|
- **Generator dispatch when Core is enabled:** `SurfaceWorld` uses the Core surface adapter; `FloatingIslands` uses its Core adapter. `Caves` uses the Core cave field only with `Core.Caves.PrimitiveField` v1. `Maze` and `VerticalShafts` use the Core lattice field only with `Core.Lattice.PrimitiveField` v1. Other generator/recipe combinations fall through to `FLegacyGeneratorFieldAdapter`. [Dispatch](Standalone/Core/src/ShapeWorldInternal.h), [recipe checks](Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h).
|
||||||
|
- **Passages:** continuous smooth swept tubes with a continuous floor profile. L125 stamps conservative route slabs and outside sentinels into the tile cache; exact route geometry is still evaluated. All 21,425 route samples passed the open-air walk check; the nine-station floor probe's maximum root offset was 7.884 mm. L130 sets the shared influence reach to **1.0533 m** (0.75 m shell + 0.21 m relief + 0.50 m smooth-max support / 6 + 0.01 m margin), converted once from metres to Core voxels for the proof, feature, fallback, and off-grid bounds. [L125](Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md), [L130](Standalone/Research/WorldAssemblerM3/Linux130/REPORT.md).
|
||||||
|
- **Streaming:** arrival uses a bounded startup apply burst: `voxel.StreamingStartupApplyBoost=1` by default, up to 24 visible meshes or 14 ms per frame for at most 30 seconds, until the initial desired set and walkable ring are ready. `voxel.StreamingFarApplySupplement=1` is also default-on: after the normal visible apply cap, at most one far result applies when under half the apply-time budget; it is inactive during the startup burst. Dynamic near reserve defaults on; coarse-first remains off; the legacy pending-result cap defaults off. The far-apply lane is Unreal-only. [CVar source](Source/VoxelForge/Private/VoxelWorld.cpp), [L121 report](Standalone/Research/WorldAssemblerM3/Linux121/REPORT.md), [architecture](ARCHITECTURE.md).
|
||||||
|
- **Determinism:** proven on Linux with Clang and GCC at W1/W8/W12. L131's unchanged-output comparison covers owner4's SW/FI/TN/VS views in 24 compiler/worker cases; the canonical owner4/owner2 recipe matrix also passes. Windows determinism is unverified. [L131 checks](Standalone/Research/WorldAssemblerM3/Linux131/REPORT.md), [v227 canonical hashes](Standalone/Tools/verify/baselines/owner-hash/canonical/).
|
||||||
|
|
||||||
|
## Current performance references
|
||||||
|
|
||||||
|
Headless medians in seconds, five interleaved L80-style measurements per version in each cell. Near-ready means the complete LOD0–2 set; whole-view is the full requested view. Values below are the edited L131 binary; the paired pre-cleanup comparison is in the [L131 report](Standalone/Research/WorldAssemblerM3/Linux131/REPORT.md) and [timing summary](Saved/Linux/l131/timing/summary.json).
|
||||||
|
|
||||||
|
| Stratum | Near-ready W8 / W12 | Whole-view W8 / W12 |
|
||||||
|
|---|---:|---:|
|
||||||
|
| S0 | 0.804 / 0.848 | 1.811 / 1.832 |
|
||||||
|
| S1 | 1.014 / 1.002 | 1.993 / 1.886 |
|
||||||
|
| S2 | 1.060 / 1.012 | 1.960 / 1.865 |
|
||||||
|
| S3 | 0.917 / 0.884 | 1.887 / 1.782 |
|
||||||
|
|
||||||
|
Across 40 paired runs per metric, the mean relative change from pre-cleanup L130 was −0.22% near-ready (95% CI −1.02% to +0.57%) and −0.29% whole-view (−1.04% to +0.46%); neither indicates a measurable slowdown. The machine gate was load 0.81 and 99.2% idle. [L80 protocol](Standalone/Research/WorldAssemblerM3/Linux80/REPORT.md), [runner and raw runs](Standalone/Research/WorldAssemblerM3/Linux131/RunL131Timing.py).
|
||||||
|
|
||||||
|
The latest recorded Linux Unreal start-to-LOD0–2 values are L127's one run per stratum: S0 2.456 s, S1 2.231 s, S2 2.514 s, S3 2.221 s. L130 did not rerun UE startup or movement. Five L127 runs at 30 m/s, 12 s moving plus 5 s dwell, had median moving near coverage **40.22%**, far holes **3.46%**, tick p99 **10.80 ms**, and worst tick **13.27 ms**. After stopping, near coverage reached 100% and far holes reached 0%. These are the latest UE references, not v227 UE measurements. [L127 report](Standalone/Research/WorldAssemblerM3/Linux127/REPORT.md), [L127 movement summary](Saved/Linux/l127/ue/movement-pairs-summary.json), [L127 start summaries](Saved/Linux/l127/ue/merge/start-summary.json).
|
||||||
|
|
||||||
|
## Open gaps
|
||||||
|
|
||||||
|
- Multiplayer world lifecycle is unfinished: seed/layout replication, authoritative modification RPCs, and serialized diff replay for late join are still open. See [ARCHITECTURE §9.5 and §9.7](ARCHITECTURE.md).
|
||||||
|
- Determinism has not been verified on Windows. Linux Clang/GCC agreement does not establish MSVC agreement.
|
||||||
|
- NullRHI measures residency and apply timing, not the first presented pixel or rendered enclosure. L127 also found four low-contrast views among 23 otherwise verified captures. [L121](Standalone/Research/WorldAssemblerM3/Linux121/REPORT.md), [L127](Standalone/Research/WorldAssemblerM3/Linux127/REPORT.md).
|
||||||
|
- UE startup/movement numbers above predate L130's v227 reach change; there is no L130/L131 UE movement comparison.
|
||||||
|
|
||||||
|
## How to verify
|
||||||
|
|
||||||
|
- Build standalone Clang or GCC with [`Standalone/BuildLinux.sh`](Standalone/BuildLinux.sh), for example `bash Standalone/BuildLinux.sh --compiler=clang++-19 --variant=l131-clang --fp-contract=off --jobs=4`. The script pins CPUs 0–11 and applies `prlimit --as=6442450944` itself.
|
||||||
|
- Fast tier: `python3 Standalone/Tools/verify/verify.py fast --out Saved/Linux/l131 --overall-timeout 1740`. It runs the walkability and current owner checks; per-run logs and the summary stay under `Saved/Linux/l131`.
|
||||||
|
- Canonical output baselines are the v227 files in `Standalone/Tools/verify/baselines/owner-hash/canonical/`. L131 also provides reproducible pre-cleanup identity matrices for owner4 tile hashes and owner4/owner2 canonical hashes under `Standalone/Research/WorldAssemblerM3/Linux131/`.
|
||||||
|
- Timing follows L80: quiet machine, no overlapping build, one warm-up per version, five interleaved runs per stratum and worker count, W8/W12. Each headless run uses `taskset -c 0-11`, `prlimit --as=6442450944`, and a 1,740 s timeout. See [`RunL131Timing.py`](Standalone/Research/WorldAssemblerM3/Linux131/RunL131Timing.py).
|
||||||
|
- Linux host build: `/home/jahni/UnrealEngine/Engine/Build/BatchFiles/Linux/Build.sh VFHostEditor Linux Development -Project=/home/jahni/VFHost/VFHost.uproject -NoUBA -MaxParallelActions=4 -Log=/home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l131/ubt.log`. Run Unreal without `prlimit`.
|
||||||
|
|
||||||
|
## Closed experiments
|
||||||
|
|
||||||
|
These rejected speed/streaming proposals stay closed unless new evidence changes their measured failure. Reports and surviving patches are linked in the [L131 inventory](Standalone/Research/WorldAssemblerM3/Linux131/REPORT.md).
|
||||||
|
|
||||||
|
| Line | Result |
|
||||||
|
|---|---|
|
||||||
|
| L116 tunnel chord bound and z cache | Pair count fell 20.8%, but stayed 1.96× L109 and readiness was 15–30% slower. Patch: [`chord-bound-zcolumn-not-merged.patch`](Standalone/Research/WorldAssemblerM3/Linux116/patches/chord-bound-zcolumn-not-merged.patch), commit `89504ec`; see [report](Standalone/Research/WorldAssemblerM3/Linux116/REPORT.md). |
|
||||||
|
| L118 pair pruning / deferred floor work | Pruned 17–18% of candidate pairs but remained 17.2–25.7% behind L109 near-ready. [Report](Standalone/Research/WorldAssemblerM3/Linux118/REPORT.md); patch: [`l118-designs.patch`](Standalone/Research/WorldAssemblerM3/Linux118/l118-designs.patch). |
|
||||||
|
| L126 floor-call filters | Cut floor calls 20–23% without reducing pair counts; all eight cells missed L109. Candidate source was restored and no standalone patch was kept; see [report](Standalone/Research/WorldAssemblerM3/Linux126/REPORT.md) and commit `01a5094`. |
|
||||||
|
| L128 half-open slab ownership | Ownership audit passed, but readiness was 14.8–28.0% behind L109 and moving coverage dropped. Report and patch `l128-slab-ownership.patch` are in archived commit `7022d02`. |
|
||||||
|
| L129 2 m physical reach | v225's metre/Core-voxel bounds mismatch made the correctly bounded candidate do more work; it was slower and failed UE movement gates. Report and patch `l129-reach-2m.patch` are in archived commit `0d1140c`. |
|
||||||
|
| L120 priority split / extra worker slots | Neither met coverage and tick gates; 10 slots reached a 16.67 ms worst tick against 15.43 ms baseline. [Report](Standalone/Research/WorldAssemblerM3/Linux120/REPORT.md); no production patch retained. |
|
||||||
|
| L122 admission relaxation | Early admission missed p99 or far-hole gates; no behavior retained. [Report](Standalone/Research/WorldAssemblerM3/Linux122/REPORT.md); patch: [`l122-trace.patch`](Standalone/Research/WorldAssemblerM3/Linux122/l122-trace.patch). |
|
||||||
|
| L123 lookahead / completion gate | Lookahead failed p99 and worsened near/far coverage; queue-only also failed p99. [Report](Standalone/Research/WorldAssemblerM3/Linux123/REPORT.md); patch: [`l123-queue-lookahead.patch`](Standalone/Research/WorldAssemblerM3/Linux123/l123-queue-lookahead.patch). |
|
||||||
|
| L124 early LOD0 pages | Optimistic gain stayed below 100 ms except negative cases; no publication/scheduling implementation was made. [Report](Standalone/Research/WorldAssemblerM3/Linux124/REPORT.md). |
|
||||||
@@ -33,48 +33,22 @@
|
|||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// L88-only composition split. These switches let the timing harness remove passage work and
|
static bool VF_IsDiagnosticEnvSwitchEnabled(const char* Name)
|
||||||
// resolved boundary-band work independently. They are diagnostic only, never world settings.
|
|
||||||
static bool VF_IsL88DiagnosticSwitchEnabled(const char* Name)
|
|
||||||
{
|
{
|
||||||
const char* Value=std::getenv(Name);
|
const char* Value=std::getenv(Name);
|
||||||
return Value&&Value[0]=='1'&&Value[1]=='\0';
|
return Value&&Value[0]=='1'&&Value[1]=='\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool VF_IsL88PassageCompositionDisabled()
|
|
||||||
{
|
|
||||||
static const bool bDisabled=VF_IsL88DiagnosticSwitchEnabled(
|
|
||||||
"VOXELFORGE_L88_DISABLE_PASSAGES")
|
|
||||||
||VF_IsL88DiagnosticSwitchEnabled("VOXELFORGE_L86_DISABLE_PASSAGE_COMPOSITION");
|
|
||||||
return bDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool VF_IsL88BoundaryBandsDisabled()
|
|
||||||
{
|
|
||||||
static const bool bDisabled=VF_IsL88DiagnosticSwitchEnabled(
|
|
||||||
"VOXELFORGE_L88_DISABLE_BOUNDARY_BANDS")
|
|
||||||
||VF_IsL88DiagnosticSwitchEnabled("VOXELFORGE_L86_DISABLE_PASSAGE_COMPOSITION");
|
|
||||||
return bDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool VF_IsL88AllowPassageAblationWalkabilityFailure()
|
|
||||||
{
|
|
||||||
static const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled(
|
|
||||||
"VOXELFORGE_L88_ALLOW_PASSAGE_ABLATION_WALKABILITY_FAILURE");
|
|
||||||
return bEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool VF_IsL98PassagePrepareTraceEnabled()
|
static bool VF_IsL98PassagePrepareTraceEnabled()
|
||||||
{
|
{
|
||||||
static const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled(
|
static const bool bEnabled=VF_IsDiagnosticEnvSwitchEnabled(
|
||||||
"VOXELFORGE_L98_PASSAGE_PREP_TRACE");
|
"VOXELFORGE_L98_PASSAGE_PREP_TRACE");
|
||||||
return bEnabled;
|
return bEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool VF_IsL130PassageReachProofAuditEnabled()
|
static bool VF_IsL130PassageReachProofAuditEnabled()
|
||||||
{
|
{
|
||||||
static const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled(
|
static const bool bEnabled=VF_IsDiagnosticEnvSwitchEnabled(
|
||||||
"VOXELFORGE_L130_PASSAGE_REACH_PROOF_AUDIT");
|
"VOXELFORGE_L130_PASSAGE_REACH_PROOF_AUDIT");
|
||||||
return bEnabled;
|
return bEnabled;
|
||||||
}
|
}
|
||||||
@@ -327,18 +301,14 @@ public:
|
|||||||
{
|
{
|
||||||
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
|
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
|
||||||
minimumSubvoxels_[2],maximumSubvoxels_[2]);
|
minimumSubvoxels_[2],maximumSubvoxels_[2]);
|
||||||
const bool disablePassageComposition=VF_IsL88PassageCompositionDisabled();
|
mayContainTransitionPassageFade_=shape.ResolvedTransitionPassageFadeIntersectsTileXY(
|
||||||
if(VF_IsL88BoundaryBandsDisabled())mayContainResolvedBoundaryBand_=false;
|
minimumSubvoxels_,maximumSubvoxels_);
|
||||||
mayContainTransitionPassageFade_=!disablePassageComposition
|
featureIndices_=shape.BuildPassageFeatureTileList(
|
||||||
&&shape.ResolvedTransitionPassageFadeIntersectsTileXY(
|
minimumSubvoxels_,maximumSubvoxels_);
|
||||||
minimumSubvoxels_,maximumSubvoxels_);
|
|
||||||
if(!disablePassageComposition)
|
|
||||||
featureIndices_=shape.BuildPassageFeatureTileList(
|
|
||||||
minimumSubvoxels_,maximumSubvoxels_);
|
|
||||||
stampIndices_=shape.BuildStampTileList(minimumSubvoxels_,maximumSubvoxels_);
|
stampIndices_=shape.BuildStampTileList(minimumSubvoxels_,maximumSubvoxels_);
|
||||||
cavernFeatureIndices_=shape.BuildCavernFeatureTileList(
|
cavernFeatureIndices_=shape.BuildCavernFeatureTileList(
|
||||||
minimumSubvoxels_,maximumSubvoxels_);
|
minimumSubvoxels_,maximumSubvoxels_);
|
||||||
passageRoutes_.assign(shape.ResolvedLayout&&!disablePassageComposition
|
passageRoutes_.assign(shape.ResolvedLayout
|
||||||
?shape.ResolvedLayout->passages.size():0,0);
|
?shape.ResolvedLayout->passages.size():0,0);
|
||||||
passageRouteSegments_.resize(passageRoutes_.size());
|
passageRouteSegments_.resize(passageRoutes_.size());
|
||||||
for(const std::uint32_t featureIndex:featureIndices_)
|
for(const std::uint32_t featureIndex:featureIndices_)
|
||||||
@@ -1561,12 +1531,8 @@ public:
|
|||||||
// the generic stratum transition distance creates a discontinuity at a
|
// the generic stratum transition distance creates a discontinuity at a
|
||||||
// mouth that crosses a wide transition band. Keep that opt-in field whole;
|
// mouth that crosses a wide transition band. Keep that opt-in field whole;
|
||||||
// its host-rock value already supplies the ceiling and bedrock.
|
// its host-rock value already supplies the ceiling and bedrock.
|
||||||
const bool disablePassageComposition=!nativeLattice
|
|
||||||
&&VF_IsL88PassageCompositionDisabled();
|
|
||||||
const bool disableBoundaryBands=!nativeLattice
|
|
||||||
&&VF_IsL88BoundaryBandsDisabled();
|
|
||||||
float boundary=graphDensity;
|
float boundary=graphDensity;
|
||||||
if(!nativeLattice&&!disableBoundaryBands)
|
if(!nativeLattice)
|
||||||
{
|
{
|
||||||
VoxelForgeCore::Linux77Profiler::FScopedPhase l77BandsPhase(
|
VoxelForgeCore::Linux77Profiler::FScopedPhase l77BandsPhase(
|
||||||
VoxelForgeCore::Linux77Profiler::EPhase::Bands);
|
VoxelForgeCore::Linux77Profiler::EPhase::Bands);
|
||||||
@@ -1595,7 +1561,6 @@ public:
|
|||||||
?bound->Resolved->passageCapabilities.hasNativeCaveField
|
?bound->Resolved->passageCapabilities.hasNativeCaveField
|
||||||
:bound->Resolved->passageCapabilities.hasNativeLatticeField))
|
:bound->Resolved->passageCapabilities.hasNativeLatticeField))
|
||||||
{
|
{
|
||||||
if(!disablePassageComposition)
|
|
||||||
{
|
{
|
||||||
VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase(
|
VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase(
|
||||||
VoxelForgeCore::Linux77Profiler::EPhase::Passage);
|
VoxelForgeCore::Linux77Profiler::EPhase::Passage);
|
||||||
@@ -1626,7 +1591,6 @@ public:
|
|||||||
ELegacyFieldTerm::ComposerPassage);
|
ELegacyFieldTerm::ComposerPassage);
|
||||||
final=ApplyResolvedCavernFloorCaps(stamped,X,Y,Z);
|
final=ApplyResolvedCavernFloorCaps(stamped,X,Y,Z);
|
||||||
}
|
}
|
||||||
if(!disablePassageComposition)
|
|
||||||
{
|
{
|
||||||
VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase(
|
VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase(
|
||||||
VoxelForgeCore::Linux77Profiler::EPhase::Passage);
|
VoxelForgeCore::Linux77Profiler::EPhase::Passage);
|
||||||
@@ -2332,18 +2296,8 @@ public:
|
|||||||
const bool bPassageRoutesValid=!bValidatePassageRoutes||ValidatePassageRoutes();
|
const bool bPassageRoutesValid=!bValidatePassageRoutes||ValidatePassageRoutes();
|
||||||
if(!bPassageRoutesValid)
|
if(!bPassageRoutesValid)
|
||||||
{
|
{
|
||||||
if(VF_IsL88PassageCompositionDisabled()
|
Error="compiled shape world contains a solid passage centreline sample";
|
||||||
&&!VF_IsL88BoundaryBandsDisabled()
|
return false;
|
||||||
&&VF_IsL88AllowPassageAblationWalkabilityFailure())
|
|
||||||
{
|
|
||||||
std::printf("[L88PassageAblation] route walkability failed as expected; "
|
|
||||||
"continuing only to measure passage-off/bands-on readiness\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Error="compiled shape world contains a solid passage centreline sample";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Stats.PassageValidationSeconds=std::chrono::duration<double>(Clock::now()-Substage).count();
|
Stats.PassageValidationSeconds=std::chrono::duration<double>(Clock::now()-Substage).count();
|
||||||
Built=true;
|
Built=true;
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# Linux131 — current state and dead experiment cleanup
|
||||||
|
|
||||||
|
Branch `wip/l131-current-state`, based on `cbbfd46`; Core evaluator remains v227. The root [`CURRENT-STATE.md`](../../../../CURRENT-STATE.md) consolidates the shipping behavior, current references, verification commands, open gaps, and closed proposals.
|
||||||
|
|
||||||
|
## Removed
|
||||||
|
|
||||||
|
- Removed `VOXELFORGE_L86_DISABLE_PASSAGE_COMPOSITION`, `VOXELFORGE_L88_DISABLE_PASSAGES`, `VOXELFORGE_L88_DISABLE_BOUNDARY_BANDS`, and `VOXELFORGE_L88_ALLOW_PASSAGE_ABLATION_WALKABILITY_FAILURE`. These only supported archived passage/boundary ablations in `Linux86/RunL86Ceiling.py`, `Linux87/RunL87Timeline.py`, and `Linux88/RunL88CeilingSplit.py`; no current `verify.py` gate or live comparison uses them. Passage feature selection, passage composition, and boundary bands now run on the normal path, and passage-route validation cannot be waived by the old ablation flag.
|
||||||
|
- Removed the `VOXELFORGE_AUDIT_LEGACY_ROUTE_GRADE` block from `Standalone/Source/WorldAssemblyPrototype.h`. The source contained its only reference; no test, current tool, or report invoked it.
|
||||||
|
- Kept route-candidate grading and all user-visible behavior. This cleanup adds no evaluator version or baseline change.
|
||||||
|
|
||||||
|
## Switch and hook inventory
|
||||||
|
|
||||||
|
### Environment switches in compiled Core/Source
|
||||||
|
|
||||||
|
| Switch | Effect and consumer | Keep decision |
|
||||||
|
|---|---|---|
|
||||||
|
| `VOXELFORGE_L74_TIGHT_PROOF_CONTROL` | Proof negative control. `Linux74/FalsifierL74.py` and `Linux75/FalsifierL75.py`. | Keep for falsifier reproducibility; not a current fast-tier input. |
|
||||||
|
| `VOXELFORGE_L75_TN_BLOCK_REGRESSION` | Fixed TunnelNetwork regression path in Core and mesher. `RunTnBlockRegressionL75.py` and `FalsifierL75.py`. | Keep; the regression tools still consume it. |
|
||||||
|
| `VOXELFORGE_L98_PASSAGE_PREP_TRACE` | Emits preparation-stage timing/count data. `RunL98Hashes.py` and `RunL98ReuseCounts.py`. | Keep as a focused profiler for future preparation comparisons. |
|
||||||
|
| `VOXELFORGE_L98_PASSAGE_REUSE_PROBE` | Compares the prepared projection with direct scalar queries. `RunL98ReuseCounts.py`. | Keep for exactness probes. |
|
||||||
|
| `VOXELFORGE_L104_FAR_HIT_CACHE` | Selects indexed versus linear far-hit candidate lookup. `RunL104ReadinessPairs.py` and `RunL104ProbeStats.py`. | Keep for reproducible A/B comparisons; cache defaults on. |
|
||||||
|
| `VOXELFORGE_L104_FAR_HIT_STATS` | Emits far-hit candidate/query counters. `RunL104ProbeStats.py`. | Keep for the measurement tool. |
|
||||||
|
| `VOXELFORGE_L115_DENSITY_PROFILE` | Enables density and floor-query profiling. `RunL115DensityProbe.py`, `RunL119DensityProbe.py`, and `RunL125DensityProbe.py`. | Keep; these remain the focused floor-probe path. |
|
||||||
|
| `VOXELFORGE_L130_PASSAGE_REACH_PROOF_AUDIT` | Checks passage proof/feature influence bounds. L130's reach audit and report. | Keep for reach changes and audit reproduction. |
|
||||||
|
|
||||||
|
Archived runners also set `VOXELFORGE_L81_PASSAGE_BOUND_PADDING_VOXELS`, `VOXELFORGE_L86_PASSAGE_RESULT_CACHE`, `VOXELFORGE_L90_PASSAGE_BRICK_METRES`, `VOXELFORGE_L90_PASSAGE_CANDIDATE_CENSUS`, `VOXELFORGE_L90_PASSAGE_REACH_METRES`, `VOXELFORGE_L91_PASSAGE_SOURCE_FLOOR_VOXELS`, `VOXELFORGE_L93_PASSAGE_CARVE_REACH_METRES`, `VOXELFORGE_L98_PASSAGE_REUSE_COUNTS`, `VOXELFORGE_L114_DENSITY_PROFILE`, and `VOXELFORGE_L118_TAG_TIMING`. None has a compiled-source reader at `cbbfd46`; they are inert historical runner strings.
|
||||||
|
|
||||||
|
### Other experiments, diagnostics, and legacy paths retained
|
||||||
|
|
||||||
|
- **World-changing tunnel ablations:** all 14 `voxel.TunnelAblate*` controls remain (`CaveWarp`, `DetailOps`, `RoomSDF`, `TunnelSDF`, `TunnelCore`, `PassageCarving`, `PassageStructuralPosts`, `NativeFloor`, `Disturbances`, `OriginSpine`, `BoundarySeal`, `LandingPosts`, `XYEdgeSeal`, `PitChimneySDF`). The editor commandlet writes their resolved mask into export and result manifests; the archived `PERF-SAMPLED.md` and `WORK-NEXT.md` record their measurements. No current runner invokes an ablation. Keep for manifest attribution and historical reproduction; removing it needs a metadata migration. Source: [`VoxelDensityAblation.cpp`](../../../../Source/VoxelForge/Private/VoxelDensityAblation.cpp), [`VoxelForgeExploreCommandlet.cpp`](../../../../Source/VoxelForgeEditor/Private/VoxelForgeExploreCommandlet.cpp).
|
||||||
|
- **Research fields:** `voxel.ResearchRedefinedDensityField`, `voxel.ResearchRedefinedDensityDetailScale`, `voxel.ResearchParameterizedCave`, and `voxel.ResearchParameterizedCaveSet` are default-off and used by `Tools/VoxelForgeTest.ps1` steps 2d/2e/2f. The region-eval commandlet consumes `SetResearchBrickBinningEnabled`, `SetResearchBrickRoomReachScale`, and `SetResearchRegionCacheWindowEnabled`; keep these editor-only experiment paths. Source: [`VoxelForgeRegionEvalExperiment.cpp`](../../../../Source/VoxelForgeEditor/Private/VoxelForgeRegionEvalExperiment.cpp), [`VoxelForgeTest.ps1`](../../../../Tools/VoxelForgeTest.ps1).
|
||||||
|
- **Runtime profiling and trace:** `voxel.SampleStacks` still starts `FVoxelStackSampler` (the guarded `Tools/VoxelForgeTest.ps1 -SampleDensityStacks` path consumes it); `voxel.ProfileDensity`, `voxel.ProfileDensityFull`, `voxel.ProfileTileGeneration`, `voxel.ProfileCollisionCookStages`, and `voxel.PerfAttribution` remain opt-in. `voxel.StartupTraceFile`, `voxel.StartupTraceMaxTiles`, and `voxel.StartupTraceUntilEndPlay` feed the Unreal startup trace used by the arrival/movement runners. Keep. Build-time `VOXELFORGE_PROFILE_LEGACY_TERMS` (L76) and `VOXELFORGE_PROFILE_L77`/`--linux77-profile` (stack sampler and route census) remain in `Standalone/BuildLinux.sh` and Core.
|
||||||
|
- **Standalone profiles and timelines:** retained `--profile-column-overlap`, `--profile-lod-work`, `--profile-passage-composer`, `--instrument-tile-drain`, `--cold-worker-timeline`, `--linux77-profile`, `--tls-probe=N`, `--tls-probe-touch=...`, and `--diagnostic-slow-shape-compile-ms=N`. The viewer's `--profile-attribution`, `--profile-detail-band`, and `--profile-far-column-overlap` remain. The L77 profiler, tile drain instrumentation, timelines, and TLS probe are measurement hooks; archived reports and runners still provide reproducible consumers.
|
||||||
|
- **Standalone audits:** all source-advertised hooks remain: `--audit-ore-vein-yield`, `--audit-resolved-layout-boundaries`, `--audit-strate-transitions`, `--audit-resolved-layout-passages`, `--audit-heightfield-profile`, `--audit-motif-intervals`, `--audit-landmark-reachability`, `--audit-native-caves`, `--audit-native-lattice`, `--audit-surface-clearance`, `--audit-uniform-block-proofs`, `--audit-base-page-equivalence`, `--audit-route-parity`, `--audit-passage-tile-seams`, `--audit-passage-source-clamp`, `--audit-passage-carve-reach`, `--audit-tile-shape-readiness`, and the mesher's `--audit-raw-skirts`. `verify.py fast` consumes the current route, passage, block-proof, transition, native-field and negative-control subset; dedicated L37/L75/L125/L130 runners exercise the specialized audits. Keep the whole audit set.
|
||||||
|
- **Evaluator A/B controls:** `voxel.FastIsFinite`, `voxel.UseFusedEvaluator`, `voxel.WormBlockSkip`, `voxel.TileCacheWindow` / its two minimum-LOD controls, `voxel.SpatialIndex`, `voxel.ChunkRoutingCache`, `voxel.UseOperatorBlock`, `voxel.CoreColumnCacheDirectMapped`, `voxel.CoreMCGradientMemoization`, `voxel.FloorRound1PassageProjectionCache`, `voxel.PlayerFitMemo`, `voxel.UseBlockEarlyOut`, `voxel.OuterClassifierMode`, and `voxel.SealedSolidProof` remain. They select optimized or comparison paths; the density block equivalence test explicitly forces `UseFusedEvaluator=0`, while most others are production defaults or historical measurement controls. `voxel.WormsForceOff` is a world-changing development measurement override. Kept; no current L131 gate changes them.
|
||||||
|
- **Standalone A/B and geometry controls:** `--exact-midpoint-density-memo`, `--no-exact-midpoint-density-memo`, `--active-lane-batching`, `--proof-block-cells=N`, `--parallel-sign-edge-repair`, `--serial-sign-edge-repair`, and `--shape-helper-limit=8|12` remain. The L94 report documents serial edge repair; no current `verify.py` consumer was found for the other CLI A/B controls, so they remain pending a separately reviewed removal. `voxel.TilePostReachDebug`, `voxel.TilePostReachScale`, and `voxel.TileReachCostDiagnostics` remain for the tile-post-reach test; `voxel.TunnelMouthTrim` remains a development-only room-mouth geometry control. No L131 gate uses these.
|
||||||
|
- `FLegacyGeneratorFieldAdapter` remains the Core fallback for unsupported generator/recipe combinations, and Unreal's Core switch remains default-off. `voxel.StreamingLegacyPendingResultCap=1` remains the L120–L123 admission negative control; `voxel.StreamingCoarseFirst` remains opt-in pending a rendered owner-plan check. `bStandaloneResearchRoundTunnels` and `bStandaloneResearchEnhancedWalls` remain consumed by the standalone viewer/Core adapter.
|
||||||
|
|
||||||
|
## Checks
|
||||||
|
|
||||||
|
- Clang 19 and GCC standalone builds passed with the L131 source stamp `5119cee164406856cbca496d160c0e0a8124ae2529fa7c0ebd51634a7c65a6cb`. `Standalone/BuildLinux.sh` applied the required CPU and address-space limits.
|
||||||
|
- L80 timing: one warm-up per binary and five interleaved pairs in each of four strata × W8/W12 cells, comparing the pre-cleanup L130 binary with L131. Load was 0.81; CPU idle was 99.2%. Across 40 pairs per metric, mean relative change was −0.22% near-ready (95% CI −1.02% to +0.57%) and −0.29% whole-view (−1.04% to +0.46%); the intervals include zero. [Raw timing summary](../../../../Saved/Linux/l131/timing/summary.json).
|
||||||
|
- Exact hashes: **24/24** owner4 SW/FI/TN/VS × Clang/GCC × W1/W8/W12 tile and whole-view identities; **18/18** canonical cases across owner4 SurfaceWorld and owner2 SurfaceWorld/FloatingIslands. All match the pre-cleanup L130 binary and agree across compiler/worker combinations. For transparency, forcing the owner4 dataset through `--recipe=floating-islands` exited during setup with “could not find a finite SurfaceWorld strate”, before hashing; it is not a valid canonical case. [Tile matrix](../../../../Saved/Linux/l131/hash-matrix/summary.json), [canonical matrix](../../../../Saved/Linux/l131/canonical-matrix/summary.json).
|
||||||
|
- Walkability: **21,425/21,425** passage centerline samples open. Seam audit: **4 pairs / 4,900** shared samples, zero mismatches. [Audit log](../../../../Saved/Linux/l131/seam-audit.log).
|
||||||
|
- Fast tier: **PASS**, 259 gated checks plus 5 diagnostics, 80 runs, 371.0 s. The five diagnostic-only comparisons are historical baselines; all required checks pass. [Summary](../../../../Saved/Linux/l131/fast-summary.json).
|
||||||
|
- Linux `VFHostEditor`: **PASS**, 27/27 actions, 78.81 s with `-NoUBA -MaxParallelActions=4`, no `prlimit`. UBT's default log rotation first failed before compilation in the read-only user config directory; the successful rerun set `-Log=.../Saved/Linux/l131/ubt.log`. Three existing RealtimeMesh deprecation warnings remain. [Build log](../../../../Saved/Linux/l131/ue-build.log).
|
||||||
|
- Unreal `Source/` files changed: **none**. No Windows compile is requested by this diff; Windows determinism remains unverified.
|
||||||
|
- `git diff --check` passes. No commit, push, or stash was made.
|
||||||
|
|
||||||
|
Builds, per-run logs, timing records, hash records, and audit output are under `Saved/Linux/l131/`.
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Compare 18 canonical owner4/owner2 hashes with the pre-cleanup L130 binary."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[4]
|
||||||
|
OUT = ROOT / "Saved/Linux/l131/canonical-matrix"
|
||||||
|
DATASETS = {
|
||||||
|
"owner4": ROOT / "Standalone/data/owner_world.json",
|
||||||
|
"owner2": ROOT / "Standalone/data/regression/owner_world_2strate_l61.json",
|
||||||
|
}
|
||||||
|
RECIPES = {"owner4": ("surface-world",), "owner2": ("surface-world", "floating-islands")}
|
||||||
|
BINARIES = {
|
||||||
|
"base": ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-{compiler}",
|
||||||
|
"l131": ROOT / "Saved/Linux/l131/bin/VoxelForgeCoreHeadless-l131-{compiler}",
|
||||||
|
}
|
||||||
|
HASH_RE = re.compile(r"^\[Pipeline(?:FullDetailHash|WholeViewHash|LODHash|ExactQueryHash)\].*$", re.M)
|
||||||
|
|
||||||
|
|
||||||
|
def run(dataset: str, recipe: str, compiler: str, workers: int, version: str) -> tuple[list[str], float]:
|
||||||
|
binary = Path(str(BINARIES[version]).format(compiler=compiler))
|
||||||
|
label = f"{dataset}-{recipe}-{compiler}-w{workers}-{version}"
|
||||||
|
log = OUT / f"{label}.log"
|
||||||
|
command = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||||
|
"timeout", "1740s", str(binary), str(DATASETS[dataset]),
|
||||||
|
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||||
|
"--force-generate", f"--workers={workers}", "--clip-radius=3",
|
||||||
|
"--max-clip-level=8", "--max-level=8", f"--recipe={recipe}", "--stream-hash"]
|
||||||
|
started = time.monotonic()
|
||||||
|
with log.open("w", encoding="utf-8") as stream:
|
||||||
|
process = subprocess.run(command, cwd=ROOT, stdout=stream,
|
||||||
|
stderr=subprocess.STDOUT, check=False, timeout=1740)
|
||||||
|
hashes = HASH_RE.findall(log.read_text(encoding="utf-8", errors="replace"))
|
||||||
|
if process.returncode or len(hashes) != 12:
|
||||||
|
raise RuntimeError(f"hash run failed: {log}; exit={process.returncode}; rows={len(hashes)}")
|
||||||
|
return hashes, time.monotonic() - started
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
|
rows = []
|
||||||
|
groups = {}
|
||||||
|
for dataset, recipes in RECIPES.items():
|
||||||
|
for recipe in recipes:
|
||||||
|
signatures = []
|
||||||
|
for workers in (1, 8, 12):
|
||||||
|
for compiler in ("clang", "gcc"):
|
||||||
|
before, before_s = run(dataset, recipe, compiler, workers, "base")
|
||||||
|
after, after_s = run(dataset, recipe, compiler, workers, "l131")
|
||||||
|
row = {"dataset": dataset, "recipe": recipe, "compiler": compiler,
|
||||||
|
"workers": workers, "hash_mismatches": sum(a != b for a, b in zip(before, after)),
|
||||||
|
"rows": len(after), "base_s": round(before_s, 3), "l131_s": round(after_s, 3),
|
||||||
|
"base_log": f"Saved/Linux/l131/canonical-matrix/{dataset}-{recipe}-{compiler}-w{workers}-base.log",
|
||||||
|
"l131_log": f"Saved/Linux/l131/canonical-matrix/{dataset}-{recipe}-{compiler}-w{workers}-l131.log"}
|
||||||
|
rows.append(row)
|
||||||
|
signatures.append((compiler, workers, after))
|
||||||
|
print("[L131CanonicalHash] " + json.dumps(row, sort_keys=True), flush=True)
|
||||||
|
(OUT / "runs-partial.json").write_text(json.dumps(rows, indent=2) + "\n")
|
||||||
|
first = signatures[0][2]
|
||||||
|
stable = all(sig == first for _, _, sig in signatures)
|
||||||
|
groups[f"{dataset}/{recipe}"] = {"base_equals_l131": all(row["hash_mismatches"] == 0 for row in rows if row["dataset"] == dataset and row["recipe"] == recipe),
|
||||||
|
"all_clang_gcc_workers_agree": stable}
|
||||||
|
failures = [row for row in rows if row["hash_mismatches"]]
|
||||||
|
(OUT / "summary.json").write_text(json.dumps({"runs": rows, "groups": groups,
|
||||||
|
"passed": len(rows)-len(failures), "failed": len(failures)}, indent=2) + "\n")
|
||||||
|
return 1 if failures or not all(group["all_clang_gcc_workers_agree"] for group in groups.values()) else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Compare 24 owner4 tile-hash cases with the pre-cleanup L130 binary."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[4]
|
||||||
|
OUT = ROOT / "Saved/Linux/l131/hash-matrix"
|
||||||
|
DATA = ROOT / "Standalone/data/owner_world.json"
|
||||||
|
BINARIES = {
|
||||||
|
"base": ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-{compiler}",
|
||||||
|
"l131": ROOT / "Saved/Linux/l131/bin/VoxelForgeCoreHeadless-l131-{compiler}",
|
||||||
|
}
|
||||||
|
CAMERAS = {
|
||||||
|
"sw": ((8.0, 16.0, -372.2626953125), 2850),
|
||||||
|
"fi": ((25.8369140625, 3.19921875, -737.0), 2249),
|
||||||
|
"tn": ((19.166015625, -14.2001953125, -753.3740234375), 2233),
|
||||||
|
"vs": ((-20.0625, -5.068359375, -900.353515625), 2329),
|
||||||
|
}
|
||||||
|
TILE_RE = re.compile(
|
||||||
|
r"^\[PipelineTileHash\] lod=(-?\d+) x=(-?\d+) y=(-?\d+) z=(-?\d+) "
|
||||||
|
r"density=(0x[0-9a-f]+) mesh=(0x[0-9a-f]+) payload=(0x[0-9a-f]+) "
|
||||||
|
r"topology=(0x[0-9a-f]+)$", re.M)
|
||||||
|
WHOLE_RE = re.compile(
|
||||||
|
r"^\[PipelineWholeViewHash\] tiles=(\d+) density=(0x[0-9a-f]+) "
|
||||||
|
r"mesh=(0x[0-9a-f]+) payload=(0x[0-9a-f]+) topology=(0x[0-9a-f]+)$", re.M)
|
||||||
|
|
||||||
|
|
||||||
|
def capture(camera_name: str, compiler: str, workers: int, version: str) -> tuple[dict, tuple[str, ...], float]:
|
||||||
|
camera, expected_tiles = CAMERAS[camera_name]
|
||||||
|
camera_arg = ",".join(f"{value:.12f}" for value in camera) + ",0,0"
|
||||||
|
binary = Path(str(BINARIES[version]).format(compiler=compiler))
|
||||||
|
log = OUT / f"owner4-{camera_name}-{compiler}-w{workers}-{version}.log"
|
||||||
|
command = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||||
|
"timeout", "1740s", str(binary), str(DATA), "--world-assembler-prototype",
|
||||||
|
"--stream-benchmark", "--stream-pipeline", f"--workers={workers}",
|
||||||
|
"--clip-radius=3", "--max-clip-level=8", "--max-level=8",
|
||||||
|
f"--camera={camera_arg}", "--stream-hash-tiles"]
|
||||||
|
started = time.monotonic()
|
||||||
|
with log.open("w", encoding="utf-8") as stream:
|
||||||
|
result = subprocess.run(command, cwd=ROOT, stdout=stream,
|
||||||
|
stderr=subprocess.STDOUT, check=False, timeout=1740)
|
||||||
|
elapsed = time.monotonic() - started
|
||||||
|
output = log.read_text(encoding="utf-8", errors="replace")
|
||||||
|
tiles = {(int(match.group(1)), int(match.group(2)), int(match.group(3)), int(match.group(4))):
|
||||||
|
match.group(5, 6, 7, 8) for match in TILE_RE.finditer(output)}
|
||||||
|
whole = WHOLE_RE.search(output)
|
||||||
|
if result.returncode or whole is None or len(tiles) != expected_tiles or len(tiles) != int(whole.group(1)):
|
||||||
|
raise RuntimeError(f"incomplete {version} {camera_name}/{compiler}/W{workers}: {log}")
|
||||||
|
return tiles, whole.groups(), elapsed
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
|
rows = []
|
||||||
|
for camera_name in CAMERAS:
|
||||||
|
for compiler in ("clang", "gcc"):
|
||||||
|
for workers in (1, 8, 12):
|
||||||
|
old_tiles, old_whole, old_s = capture(camera_name, compiler, workers, "base")
|
||||||
|
new_tiles, new_whole, new_s = capture(camera_name, compiler, workers, "l131")
|
||||||
|
keys = set(old_tiles) | set(new_tiles)
|
||||||
|
tile_mismatches = sum(old_tiles.get(key) != new_tiles.get(key) for key in keys)
|
||||||
|
row = {"owner": "owner4", "camera": camera_name, "compiler": compiler,
|
||||||
|
"workers": workers, "tiles": len(new_tiles),
|
||||||
|
"tile_mismatches": tile_mismatches,
|
||||||
|
"whole_view_match": old_whole == new_whole,
|
||||||
|
"base_s": round(old_s, 3), "l131_s": round(new_s, 3),
|
||||||
|
"base_log": f"Saved/Linux/l131/hash-matrix/owner4-{camera_name}-{compiler}-w{workers}-base.log",
|
||||||
|
"l131_log": f"Saved/Linux/l131/hash-matrix/owner4-{camera_name}-{compiler}-w{workers}-l131.log"}
|
||||||
|
rows.append(row)
|
||||||
|
print("[L131HashIdentity] " + json.dumps(row, sort_keys=True), flush=True)
|
||||||
|
(OUT / "runs-partial.json").write_text(json.dumps(rows, indent=2) + "\n")
|
||||||
|
failures = [row for row in rows if row["tile_mismatches"] or not row["whole_view_match"]]
|
||||||
|
(OUT / "summary.json").write_text(json.dumps({"runs": rows, "passed": len(rows)-len(failures),
|
||||||
|
"failed": len(failures)}, indent=2) + "\n")
|
||||||
|
return 1 if failures else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Five interleaved L80 readiness measurements per stratum and worker count."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import statistics
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[4]
|
||||||
|
OUT = ROOT / "Saved/Linux/l131/timing"
|
||||||
|
DATA = ROOT / "Standalone/data/owner_world.json"
|
||||||
|
BINARIES = {
|
||||||
|
"base": ROOT / "Saved/Linux/l130/bin/VoxelForgeCoreHeadless-l130-clang",
|
||||||
|
"l131": ROOT / "Saved/Linux/l131/bin/VoxelForgeCoreHeadless-l131-clang",
|
||||||
|
}
|
||||||
|
CAMERAS = {
|
||||||
|
0: (8.0, 16.0, -372.2626953125),
|
||||||
|
1: (25.8369140625, 3.19921875, -737.0),
|
||||||
|
2: (19.166015625, -14.2001953125, -753.3740234375),
|
||||||
|
3: (-20.0625, -5.068359375, -900.353515625),
|
||||||
|
}
|
||||||
|
PIPELINE_RE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M)
|
||||||
|
FIELDS_RE = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)")
|
||||||
|
NEAR_RE = re.compile(r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) cold_ready_s=([0-9.]+)$", re.M)
|
||||||
|
|
||||||
|
|
||||||
|
def run(strate: int, workers: int, version: str, phase: str, replicate: int) -> dict:
|
||||||
|
camera = ",".join(f"{value:.12f}" for value in CAMERAS[strate]) + ",0,0"
|
||||||
|
label = f"s{strate}-w{workers}-{version}-{phase}{replicate}-l131-v227"
|
||||||
|
log = OUT / f"{label}.log"
|
||||||
|
command = ["taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--",
|
||||||
|
"timeout", "1740s", str(BINARIES[version]), str(DATA),
|
||||||
|
"--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline",
|
||||||
|
f"--workers={workers}", "--clip-radius=3", "--max-clip-level=8",
|
||||||
|
"--max-level=8", f"--camera={camera}", "--profile-lod-work",
|
||||||
|
"--stream-scheduler-policy=3"]
|
||||||
|
started = time.monotonic()
|
||||||
|
with log.open("w", encoding="utf-8") as output:
|
||||||
|
result = subprocess.run(command, cwd=ROOT, stdout=output,
|
||||||
|
stderr=subprocess.STDOUT, check=False, timeout=1740)
|
||||||
|
content = log.read_text(encoding="utf-8", errors="replace")
|
||||||
|
pipeline, near = PIPELINE_RE.search(content), NEAR_RE.search(content)
|
||||||
|
if result.returncode or pipeline is None or near is None:
|
||||||
|
raise RuntimeError(f"timing run failed: {log}; exit={result.returncode}")
|
||||||
|
fields = dict(FIELDS_RE.findall(pipeline.group(1)))
|
||||||
|
row = {"strate": strate, "workers": workers, "version": version,
|
||||||
|
"phase": phase, "replicate": replicate,
|
||||||
|
"lod02_ready_s": float(near.group(3)),
|
||||||
|
"whole_view_ready_s": float(fields["whole_view_ready"].removesuffix("s")),
|
||||||
|
"wall_s": round(time.monotonic() - started, 3),
|
||||||
|
"log": str(log.relative_to(ROOT))}
|
||||||
|
print("[L131TimingRun] " + json.dumps(row, sort_keys=True), flush=True)
|
||||||
|
return row
|
||||||
|
|
||||||
|
|
||||||
|
def quiet_machine() -> tuple[float, float]:
|
||||||
|
load_1m = os.getloadavg()[0]
|
||||||
|
def totals() -> tuple[int, int]:
|
||||||
|
fields = Path("/proc/stat").read_text().splitlines()[0].split()
|
||||||
|
values = [int(value) for value in fields[1:]]
|
||||||
|
return sum(values), values[3] + (values[4] if len(values) > 4 else 0)
|
||||||
|
before = totals()
|
||||||
|
time.sleep(2.0)
|
||||||
|
after = totals()
|
||||||
|
idle = 100.0 * (after[1] - before[1]) / max(1, after[0] - before[0])
|
||||||
|
return load_1m, idle
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if any(not path.is_file() for path in (DATA, *BINARIES.values())):
|
||||||
|
raise SystemExit("missing timing input")
|
||||||
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
|
load_1m, idle = quiet_machine()
|
||||||
|
(OUT / "machine-load-before.txt").write_text(
|
||||||
|
f"1-minute load: {load_1m:.2f}\n2-second CPU idle: {idle:.1f}%\n")
|
||||||
|
print(f"[L131TimingGate] load_1m={load_1m:.2f} cpu_idle_2s={idle:.1f}%", flush=True)
|
||||||
|
if load_1m >= 0.9 or idle < 97.0:
|
||||||
|
raise SystemExit("timing refused: machine is above the L80 quiet-load gate")
|
||||||
|
|
||||||
|
rows = []
|
||||||
|
for strate in range(4):
|
||||||
|
for workers in (8, 12):
|
||||||
|
for version in BINARIES:
|
||||||
|
rows.append(run(strate, workers, version, "warmup", 0))
|
||||||
|
for replicate in range(1, 6):
|
||||||
|
order = tuple(BINARIES) if replicate % 2 else tuple(reversed(BINARIES))
|
||||||
|
for version in order:
|
||||||
|
rows.append(run(strate, workers, version, "measured", replicate))
|
||||||
|
(OUT / "runs-partial.json").write_text(json.dumps(rows, indent=2) + "\n")
|
||||||
|
|
||||||
|
measured = [row for row in rows if row["phase"] == "measured"]
|
||||||
|
summary = []
|
||||||
|
for strate in range(4):
|
||||||
|
for workers in (8, 12):
|
||||||
|
old = [row for row in measured if row["strate"] == strate and row["workers"] == workers and row["version"] == "base"]
|
||||||
|
new = [row for row in measured if row["strate"] == strate and row["workers"] == workers and row["version"] == "l131"]
|
||||||
|
item = {"strate": strate, "workers": workers, "replicates_per_version": 5}
|
||||||
|
for key in ("lod02_ready_s", "whole_view_ready_s"):
|
||||||
|
old_med, new_med = statistics.median(row[key] for row in old), statistics.median(row[key] for row in new)
|
||||||
|
item[f"base_{key}_median"] = old_med
|
||||||
|
item[f"l131_{key}_median"] = new_med
|
||||||
|
item[f"delta_pct_{key}"] = round(100.0 * (new_med / old_med - 1.0), 2)
|
||||||
|
item[f"base_{key}_values"] = [row[key] for row in old]
|
||||||
|
item[f"l131_{key}_values"] = [row[key] for row in new]
|
||||||
|
summary.append(item)
|
||||||
|
(OUT / "summary.json").write_text(json.dumps({"runs": rows, "summary": summary}, indent=2) + "\n")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
@@ -2566,15 +2566,9 @@ namespace StandaloneStreamBenchmark
|
|||||||
ShapeRequest.detail=DetailVariant;ShapeRequest.includeFarWorld=bIncludeFarWorld&&!bDeferFarWorld;
|
ShapeRequest.detail=DetailVariant;ShapeRequest.includeFarWorld=bIncludeFarWorld&&!bDeferFarWorld;
|
||||||
ShapeRequest.roundTunnels=bRoundTunnels;
|
ShapeRequest.roundTunnels=bRoundTunnels;
|
||||||
ShapeRequest.enhancedTunnelWalls=bEnhancedTunnelWalls;
|
ShapeRequest.enhancedTunnelWalls=bEnhancedTunnelWalls;
|
||||||
const char* L86DisablePassages=std::getenv(
|
ShapeRequest.validatePassageRoutes=!bCaptureSkipWalkability;
|
||||||
"VOXELFORGE_L86_DISABLE_PASSAGE_COMPOSITION");
|
|
||||||
const bool bL86DisablePassages=L86DisablePassages
|
|
||||||
&&L86DisablePassages[0]=='1'&&L86DisablePassages[1]=='\0';
|
|
||||||
ShapeRequest.validatePassageRoutes=!bCaptureSkipWalkability&&!bL86DisablePassages;
|
|
||||||
if(bCaptureSkipWalkability)
|
if(bCaptureSkipWalkability)
|
||||||
std::printf("[CaptureWalkabilityGate] validation=deferred geometry_input=unchanged mode=mesh-export\n");
|
std::printf("[CaptureWalkabilityGate] validation=deferred geometry_input=unchanged mode=mesh-export\n");
|
||||||
if(bL86DisablePassages)
|
|
||||||
std::printf("[L86PassageCeiling] validation=skipped geometry=passage_composition_disabled diagnostic_only=true\n");
|
|
||||||
FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
|
FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
|
||||||
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileColumnOverlap,
|
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileColumnOverlap,
|
||||||
FarHorizonLOD8InteriorStepVoxels,bUseSharedColumnCache,
|
FarHorizonLOD8InteriorStepVoxels,bUseSharedColumnCache,
|
||||||
|
|||||||
@@ -153,80 +153,6 @@ namespace StandaloneWorldAssemblyPrototype
|
|||||||
candidateCenterSpacing=32;
|
candidateCenterSpacing=32;
|
||||||
}
|
}
|
||||||
const double coreVoxelMetres=static_cast<double>(coreVoxelSizeMicrons)/1000000.0;
|
const double coreVoxelMetres=static_cast<double>(coreVoxelSizeMicrons)/1000000.0;
|
||||||
if(std::getenv("VOXELFORGE_AUDIT_LEGACY_ROUTE_GRADE"))
|
|
||||||
{
|
|
||||||
constexpr std::int32_t legacyCenterSpacing=64;
|
|
||||||
constexpr std::int32_t legacyWaypointSpacing=8;
|
|
||||||
std::array<GradeSegmentAudit,32> legacySegments{};
|
|
||||||
std::uint64_t legacyGradeFailCandidates=0;
|
|
||||||
double legacyMinimumGround=std::numeric_limits<double>::infinity();
|
|
||||||
double legacyMaximumGround=-std::numeric_limits<double>::infinity();
|
|
||||||
for(std::int32_t centerY=-256;centerY<=256;centerY+=legacyCenterSpacing)
|
|
||||||
for(std::int32_t centerX=-256;centerX<=256;centerX+=legacyCenterSpacing)
|
|
||||||
for(const Direction& direction:directions)
|
|
||||||
{
|
|
||||||
bool candidateGradeFail=false;
|
|
||||||
std::int64_t previousGround=0,previousX=0,previousY=0;
|
|
||||||
for(std::int32_t index=0;index<=32;++index)
|
|
||||||
{
|
|
||||||
const std::int64_t along=(index-16)*legacyWaypointSpacing;
|
|
||||||
const std::int64_t x=centerX+std::llround(
|
|
||||||
static_cast<double>(along)*direction.x/65536.0);
|
|
||||||
const std::int64_t y=centerY+std::llround(
|
|
||||||
static_cast<double>(along)*direction.y/65536.0);
|
|
||||||
const auto column=finalField.point(WorldAssemblyFixed(static_cast<double>(x)),
|
|
||||||
WorldAssemblyFixed(static_cast<double>(y)),0);
|
|
||||||
const double groundMetres=static_cast<double>(column.groundHeightSubvoxels)
|
|
||||||
*coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel;
|
|
||||||
legacyMinimumGround=std::min(legacyMinimumGround,groundMetres);
|
|
||||||
legacyMaximumGround=std::max(legacyMaximumGround,groundMetres);
|
|
||||||
if(index>0)
|
|
||||||
{
|
|
||||||
const std::int64_t horizontalQ=static_cast<std::int64_t>(std::llround(
|
|
||||||
std::hypot(static_cast<double>(x-previousX),
|
|
||||||
static_cast<double>(y-previousY))*WorldAssemblySubvoxelsPerVoxel));
|
|
||||||
const std::int64_t riseQ=std::abs(
|
|
||||||
column.groundHeightSubvoxels-previousGround);
|
|
||||||
if(horizontalQ==0||riseQ*65536>horizontalQ*GradeQ16)
|
|
||||||
{
|
|
||||||
candidateGradeFail=true;
|
|
||||||
GradeSegmentAudit& segment=legacySegments[
|
|
||||||
static_cast<std::size_t>(index-1)];
|
|
||||||
++segment.failures;
|
|
||||||
const double grade=horizontalQ>0
|
|
||||||
?static_cast<double>(riseQ)/static_cast<double>(horizontalQ)
|
|
||||||
:std::numeric_limits<double>::infinity();
|
|
||||||
if(grade>segment.maximumGrade)
|
|
||||||
{
|
|
||||||
segment.maximumGrade=grade;
|
|
||||||
segment.fromGround=previousGround;
|
|
||||||
segment.toGround=column.groundHeightSubvoxels;
|
|
||||||
segment.fromX=previousX;segment.fromY=previousY;
|
|
||||||
segment.toX=x;segment.toY=y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
previousGround=column.groundHeightSubvoxels;previousX=x;previousY=y;
|
|
||||||
}
|
|
||||||
if(candidateGradeFail)++legacyGradeFailCandidates;
|
|
||||||
}
|
|
||||||
std::printf("[WorldAssemblerLegacyRouteGradeProfile] candidates=648 grade_fail_candidates=%llu ground_range_m=%.3f..%.3f grade_limit_deg=15.000 chord_m=%.3f waypoint_step_m=%.3f center_step_m=%.3f\n",
|
|
||||||
static_cast<unsigned long long>(legacyGradeFailCandidates),
|
|
||||||
legacyMinimumGround,legacyMaximumGround,256.0*coreVoxelMetres,
|
|
||||||
legacyWaypointSpacing*coreVoxelMetres,legacyCenterSpacing*coreVoxelMetres);
|
|
||||||
const double metresPerSubvoxel=coreVoxelMetres/WorldAssemblySubvoxelsPerVoxel;
|
|
||||||
for(std::size_t segmentIndex=0;segmentIndex<legacySegments.size();++segmentIndex)
|
|
||||||
{
|
|
||||||
const GradeSegmentAudit& segment=legacySegments[segmentIndex];
|
|
||||||
if(segment.failures==0)continue;
|
|
||||||
std::printf("[WorldAssemblerLegacyRouteGradeSegment] index=%zu rejected_candidates=%llu max_grade_deg=%.3f ground_m=%.3f->%.3f xy_m=(%.3f,%.3f)->(%.3f,%.3f)\n",
|
|
||||||
segmentIndex,static_cast<unsigned long long>(segment.failures),
|
|
||||||
std::atan(segment.maximumGrade)*57.29577951308232,
|
|
||||||
segment.fromGround*metresPerSubvoxel,segment.toGround*metresPerSubvoxel,
|
|
||||||
segment.fromX*coreVoxelMetres,segment.fromY*coreVoxelMetres,
|
|
||||||
segment.toX*coreVoxelMetres,segment.toY*coreVoxelMetres);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::printf("[WorldAssemblerRouteCandidateEnvelope] max_chord_m=%.3f length_variants=%zu center_step_m=%.3f arrival_radius_m=%.3f departure_radius_m=%.3f\n",
|
std::printf("[WorldAssemblerRouteCandidateEnvelope] max_chord_m=%.3f length_variants=%zu center_step_m=%.3f arrival_radius_m=%.3f departure_radius_m=%.3f\n",
|
||||||
2.0*candidateHalfLengths.front()*coreVoxelMetres,candidateHalfLengths.size(),
|
2.0*candidateHalfLengths.front()*coreVoxelMetres,candidateHalfLengths.size(),
|
||||||
candidateCenterSpacing*coreVoxelMetres,
|
candidateCenterSpacing*coreVoxelMetres,
|
||||||
|
|||||||
Reference in new issue
Block a user