Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebae71b142 | ||
|
|
81071969fc | ||
|
|
cbbfd46bd3 |
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
|
||||
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
|
||||
12 visible mesh submissions / 14 ms while the initial desired set and walkable ring are incomplete,
|
||||
with a 30 second ceiling; at `0`, the authored budget is unchanged. On the matched legacy-order test,
|
||||
the boost changed full-set readiness from 17.412 s to 17.346 s and removed count-cap frames, but did
|
||||
not improve end-to-end residency. Keep the normal 4 / 2 ms guard for play.
|
||||
The separate `voxel.StreamingStartupApplyBoost` switch is default-on in the current code. At `1`, it
|
||||
temporarily allows up to 24 visible mesh submissions / 14 ms while the initial desired set and
|
||||
walkable ring are incomplete, with a 30 second ceiling; at `0`, the authored budget is unchanged.
|
||||
The historical matched S6 run changed full-set readiness from 17.412 s to 17.346 s and removed
|
||||
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
|
||||
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
|
||||
`PendingTiles` accounting; the test harness's `NearReserveMode=Legacy` also sets
|
||||
`voxel.StreamingDynamicNearReserve=0`, reproducing the S6 path. `StreamingDynamicNearReserve` now
|
||||
defaults to `1`; `StreamingCoarseFirst` remains `0`, and the apply boost remains `0` in the matched
|
||||
measurement.
|
||||
defaults to `1`; `StreamingCoarseFirst` remains `0`. That historical S6 matched measurement disabled
|
||||
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,
|
||||
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.
|
||||
|
||||
## 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`
|
||||
index (§3), "I want to change X → go here" (§5), conventions & gotchas (§6). Trust **symbol names
|
||||
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. |
|
||||
| `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. |
|
||||
| `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). |
|
||||
| `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). |
|
||||
@@ -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`. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
| `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. |
|
||||
|
||||
@@ -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 <vector>
|
||||
|
||||
// L88-only composition split. These switches let the timing harness remove passage work and
|
||||
// resolved boundary-band work independently. They are diagnostic only, never world settings.
|
||||
static bool VF_IsL88DiagnosticSwitchEnabled(const char* Name)
|
||||
static bool VF_IsDiagnosticEnvSwitchEnabled(const char* Name)
|
||||
{
|
||||
const char* Value=std::getenv(Name);
|
||||
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 const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled(
|
||||
static const bool bEnabled=VF_IsDiagnosticEnvSwitchEnabled(
|
||||
"VOXELFORGE_L98_PASSAGE_PREP_TRACE");
|
||||
return bEnabled;
|
||||
}
|
||||
|
||||
static bool VF_IsL130PassageReachProofAuditEnabled()
|
||||
{
|
||||
static const bool bEnabled=VF_IsL88DiagnosticSwitchEnabled(
|
||||
static const bool bEnabled=VF_IsDiagnosticEnvSwitchEnabled(
|
||||
"VOXELFORGE_L130_PASSAGE_REACH_PROOF_AUDIT");
|
||||
return bEnabled;
|
||||
}
|
||||
@@ -327,18 +301,14 @@ public:
|
||||
{
|
||||
mayContainResolvedBoundaryBand_=shape.ResolvedBoundaryBandsIntersectSubvoxelRange(
|
||||
minimumSubvoxels_[2],maximumSubvoxels_[2]);
|
||||
const bool disablePassageComposition=VF_IsL88PassageCompositionDisabled();
|
||||
if(VF_IsL88BoundaryBandsDisabled())mayContainResolvedBoundaryBand_=false;
|
||||
mayContainTransitionPassageFade_=!disablePassageComposition
|
||||
&&shape.ResolvedTransitionPassageFadeIntersectsTileXY(
|
||||
minimumSubvoxels_,maximumSubvoxels_);
|
||||
if(!disablePassageComposition)
|
||||
featureIndices_=shape.BuildPassageFeatureTileList(
|
||||
minimumSubvoxels_,maximumSubvoxels_);
|
||||
mayContainTransitionPassageFade_=shape.ResolvedTransitionPassageFadeIntersectsTileXY(
|
||||
minimumSubvoxels_,maximumSubvoxels_);
|
||||
featureIndices_=shape.BuildPassageFeatureTileList(
|
||||
minimumSubvoxels_,maximumSubvoxels_);
|
||||
stampIndices_=shape.BuildStampTileList(minimumSubvoxels_,maximumSubvoxels_);
|
||||
cavernFeatureIndices_=shape.BuildCavernFeatureTileList(
|
||||
minimumSubvoxels_,maximumSubvoxels_);
|
||||
passageRoutes_.assign(shape.ResolvedLayout&&!disablePassageComposition
|
||||
passageRoutes_.assign(shape.ResolvedLayout
|
||||
?shape.ResolvedLayout->passages.size():0,0);
|
||||
passageRouteSegments_.resize(passageRoutes_.size());
|
||||
for(const std::uint32_t featureIndex:featureIndices_)
|
||||
@@ -1561,12 +1531,8 @@ public:
|
||||
// the generic stratum transition distance creates a discontinuity at a
|
||||
// mouth that crosses a wide transition band. Keep that opt-in field whole;
|
||||
// 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;
|
||||
if(!nativeLattice&&!disableBoundaryBands)
|
||||
if(!nativeLattice)
|
||||
{
|
||||
VoxelForgeCore::Linux77Profiler::FScopedPhase l77BandsPhase(
|
||||
VoxelForgeCore::Linux77Profiler::EPhase::Bands);
|
||||
@@ -1595,7 +1561,6 @@ public:
|
||||
?bound->Resolved->passageCapabilities.hasNativeCaveField
|
||||
:bound->Resolved->passageCapabilities.hasNativeLatticeField))
|
||||
{
|
||||
if(!disablePassageComposition)
|
||||
{
|
||||
VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase(
|
||||
VoxelForgeCore::Linux77Profiler::EPhase::Passage);
|
||||
@@ -1626,7 +1591,6 @@ public:
|
||||
ELegacyFieldTerm::ComposerPassage);
|
||||
final=ApplyResolvedCavernFloorCaps(stamped,X,Y,Z);
|
||||
}
|
||||
if(!disablePassageComposition)
|
||||
{
|
||||
VoxelForgeCore::Linux77Profiler::FScopedPhase l77PassagePhase(
|
||||
VoxelForgeCore::Linux77Profiler::EPhase::Passage);
|
||||
@@ -2332,18 +2296,8 @@ public:
|
||||
const bool bPassageRoutesValid=!bValidatePassageRoutes||ValidatePassageRoutes();
|
||||
if(!bPassageRoutesValid)
|
||||
{
|
||||
if(VF_IsL88PassageCompositionDisabled()
|
||||
&&!VF_IsL88BoundaryBandsDisabled()
|
||||
&&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;
|
||||
}
|
||||
Error="compiled shape world contains a solid passage centreline sample";
|
||||
return false;
|
||||
}
|
||||
Stats.PassageValidationSeconds=std::chrono::duration<double>(Clock::now()-Substage).count();
|
||||
Built=true;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# VoxelForge — open read-only review: what should be done and focused on now?
|
||||
|
||||
You are an outside reviewer. **Do not edit, create or delete any file, and do not build or run anything.** Read the
|
||||
repository and its reports and reason. Be thorough; mark each claim as [CODE] (with file:line), [MEASURED] (from a
|
||||
report), or [INFERENCE].
|
||||
|
||||
## The project, in the owner's words and goals
|
||||
|
||||
- VoxelForge is a UE5 density-field voxel plugin for a **multiplayer** game. The world is made of stacked "strates"
|
||||
(layers) linked by tunnels. The standalone C++ generator is "Core" (`Standalone/Core`), and it is also compiled into
|
||||
Unreal. Read `CLAUDE.md`, `CODEMAP.md`, `ARCHITECTURE.md`, `GDD.md`, `COMPOSER-NOTES.md` and `fable-idea.md` at the
|
||||
plugin root for the game and design intent. The research reports are in
|
||||
`Standalone/Research/WorldAssemblerM3/Linux*/REPORT.md` and the `Astra*/` reviews.
|
||||
- Owner goals stated over time:
|
||||
- the near terrain (LOD0–2) ready in ~1 s on arrival, then far terrain keeps filling in at low priority;
|
||||
- same seed gives the same world on every machine (byte-identity with older versions is NOT required);
|
||||
- smooth for VR and high-speed travel;
|
||||
- all generators (surface, floating islands, caves, dreamcore/liminal, etc.) working in Core;
|
||||
- the system should eventually *invent* strates and worlds from tagged authored content plus a seed;
|
||||
- keep things simple and avoid over-complication.
|
||||
- The current main line is branch `assembler/world`.
|
||||
|
||||
## Your task
|
||||
|
||||
Look at the whole: code, reports, design docs, and the direction of the last few dozen rounds. Tell the owner what
|
||||
should be done and focused on now, whatever it is. That may be performance, features, generation quality, gameplay
|
||||
foundations, architecture, technical debt, tooling, process, or stopping something. Don't assume the recent focus is
|
||||
the right one; question it if the evidence says so.
|
||||
|
||||
Answer:
|
||||
1. **Where the project actually is**: what works, what's fragile, what's missing for the game to exist.
|
||||
2. **The top 3–5 things to focus on now**, ranked, each with why, a rough size, what "done" looks like, and how to
|
||||
tell it worked.
|
||||
3. **What to stop or deprioritise**, and why.
|
||||
4. **Risks or debts** that will bite later if ignored.
|
||||
|
||||
Write plain Markdown, at most ~1,500 words, readable by a non-specialist owner (explain jargon briefly).
|
||||
@@ -0,0 +1,72 @@
|
||||
[INFERENCE] **Focus now on a small, persistent multiplayer descent, supported by end-to-end Unreal performance work.** VoxelForge has substantial terrain technology. The larger uncertainty is whether it delivers a reliable, interesting shared expedition. Another sequence of tunnel optimizations will not resolve that.
|
||||
|
||||
Read-only review of `assembler/world` at `044cd6d`; no files changed and no builds, tests, or project execution. [CODE] identifies repository evidence; design-document references establish intent, not implementation. [MEASURED] means reported results, not independently reproduced measurements.
|
||||
|
||||
**1. Where the project actually is**
|
||||
|
||||
[CODE] **Core is real and integrated, but generator implementation remains mixed.** Unreal compiles the canonical standalone sources through validated wrappers. Core dispatches to surface, floating-island and native graph evaluators, with a legacy-generator fallback when appropriate. That is useful coverage, but does not mean every family has a complete native implementation. See [VoxelForgeCore.Build.cs:15](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForgeCore/VoxelForgeCore.Build.cs:15) and [ShapeWorldInternal.h:600](/home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:600).
|
||||
|
||||
[MEASURED] **Passage correctness and speed have improved substantially.** L109 simplified tunnels and removed support-restoration machinery, reducing floating-island and tunnel-network near-generation times by approximately 31–38%. L125 reports 21,425/21,425 open route samples, a maximum sampled floor offset of 7.884 mm, and matching cross-compiler/worker hashes. These are meaningful engineering achievements. [L109](Standalone/Research/WorldAssemblerM3/Linux109/REPORT.md), [L125](Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md).
|
||||
|
||||
[MEASURED] **The one-second player experience is not achieved.** L125’s standalone near-ready medians were approximately 0.78–1.03 seconds. L127’s Unreal startup took 2.22–2.51 seconds; at 30 m/s, median near coverage fell from 43.36% to 40.22% after the smooth-tunnel merge. Both versions recovered after stopping. L130 found no measurable timing improvement and skipped Unreal movement. These are different workloads; subtracting their times would not isolate a particular overhead. [L125](Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md), [L127](Standalone/Research/WorldAssemblerM3/Linux127/REPORT.md), [L130](Standalone/Research/WorldAssemblerM3/Linux130/REPORT.md).
|
||||
|
||||
[CODE] **Multiplayer foundations exist; the multiplayer lifecycle remains unfinished here.** There are season hashes, local terrain-edit entry points, and streaming-anchor infrastructure. The architecture explicitly leaves join replication, authoritative edit messages, late-join snapshots and networked season changes open. The edit entry point directly dispatches to local modification paths. [VoxelWorld.h:574](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelWorld.h:574), [VoxelWorld.cpp:15771](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:15771), [ARCHITECTURE.md:2408](/home/jahni/VoxelM/Plugins/VoxelForge/ARCHITECTURE.md:2408).
|
||||
|
||||
[CODE] **The composer is more than a proposal, but less than the full content vision.** It rolls candidates, measures them and rejects failures. The intended system additionally combines tagged geometry, materials, decorations, creatures and audio; theme coherence remains an open design item. [VoxelSeasonManifest.cpp:2523](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelSeasonManifest.cpp:2523), [COMPOSER-NOTES.md:1512](/home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:1512).
|
||||
|
||||
[INFERENCE] **This repository demonstrates a capable terrain platform, not yet a validated game loop.** I cannot establish what gameplay exists outside the plugin. The GDD itself identifies “Is the descent fun?” as its first unresolved question. [GDD.md:441](/home/jahni/VoxelM/Plugins/VoxelForge/GDD.md:441).
|
||||
|
||||
**2. Ranked priorities**
|
||||
|
||||
All sizes below are [INFERENCE]: rough focused engineering estimates, excluding substantial art production.
|
||||
|
||||
**1 — Deliver one multiplayer expedition that survives reconnecting. Size: 3–6 weeks.**
|
||||
|
||||
[INFERENCE] Use two contrasting strates and their connecting tunnel. Two players descend, find one destination, uncover or collect something, return, and retain their changes after restart. Include a third player joining after terrain has changed. Avoid expanding immediately into the city economy or community backend.
|
||||
|
||||
[INFERENCE] The necessary foundation is a server-approved world identity, ordered authoritative edits, a saved snapshot plus subsequent edits, and collision around separated players. Give edits stable identifiers so retransmission cannot apply them twice. Reuse the existing local edit and anchor systems.
|
||||
|
||||
[INFERENCE] **Done:** host/client edits agree; a late joiner reconstructs the same terrain; restart preserves it; incompatible world versions fail clearly; remote players have ground when away from the host.
|
||||
|
||||
[INFERENCE] **Success:** a complete shared expedition without terrain disagreement, lost progress or collision failures—and players can explain what made them want to descend again. This tests the project’s central assumptions much earlier than a complete RPG would.
|
||||
|
||||
**2 — Close the Unreal arrival and movement gap. Size: 1–3 weeks initially.**
|
||||
|
||||
[MEASURED] L122 found idle generation capacity while admission was blocked; L123 measured approximately 19 ms from region request to game-thread observation despite sub-millisecond median compilation. Simple lookahead and admission relaxations failed their combined coverage/frame-time gates. L121’s modest extra far-apply lane did improve far coverage. [L121](Standalone/Research/WorldAssemblerM3/Linux121/REPORT.md), [L122](Standalone/Research/WorldAssemblerM3/Linux122/REPORT.md), [L123](Standalone/Research/WorldAssemblerM3/Linux123/REPORT.md).
|
||||
|
||||
[INFERENCE] First establish one current-build, rendered Unreal baseline on intended hardware. Measure arrival through **visible terrain and usable collision**, then walking, 30 m/s travel, turns, teleporting and edits. Record near coverage, far gaps, frame-time spikes and memory separately. NullRHI measurements, which omit rendering, cannot certify VR comfort.
|
||||
|
||||
[INFERENCE] Investigate region completion, admission and publication before another broad density rewrite. A game-thread continuation is a candidate experiment, not a proven solution; keep world mutation on its owning thread.
|
||||
|
||||
[INFERENCE] **Done:** approximately one-second LOD0–2 readiness on the agreed hardware, safe collision, steadily filling far terrain, and an explicit movement-coverage target without worsening frame spikes. **Success:** repeated rendered runs meet those limits, including with remote-player collision work. Do not redefine “ready” as only the nearest handful of tiles.
|
||||
|
||||
**3 — Turn generator breadth into playable variety. Size: 2–4 weeks for the first content slice.**
|
||||
|
||||
[INFERENCE] Establish a compact capability matrix for each family: Core dispatch, entrances/exits, interior connectivity, edits, materials/content, far terrain and performance. Include dreamcore/liminal explicitly; motif generation alone does not establish a convincing anomalous place.
|
||||
|
||||
[MEASURED] L58 illustrates the distinction: its lattice route passed reachability checks, but the review described a corkscrew tunnel rather than the intended open vertical shaft. Technical validity and identity are separate acceptance criteria. [L58](Standalone/Research/WorldAssemblerM3/Linux58/REPORT.md).
|
||||
|
||||
[INFERENCE] Extend the existing offline composer with a small tagged library: a grounded cave, an island environment and one liminal identity, each with coherent materials, sound and a destination. Preserve owner review before publishing a season.
|
||||
|
||||
[INFERENCE] **Done:** several seeds produce recognizably different, coherent places with findable progression and usable encounter spaces. **Success:** players navigate them without developer guidance and distinguish their identities without reading labels. Expand families after this works.
|
||||
|
||||
**4 — Consolidate the evidence and remove obsolete complexity incrementally. Size: 2–4 days, then ongoing.**
|
||||
|
||||
[INFERENCE] Maintain one short current-state page: shipped behavior, open defects, active baseline, hardware and next acceptance test. Keep historical reports as history. Remove rejected experimental paths when they no longer serve a specific comparison; extract stable responsibilities when touching oversized files.
|
||||
|
||||
[INFERENCE] **Done:** a contributor can identify the current evaluator, runtime path, multiplayer gaps and performance limits without reconstructing 130 rounds. **Success:** new work no longer repeats rejected experiments or treats old measurements as current.
|
||||
|
||||
**3. Stop or deprioritise**
|
||||
|
||||
- [INFERENCE] **Pause open-ended tunnel micro-optimization.** L125/L126 missed the older speed bar; L130’s reach correction produced no measurable speedup. Keep correctness fixes, but require a current cost account and a bounded experiment before further optimization. [MEASURED: L126](Standalone/Research/WorldAssemblerM3/Linux126/REPORT.md), [L130](Standalone/Research/WorldAssemblerM3/Linux130/REPORT.md).
|
||||
- [INFERENCE] **Do not implement Astra recommendations mechanically.** Astra1’s support-heavy model predates L109’s simplification. Astra2/3 offer hypotheses, not measured wins for today’s code. Re-profile before adopting them.
|
||||
- [INFERENCE] **Defer GPU generation, a mesher replacement, elaborate discovery systems and large-scale backend work.** None currently resolves the missing shared expedition.
|
||||
- [INFERENCE] **Stop requiring old-version byte identity for deliberate generation changes.** Preserve peer agreement within a version and explicit versioned saves; permit reviewed geometry improvements.
|
||||
|
||||
**4. Debts that will bite later**
|
||||
|
||||
[INFERENCE] **Determinism needs a deployment contract.** Linux Clang/GCC and worker-count agreement is strong evidence, not proof across every intended machine. Include Windows/compiler/CPU combinations actually supported. World identity must cover evaluator, content, layout, scale and edit state—not merely seed. [MEASURED: L130](Standalone/Research/WorldAssemblerM3/Linux130/REPORT.md).
|
||||
|
||||
[CODE] **Scale and fallback complexity remain active integration risks.** Core is opt-in, and runtime queries bridge different coordinate conventions. [VoxelWorld.h:300](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelWorld.h:300), [VoxelWorld.cpp:15612](/home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:15612). [INFERENCE] Test edits, content placement and collision across those boundaries before broadening authoring.
|
||||
|
||||
[INFERENCE] **A passing route audit does not prove a whole strate is enjoyable, connected or suitable for six-player combat.** Retain geometric checks, but add actual traversal, destination discovery and encounter-space evaluation. Those are now more valuable than another polished tunnel benchmark.
|
||||
@@ -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())
|
||||
@@ -0,0 +1,35 @@
|
||||
# VoxelForge — research R46 (read-only): generator capability matrix
|
||||
|
||||
You are a researcher. **Read only: do not edit, create or delete any file, and do not build, run or test anything.**
|
||||
Read the code, reports and design docs. Be thorough: verify each claim by hand in the code, and mark each one
|
||||
[CODE] file:line, [MEASURED] report, or [INFERENCE]. Branch `assembler/world` (`cbbfd46`).
|
||||
|
||||
## Why
|
||||
|
||||
The owner approved the next focus (from `Standalone/Research/WorldAssemblerM3/Astra4/REVIEW.md` #3): turn generator
|
||||
breadth into playable variety. First we need an honest picture of what each strate/generator family can do today.
|
||||
|
||||
## Task
|
||||
|
||||
Find every generator family / strate type: surface world, floating islands, caves/cavern, tunnel network, vertical
|
||||
shafts, dreamcore/liminal, and any others in the code (Core native, legacy fallback, op stack, composer). For each,
|
||||
fill one row:
|
||||
- **Core path:** native Core evaluator, legacy fallback, or not in Core at all? Where is it dispatched?
|
||||
- **Entrances/exits:** arrival and departure mouths, and the primordial law (arrival → departure walkable).
|
||||
- **Interior connectivity:** walkable, and audited by what?
|
||||
- **Edits:** does digging (diff layer) work on it in the Core path?
|
||||
- **Materials/content:** material IDs, decorations, foliage, lights, anything placeable.
|
||||
- **Far terrain:** does it have far LOD/shells?
|
||||
- **Performance:** latest measured near-ready, with the report.
|
||||
- **Identity:** what makes it look and feel distinct today; is it recognisable without a label?
|
||||
- **Owner world:** used in `Standalone/data/owner_world.json`? Which strate letter (SW/FI/TN/VS)?
|
||||
- **Gaps:** what's missing for it to be a "place" with its own identity and a destination.
|
||||
|
||||
Then:
|
||||
1. Which three families are closest to being distinct places (the owner's example: a grounded cave, an island
|
||||
environment, one liminal identity)? What is the smallest work to get each there?
|
||||
2. What does the composer (`VoxelSeasonManifest.cpp`, `COMPOSER-NOTES.md`) already do for tagged content, and what's
|
||||
the smallest next step?
|
||||
3. Risks: places where the Core path silently falls back, or where a family exists in docs but not in code.
|
||||
|
||||
Write plain Markdown: the matrix plus ≤ ~800 words of findings.
|
||||
@@ -0,0 +1,41 @@
|
||||
# VoxelForge R46 — generator capability matrix
|
||||
|
||||
Read-only review of `assembler/world` at `cbbfd46`; no files changed, and no builds, runs, or tests were performed.
|
||||
|
||||
## Shared dispatch and contracts
|
||||
|
||||
[CODE] The eight `ECaveGeneratorType` values are TunnelNetwork, FlatPlain, CrystalChamber, Maze, SurfaceWorld, VerticalShafts, FloatingIslands, and Underwater. `NativeCaves`, `NativeLattice`, and `ProfiledHeightfield` are optional Core recipes layered onto those types, not additional strate types. [VoxelStrateTypes.h:175](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:175>) [VoxelStrateTypes.h:203](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:203>)
|
||||
|
||||
[CODE] Core binds native SurfaceWorld and FloatingIslands evaluators when matching plans exist; it binds native cave/lattice graph fields when their capabilities are present. Otherwise it attaches a legacy generator adapter. The density dispatcher exposes paths such as `SurfaceWorld-native`, `SurfaceWorld-legacy`, `Caves-native`, and `compiled-analytic/<kind>`. [ShapeWorldInternal.h:600](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:600>) [ShapeWorldInternal.h:640](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:640>) [ShapeWorldInternal.h:649](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:649>) [ShapeWorldInternal.h:3101](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3101>)
|
||||
|
||||
[CODE] The adapter plans inter-strate passages and resolves the layout before Core evaluates it. The composer’s primordial law checks a player-fit, walk-only path between the center-column interior endpoints; it is an arrival-to-departure test, not a requirement that every disconnected room or shaft join the largest component. [VoxelForgeCoreAdapter.cpp:1545](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:1545>) [VoxelSeasonManifest.cpp:2194](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelSeasonManifest.cpp:2194>) [VoxelStrateMeasure.h:315](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateMeasure.h:315>)
|
||||
|
||||
[CODE] Core edit transactions become density brushes applied after field composition. The same stage covers native and fallback density paths. [VoxelForgeCore.cpp:3307](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/VoxelForgeCore.cpp:3307>) [ShapeWorldInternal.h:3036](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3036>) [ShapeWorldInternal.h:5201](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:5201>)
|
||||
|
||||
[CODE] Any strate can author decorations, landmarks, ambient actors, and creatures. Placement supports actors or instanced meshes; Core material samples default to host ID 1 and can carry two resource IDs. These are shared content hooks, not a distinct palette per generator family. [VoxelStrateDefinition.h:352](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateDefinition.h:352>) [VoxelStrateTypes.h:2204](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:2204>) [VoxelForgeCore.h:1273](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h:1273>)
|
||||
|
||||
**Performance key:** L125 is the latest absolute owner four-strata LOD0–2 timing table I found; L130’s paired comparison found no measurable change. L125 labels rows S0–S3, so mapping them to SW/FI/TN/VS in the explicit L109 order is an **[INFERENCE]**. Values below are W8/W12 medians in seconds; they measure the owner layout, not isolated native evaluator costs. [L125:24](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md:24>) [L125:28](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md:28>) [L125:35](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md:35>) [L130:9](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux130/REPORT.md:9>) [L109:21](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux109/REPORT.md:21>)
|
||||
|
||||
## Matrix
|
||||
|
||||
| Family / owner | Core path | Entrances, connectivity, and primordial law | Edits, materials, and content | Far terrain and performance | Identity and gaps |
|
||||
|---|---|---|---|---|---|
|
||||
| **SurfaceWorld — SW** | [CODE] Native `Heightfield2D` when a matching surface plan binds; legacy SurfaceWorld fallback otherwise. [ShapeWorldInternal.h:600](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:600>) [ShapeWorldInternal.h:6685](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6685>) | [CODE] Owner export enables an open surface entry; SW also supplies the 0–1 departure mouth. [MEASURED] The shared route audit passed 21,425/21,425 centerline samples. [owner_world.json:1](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/data/owner_world.json:1>) [L125:39](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux125/REPORT.md:39>) | [CODE] Digging works. Surface supports biome terrain/material signals, water, and the shared placement hooks; no family-specific content pack is proven in the owner export. [VoxelStrateTypes.h:1609](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:1609>) | [CODE] Common mesh LOD and far shells; native surface plans also get far ground/cap refinement. [MEASURED] **SW:** 0.780/0.807 near-ready. [VoxelForgeCore.cpp:2996](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/VoxelForgeCore.cpp:2996>) [VoxelForgeCore.cpp:3073](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/VoxelForgeCore.cpp:3073>) | [INFERENCE] Outdoor hills, mountains, rivers, and beaches have a legible silhouette. It still needs distinctive foliage/materials, sound, and a destination to read as a complete place. |
|
||||
| **FloatingIslands — FI** | [CODE] Native island field when a matching island plan binds; otherwise falls through to the legacy analytic path. [ShapeWorldInternal.h:620](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:620>) [ShapeWorldInternal.h:6692](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:6692>) | [CODE] Owner route enters from SW and departs toward TN; native island route audits check capsule clearance and support. [MEASURED] The owner passage checks passed. [MEASURED] L67 reported the owner FI path as `compiled-analytic/FloatingIslands`, not native; the reason was unresolved in R36. [L67:5](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux67/REPORT.md:5>) [Research36:11](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Research36/REPORT.md:11>) | [CODE] Digging works; foliage, landmarks, ambient actors, and lights can use shared placement systems. [INFERENCE] No island-specific owner palette/content is established by the export. | [CODE] Common far mesh and shell paths. [MEASURED] **FI:** 0.981/0.962 near-ready in the owner layout. | [INFERENCE] Floating land silhouettes can be immediately recognizable. Confirm native dispatch, then add an island ecology, a landmark, and a clear route/destination. |
|
||||
| **TunnelNetwork — TN** | [CODE] The owner’s regular path is Core’s legacy/compiled-analytic fallback. `NativeCaves` is optional for TN/Underwater and evaluates authored room/tunnel graphs. [VoxelForgeCoreAdapter.cpp:145](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:145>) [VoxelGenerator.cpp:2645](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:2645>) | [CODE] Owner arrival from FI and departure toward VS. [MEASURED] Inter-strate walkability passes; that does not prove every interior room is connected. Native cave fixture flood-fill connected its chosen arrival/departure pair. [L54:21](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux54/REPORT.md:21>) | [CODE] Digging works. Generic cave decorations/landmarks/lighting are available; there is no family-specific Core material palette. | [CODE] Common far LOD/shells. [MEASURED] **TN:** 1.025/0.965 near-ready in the owner layout. Optional native-cave fixture: 0.177 s near ring and 0.706 s cold whole view, a different workload. [L54:37](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux54/REPORT.md:37>) | [INFERENCE] Rooms and tunnels read as caves, but the owner route lacks a content-defined destination. Small cave graph and a landmark/content pack would make it a place; translating the owner’s legacy parameters to native cave records remains separate work. |
|
||||
| **FlatPlain** | [CODE] Legacy fallback/op stack only; it uses the slab builder. [VoxelGenerator.cpp:2600](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:2600>) [VoxelDensityOpStack.cpp:9373](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelDensityOpStack.cpp:9373>) | [CODE] No intrinsic mouths; shared passage planner supplies endpoints. [INFERENCE] Its open floor/ceiling band may connect the selected endpoints, but no family-specific arrival/departure audit was found. | [CODE] Digging works; shared decorations/landmarks can populate the chamber. | [CODE] Common far LOD/shells. [MEASURED] No separate near-ready timing found. | [INFERENCE] Open underground plain with columns. Needs a distinctive floor/ceiling profile, content, and destination; it has no native Core slab recipe. |
|
||||
| **CrystalChamber** | [CODE] Same slab op-stack builder as FlatPlain; distinctness comes from parameter values, especially ceiling roughness. [VoxelGenerator.cpp:2600](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:2600>) | [CODE] Same shared-mouth arrangement as FlatPlain; no family-specific walk audit found. | [CODE] Digging works. Crystal decoration is authorable through shared placement, not guaranteed by the geometry type. [VoxelStrateTypes.h:169](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:169>) | [CODE] Common far LOD/shells. [MEASURED] No separate near-ready timing found. | [INFERENCE] Hanging formations could distinguish it, but parameters alone do not supply crystal materials, lighting, or a destination. |
|
||||
| **Maze** | [CODE] Legacy maze op stack; optional `NativeLattice` graph recipe, which is shared with VerticalShafts rather than a dedicated native maze generator. [VoxelForgeCoreAdapter.cpp:159](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:159>) [VoxelGenerator.cpp:2592](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:2592>) | [CODE] Mouths are shared-planner endpoints; native lattice fixtures test capsule reachability between chosen endpoints. [MEASURED] L60 native lattice fixture: 0.561 s near ring, 1.701 s whole view—not the owner near-ready workload. [L60:19](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux60/REPORT.md:19>) [L60:36](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux60/REPORT.md:36>) | [CODE] Digging works; common content hooks apply. | [CODE] Common far LOD/shells; L60 streamed the lattice fixture through LOD0–8. [L60:15](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux60/REPORT.md:15>) | [INFERENCE] Tight branching corridors are a recognizable grammar, but the native fixture’s helix/maze graph needs a content destination and stronger per-seed identity. |
|
||||
| **VerticalShafts — VS** | [CODE] Legacy shaft op stack; optional `NativeLattice` is a generic authored graph, not a shaft-specific Core evaluator. [VoxelGenerator.cpp:2622](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:2622>) | [CODE] Owner arrival comes from TN; the four-strata export has no lower fifth-stratum passage. [MEASURED] The composer found a VerticalShafts arrival/departure violation; L58’s lattice route passed but was a helix. [COMPOSER-NOTES.md:1437](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:1437>) [Linux58:11](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux58/REPORT.md:11>) | [CODE] Digging works; generic props and lights can be placed. | [CODE] Common far LOD/shells. [MEASURED] **VS:** 0.879/0.838 near-ready in owner layout. | [INFERENCE] Vertical silhouettes could distinguish it, but the native graph example is not an open shaft. Needs a shaft-specific core, safe landings, and a proven route. |
|
||||
| **Underwater** | [CODE] TunnelNetwork density plus water behavior; optional NativeCaves recipe is accepted. No separate native water generator recipe. [VoxelGenerator.cpp:2638](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelGenerator.cpp:2638>) [Unreal1:131](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Unreal1/REPORT.md:131>) | [CODE] Shared passage mouths; composer’s law is walk-only, so it does not certify swimming or water traversal. [INFERENCE] A flooded route needs dry walkable sections or a separate traversal rule. | [CODE] Digging works; water and shared content are available, but the native assembly recipe does not itself provide an authored water feature. | [CODE] Common far terrain; far water presentation is not established here. [MEASURED] No separate near-ready timing found. | [INFERENCE] “Flooded cave” is a plausible identity, but water, lighting, air pockets, and destination spaces need authored treatment. |
|
||||
| **Dreamcore / liminal** | [CODE] No `Dreamcore` generator type. Existing Core stamps/motif fields are overlays; motif override currently requires a resolved SurfaceWorld strate. [VoxelStrateTypes.h:175](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:175>) [WorldAssemblyPrototype.h:568](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Source/WorldAssemblyPrototype.h:568>) | [CODE] Inherits mouths and connectivity from its base family; motif fixtures preserve route keepouts. [MEASURED] L60 motif overlay: 0.493 s near ring, 1.326 s whole view. [Linux56:21](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux56/REPORT.md:21>) [L60:35](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux60/REPORT.md:35>) | [CODE] Digging applies to the composed field; current motif kinds include carve arch/ellipsoid and fill pillar/dais/monolith/platform. [VoxelStrateTypes.h:222](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateTypes.h:222>) | [CODE] Base field uses common far LOD/shells. Motifs have LOD coverage, but no liminal-specific far treatment. | [INFERENCE] Motifs alone do not read as dreamcore. It needs a repeated spatial grammar, coherent palette/light/sound, and an explorable destination. Not in owner world. |
|
||||
|
||||
Owner mapping: [MEASURED] the owner export references four fixed strata and opens the surface; the named four-family owner route is SW/FI/TN/VS. [CODE] The L125–L130 timings are for that owner layout. [owner_world.json:1](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/data/owner_world.json:1>) [L109:21](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux109/REPORT.md:21>) [L120:23](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux120/REPORT.md:23>)
|
||||
|
||||
## Findings
|
||||
|
||||
1. **Closest to distinct places: TN caves, FI, and liminal overlays.** [INFERENCE] TN already has cave geometry and route proof: add one authored destination chamber plus a small landmark/material/light kit. FI already has a distinctive suspended-land silhouette and route support: first confirm its native dispatch, then add foliage, a landmark, and route cues. Liminal is the smallest overlay slice: reuse the flat/profiled base and existing monolith/platform stamps, then define one repeatable anomaly pattern and a matching content kit. These need authored destinations and themes more than new density families.
|
||||
|
||||
2. **Composer status and smallest next step.** [CODE] `VoxelSeasonManifest.cpp` rolls candidates from a corpus, measures them, rejects vacuous/fragmented/primordial-law failures, and selects for grounded/outlier mix plus archetype/recipe variety. Promoted records carry an archetype tag and corpus provenance is tagged `project`, `default`, or `promoted`. [VoxelSeasonManifest.cpp:2523](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelSeasonManifest.cpp:2523>) [COMPOSER-NOTES.md:431](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:431>) [COMPOSER-NOTES.md:1466](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:1466>) Strate and biome gameplay tags are stored, but theme draws for materials, creatures, decorations, and audio are still open. [VoxelStrateDefinition.h:389](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelStrateDefinition.h:389>) [COMPOSER-NOTES.md:1484](</home/jahni/VoxelM/Plugins/VoxelForge/COMPOSER-NOTES.md:1484>) [INFERENCE] Smallest step: tag one real content class with multiple theme tags and let one seed-selected family draw a coherent, reviewable mini-pack.
|
||||
|
||||
3. **Risks.** [CODE] Missing native plans/capabilities reach the legacy binding; path diagnostics are needed to distinguish them. [ShapeWorldInternal.h:649](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:649>) [MEASURED] The latest explicit owner dispatch note I found says FI/TN/VS used compiled analytic fields; L130 reports timing but not dispatch, so that path should be rechecked before calling those owner generators native. [Linux67:5](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux67/REPORT.md:5>) [Linux130:9](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux130/REPORT.md:9>) [INFERENCE] Dreamcore exists as a design goal, not a generator; NativeLattice proves routes but not a shaft identity; FlatPlain/CrystalChamber remain legacy slab fields; and water presentation remains outside the native Core recipe.
|
||||
@@ -2566,15 +2566,9 @@ namespace StandaloneStreamBenchmark
|
||||
ShapeRequest.detail=DetailVariant;ShapeRequest.includeFarWorld=bIncludeFarWorld&&!bDeferFarWorld;
|
||||
ShapeRequest.roundTunnels=bRoundTunnels;
|
||||
ShapeRequest.enhancedTunnelWalls=bEnhancedTunnelWalls;
|
||||
const char* L86DisablePassages=std::getenv(
|
||||
"VOXELFORGE_L86_DISABLE_PASSAGE_COMPOSITION");
|
||||
const bool bL86DisablePassages=L86DisablePassages
|
||||
&&L86DisablePassages[0]=='1'&&L86DisablePassages[1]=='\0';
|
||||
ShapeRequest.validatePassageRoutes=!bCaptureSkipWalkability&&!bL86DisablePassages;
|
||||
ShapeRequest.validatePassageRoutes=!bCaptureSkipWalkability;
|
||||
if(bCaptureSkipWalkability)
|
||||
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,
|
||||
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileColumnOverlap,
|
||||
FarHorizonLOD8InteriorStepVoxels,bUseSharedColumnCache,
|
||||
|
||||
@@ -153,80 +153,6 @@ namespace StandaloneWorldAssemblyPrototype
|
||||
candidateCenterSpacing=32;
|
||||
}
|
||||
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",
|
||||
2.0*candidateHalfLengths.front()*coreVoxelMetres,candidateHalfLengths.size(),
|
||||
candidateCenterSpacing*coreVoxelMetres,
|
||||
|
||||
Reference in new issue
Block a user