diag: bounded passage carve reach rejected (L93); R43 Unreal SW startup notes

Explicit carve reach R (diagnostic, default unbounded): R=2.5 m -> 1.56 cm max displacement,
106 deg max normal change; R=4 m -> 0.63 cm but 53 deg normals. Fails the bar; readiness gain
small and inconsistent (TN -5%, VS +6-7%). No world change (v214). Fast tier PASS.
R43: Unreal SW bReady 2.16 s = serial sign-edge repair (1.94 s, 10.9M corrections;
parallelSignEdgeRepair exists but off); ~0.45 s of SerializeResolvedWorld = adapter SW route search.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-28 07:33:53 +01:00
1 parent 70c37aaab3
commit 1e111cc042
9 files changed
+537 -47

No files matched your search

@@ -1813,6 +1813,10 @@ namespace VoxelForgeCore
// entering passage composition to at least -N voxel units for this tile.
// A negative value leaves the process-level diagnostic override in control.
double diagnosticPassageSourceFloorVoxels = -1.0;
// Research-only field comparison. Zero keeps the unbounded passage carve;
// a positive value bounds its signed-distance reach in metres. A negative
// value leaves the process-level L93 setting in control.
double diagnosticPassageCarveReachMetres = -1.0;
// Research-only: collect tile-drain kernel counters and floating-island cache metrics.
// Inactive on ordinary generation so the hot path only pays the option check.
bool instrumentTileDrain = false;
+70 -24
View File
@@ -84,6 +84,20 @@ static double VF_L91PassageSourceFloorVoxels()
return Value;
}
static double VF_L93PassageCarveReachMetres()
{
static const double Value=[]
{
const char* Raw=std::getenv("VOXELFORGE_L93_PASSAGE_CARVE_REACH_METRES");
if(!Raw||!*Raw)return 0.0;
char* End=nullptr;
const double Parsed=std::strtod(Raw,&End);
return End!=Raw&&*End=='\0'&&std::isfinite(Parsed)&&Parsed>0.0
?Parsed:0.0;
}();
return Value;
}
// Standalone-only world compiler. It compiles the runtime room/tunnel/passages into
// axis-line intervals, composes rock/cave signs into packed Z-column words, then displaces
// only the conservative surface band. The copied Unreal generator remains the A/B reference.
@@ -241,14 +255,18 @@ public:
const std::array<std::int64_t,3>& minimumSubvoxels,
const std::array<std::int64_t,3>& maximumSubvoxels,
VoxelForgeCore::TileGenerationStats* profileStats=nullptr,int32 profileLod=0,
double passageSourceFloorVoxels=-1.0)
double passageSourceFloorVoxels=-1.0,
double passageCarveReachMetres=-1.0)
:shape_(&shape),minimumSubvoxels_(minimumSubvoxels),
maximumSubvoxels_(maximumSubvoxels),previous_(ActivePassageTileQueries),
profileStats_(profileStats),profileLod_(profileLod),
candidateProfiled_(profileStats!=nullptr&&shape.L90PassageCandidateProgramEnabled),
passageSourceFloorVoxels_(std::isfinite(passageSourceFloorVoxels)
&&passageSourceFloorVoxels>=0.0?passageSourceFloorVoxels
:VF_L91PassageSourceFloorVoxels())
:VF_L91PassageSourceFloorVoxels()),
passageCarveReachMetres_(std::isfinite(passageCarveReachMetres)
&&passageCarveReachMetres>=0.0?passageCarveReachMetres
:VF_L93PassageCarveReachMetres())
{
if(passageSourceFloorVoxels_>0.0)
clampCounters_=std::make_shared<FPassageSourceClampCounters>();
@@ -360,6 +378,7 @@ public:
previous_(ActivePassageTileQueries),profileLod_(source.profileLod_),
candidateProfiled_(source.candidateProfiled_),
passageSourceFloorVoxels_(source.passageSourceFloorVoxels_),
passageCarveReachMetres_(source.passageCarveReachMetres_),
clampCounters_(source.clampCounters_),ownsClampCounters_(false)
{ ActivePassageTileQueries=this; }
~FScopedPassageTileQueries()
@@ -479,6 +498,7 @@ public:
{return profileStats_;}
bool candidateCensusProfiled() const noexcept{return candidateProfiled_;}
double passageSourceFloorVoxels() const noexcept{return passageSourceFloorVoxels_;}
double passageCarveReachMetres() const noexcept{return passageCarveReachMetres_;}
void recordPassageSourceClamp(float sourceDensity) const noexcept
{
if(passageSourceFloorVoxels_<=0.0)return;
@@ -556,6 +576,7 @@ public:
int32 profileLod_=0;
bool candidateProfiled_=false;
double passageSourceFloorVoxels_=0.0;
double passageCarveReachMetres_=0.0;
mutable std::shared_ptr<FPassageSourceClampCounters> clampCounters_;
bool ownsClampCounters_=true;
mutable std::uint64_t l90Queries_=0,l90NoBrickQueries_=0;
@@ -1284,6 +1305,23 @@ public:
&&passageTileQueries->matches(*this);
auto* passageProfile=passageTileScopeMatches
?passageTileQueries->profileStats():nullptr;
const double passageCarveReachMetres=passageTileScopeMatches
?passageTileQueries->passageCarveReachMetres()
:VF_L93PassageCarveReachMetres();
const bool passageCarveReachEnabled=passageCarveReachMetres>0.0
&&std::isfinite(passageCarveReachMetres);
const double passageCarveReachQ=passageCarveReachEnabled
?passageCarveReachMetres*qPerMetre
:std::numeric_limits<double>::infinity();
const auto carveSourceReachQ=[&](float source)
{
const double sourceReach=source<0.0f
?-static_cast<double>(source)*Q+0.24*qPerMetre
:std::max(2.25*qPerMetre,-static_cast<double>(source)*Q
+0.24*qPerMetre);
return passageCarveReachEnabled
?std::min(sourceReach,passageCarveReachQ):sourceReach;
};
if(passageProfile)++passageProfile->passageComposerQueries;
const bool l90CandidateProfiled=passageTileScopeMatches
&&passageTileQueries->candidateCensusProfiled();
@@ -1335,13 +1373,10 @@ public:
&&!passageTileQueries->hasAnyMouthSupport()
&&!passageTileQueries->mayContainUpperMouthSupport())return density;
// On solid samples, the SDF carve can still move the scalar density far outside the
// physical tunnel. The per-passage test below already accounts for this tail using the
// incoming density plus the bounded relief allowance. Apply that same proof before
// entering the passage loop for points outside the scalar influence reach. Columns and
// both mouth-support paths keep their own tile envelopes and therefore disable this
// cut. Optional extra padding is only for research sweeps; zero is the exact bound.
// Invalid values fail open.
// On solid samples, the unbounded SDF carve can move density far outside the tube.
// Bound that source-dependent tail, or cap it at the explicit carve reach. Whole-tile
// rejection is limited to tiles with no route, column, or mouth feature, so the separate
// support and landing paths keep their existing envelopes. Invalid values fail open.
static const double PassageBoundPaddingVoxels=[]
{
constexpr double DefaultPaddingVoxels=0.0;
@@ -1358,7 +1393,9 @@ public:
&&std::isfinite(PassageBoundPaddingVoxels)
&&!passageTileQueries->hasColumnZOverlap()
&&!passageTileQueries->hasAnyMouthSupport()
&&!passageTileQueries->mayContainUpperMouthSupport())
&&!passageTileQueries->mayContainUpperMouthSupport()
&&(!passageCarveReachEnabled
||!passageTileQueries->hasRouteFeatureOverlap()))
{
if(passageProfile)++passageProfile->passageTileBoundChecks;
bool bAnyPassageWithinBound=false;
@@ -1388,8 +1425,11 @@ public:
(CarveHigh-Passage.controlPoints.begin())-1);
const std::ptrdiff_t CarveEnd=std::min<std::ptrdiff_t>(LowerMouthIndex-1,
(CarveLow-Passage.controlPoints.begin())+1);
const double SignedDistanceLimit=-static_cast<double>(density)*Q
+0.24*qPerMetre+ExtraPadding;
const double rawSignedDistanceLimit=-static_cast<double>(density)*Q
+0.24*qPerMetre;
const double SignedDistanceLimit=passageCarveReachEnabled
?std::min(rawSignedDistanceLimit,passageCarveReachQ)+ExtraPadding
:rawSignedDistanceLimit+ExtraPadding;
if(PassageMayAffectDensity(PassageIndex,CarveBegin,CarveEnd,
LowerMouthIndex,Constants.mouthSearchBegin,Constants.mouthSearchEnd,
Constants.lastIndex,qx,qy,qz,SignedDistanceLimit))
@@ -1686,10 +1726,7 @@ public:
const std::ptrdiff_t mouthSearchEnd=passageConstants.mouthSearchEnd;
if(l90CandidateProfiled)
{
const double signedDistanceLimit=density<0.0f
?-static_cast<double>(composed)*Q+0.24*qPerMetre
:std::max(2.25*qPerMetre,-static_cast<double>(composed)*Q
+0.24*qPerMetre);
const double signedDistanceLimit=carveSourceReachQ(composed);
const bool sourceProofAvailable=L90PassageCandidateProgramValid
&&std::isfinite(signedDistanceLimit)
&&signedDistanceLimit<=L90PassageCandidateReachMetres*qPerMetre
@@ -1704,10 +1741,12 @@ public:
}
if(density<0.0f&&tilePassageFree)
{
// A tile without this passage's route feature cannot contain its separate
// tread/support work, so the carve reach is sufficient for this query skip.
if(passageProfile)++passageProfile->passageNegativeBoundChecks;
if(!PassageMayAffectDensity(passageIndex,carveBegin,carveEnd,
lowerMouthIndex,mouthSearchBegin,mouthSearchEnd,lastIndex,qx,qy,qz,
-static_cast<double>(composed)*Q+0.24*qPerMetre))
carveSourceReachQ(composed)))
{
if(passageProfile)++passageProfile->passageNegativeBoundRejects;
continue;
@@ -1726,8 +1765,7 @@ public:
if(passageProfile)++passageProfile->passagePositiveBoundChecks;
if(!PassageMayAffectDensity(passageIndex,carveBegin,carveEnd,
lowerMouthIndex,mouthSearchBegin,mouthSearchEnd,lastIndex,qx,qy,qz,
std::max(2.25*qPerMetre,-static_cast<double>(composed)*Q
+0.24*qPerMetre)))
carveSourceReachQ(composed)))
{
if(passageProfile)++passageProfile->passagePositiveBoundRejects;
continue;
@@ -1863,10 +1901,7 @@ public:
considerCarveSegment(static_cast<std::size_t>(index),3);
}
if(!std::isfinite(bestSignedDistance))continue;
const double l90SignedDistanceLimit=density<0.0f
?-static_cast<double>(composed)*Q+0.24*qPerMetre
:std::max(2.25*qPerMetre,-static_cast<double>(composed)*Q
+0.24*qPerMetre);
const double l90SignedDistanceLimit=carveSourceReachQ(composed);
if(l90CandidateProfiled&&bestSignedDistance<=l90SignedDistanceLimit
&&l90SignedDistanceLimit<=L90PassageCandidateReachMetres*qPerMetre)
passageTileQueries->recordL90ProofCheck(0,
@@ -2108,6 +2143,17 @@ public:
*floorAlignment*floorAlignment*floorBelowWeight*mouthWalkLaneWeight;
const float fullyCarvedDensity=std::max(composed,
static_cast<float>(-roughSignedDistance/Q));
double carveReachWeight=1.0;
if(passageCarveReachEnabled)
{
constexpr double ReachBlendWidthMetres=0.5;
const double blendWidthQ=std::min(ReachBlendWidthMetres,
passageCarveReachMetres)*qPerMetre;
const double fade=std::clamp((passageCarveReachQ-bestSignedDistance)
/std::max(1.0,blendWidthQ),0.0,1.0);
if(passageProfile)++passageProfile->passageSmoothstepEvaluations;
carveReachWeight=fade*fade*(3.0-2.0*fade);
}
static const bool bL75TraceTnPassage=[]
{
const char* Value=std::getenv("VOXELFORGE_L75_TN_BLOCK_REGRESSION");
@@ -2115,7 +2161,7 @@ public:
}();
const float passageInput=composed;
composed=std::lerp(composed,fullyCarvedDensity,
static_cast<float>(floorCarveWeight));
static_cast<float>(floorCarveWeight*carveReachWeight));
if(bL75TraceTnPassage&&X==-80.0f&&Y==-20.0f&&Z==-3218.0f
&&composed!=passageInput)
{
+2 -1
View File
@@ -2797,7 +2797,8 @@ namespace VoxelForgeCore
const FStandaloneShapeWorld::FScopedPassageTileQueries passageFeatureScope(
tileShape,queryMinimum,queryMaximum,
options.profilePassageComposer?&out.diagnostics:nullptr,key.lod,
options.diagnosticPassageSourceFloorVoxels);
options.diagnosticPassageSourceFloorVoxels,
options.diagnosticPassageCarveReachMetres);
if(options.profilePassageComposer)
{
out.diagnostics.passageComposerProfiled=true;
@@ -0,0 +1,68 @@
## Ranked findings
1. **[TRACE] The extra ~2 seconds are inside Core’s shape build.** Across the three final runs, SW’s `core_compile_start → core_bready` interval is **2.171, 2.157, and 2.038 s**; FI’s is **0.173, 0.184, and 0.187 s**. The median gap is **1.973 s**. [SW traces](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:24>), [FI traces](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.trace.jsonl:24>)
**[TRACE]** The SW `ShapeStage`’s median `sign_edge_distances` time is **1.942 s**, versus **8.8 ms** for FI. SW repairs **10,864,702** endpoint proxies, with **10,864,427** occupancy corrections; FI records zero endpoint proxies. Both compile **138,188,413 nodes** and use the same assembly, recipe, and plan hashes. [SW shape log](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.stdout.log:1376>), [FI shape log](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.stdout.log:1132>), [L92 hashes](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux92/REPORT.md:26>)
**[CODE]** `FStandaloneShapeWorld::Build` runs `ApplyDetailBand`, then `CompleteSignEdgeDistances`; the latter calls `AnalyticDensityAt` for missing edge samples. The parallel repair branch exists, but `parallelSignEdgeRepair` defaults to `false` and Unreal does not set it on this request. [Shape build](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3331>), [serial repair](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:12000>), [request default](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h:1592>), [Unreal request](</home/jahni/VoxelM/Plugins/VoxelForge/Private/VoxelWorld.cpp:7807>)
**[INFERENCE]** The dominant delay is serial sign-edge repair over the SW-start shape region. The different spawn heights support that explanation: SW starts at −200 m, within the SurfaceWorld stratum; FI starts at −737 m. **Falsifier:** an identical SW run showing sign-edge repair below roughly 100 ms, or showing that the repair is not part of `World::compile`, would overturn this attribution. [SW spawn](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:27>), [FI spawn](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.trace.jsonl:27>)
2. **[TRACE] The adapter’s route search is a separate ~0.45 s cost before compile launch.** In the measured SW run, serialization takes **466.957 ms**. The corresponding route logs span about **452 ms** from the failed legacy candidate set to the bounded-mouth candidate result; that fallback visits 78,408 candidates and ends with only three sweep attempts. [SW trace](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:17>), [SW route logs](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.log:928>)
**[CODE]** This runs in `BuildFiniteSurfaceRoute`, called while `BuildSurfaceStratumPlan` assembles the manifest inside `SerializeResolvedWorld`. It finishes before `core_compile_launch`; it cannot explain the launch-to-`bReady` interval. [Route search](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:445>), [plan call](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:839>), [manifest build](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:1635>), [compile launch](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:23>)
**[INFERENCE]** The route search explains much of the **shared** ~466–468 ms serialization cost in both FI and SW, but not why SW takes longer than FI after compile starts. The log span is strong attribution, though it is not a per-function timer. **Falsifier:** a direct timer showing the candidate loops take far less than 400 ms, or showing they fall outside the measured exporter interval.
3. **[CODE][TRACE] The “radius 6 / max clip 6” values are the Settings asset values, not the Core compile settings in these traces.** Core uses `CoreClipRadius=3` and `CoreMaxClipLevel=8`; the adapter writes those values into the snapshot, and the runtime log says `clip_radius=3 max_level=8`. The trace’s `settings_resolved` event reports the separate Settings values 6/6. [Core defaults](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Public/VoxelWorld.h:310>), [snapshot override](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:2104>), [trace Settings values](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:3>), [runtime Core values](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.log:932>)
**[INFERENCE]** Changing the legacy Settings radius to 3 would not fix this Core compile; it already uses 3. **Falsifier:** inspecting the Core snapshot actually consumed by `World` and finding radius 6 / max level 6.
4. **[CODE][TRACE] Far parents, recipe differences, and long validation do not explain this gap.** Unreal sets `Request.includeFarWorld=false`, and the SW logs report `far_parents=0.000 ms`; FI and SW also log the same assembly/recipe/plan hashes. Passage validation is about 1.2–1.7 ms. [Request](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:7807>), [far build condition](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:3339>), [SW shape stages](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.stdout.log:1379>)
**[INFERENCE]** Neither another plan path nor a debug/validation pass accounts for the 1.97 s FI/SW gap. **Falsifier:** a run with different plan hashes, nonzero far-parent time, or an unmeasured validation stage above hundreds of milliseconds.
## Trace arithmetic
**[TRACE]** These are direct subtractions of `core_compile_start.t_s` from `core_bready.t_s`:
| Arrival | Repeat 1 | Repeat 2 | Repeat 3 | Median |
|---|---:|---:|---:|---:|
| FI | `.742608 − .569354 = .173254 s` | `.749704 − .565919 = .183785 s` | `.796746 − .609896 = .186850 s` | `.183785 s` |
| SW | `2.780194 − .608768 = 2.171426 s` | `2.737530 − .580978 = 2.156552 s` | `2.616805 − .578886 = 2.037919 s` | `2.156552 s` |
[FI trace 1](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-1.trace.jsonl:24>), [FI trace 2](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-2.trace.jsonl:24>), [FI trace 3](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-3.trace.jsonl:24>), [SW trace 1](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:24>), [SW trace 2](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-2.trace.jsonl:24>), [SW trace 3](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.trace.jsonl:24>)
**[TRACE]** The reported `compile_s` values differ by at most about 26 μs because the code samples the duration just before recording the event timestamp. The SW run 1 trace then shows `bReady` at **2.780194 s**, first tile `request` at **2.794163 s**, and scheduler admission at **2.794603 s**. So the ~2.75 s table value is almost entirely the wait for `bReady`; the first per-tile request is about **14 ms** after readiness. [Ready sample](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:7886>), [SW events](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-1.trace.jsonl:422>)
**[TRACE]** The detailed logs match the Core trace: median FI `ShapeStage` is **183.527 ms**, median SW is **2,156.283 ms**; SW’s median sign-edge substage alone is **1,942.160 ms**. **Falsifier:** a trace/log pair with the same run identifiers but materially different `ShapeStage` and `core_bready` durations would break this mapping. [FI stage](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-fi-on-2.stdout.log:1137>), [SW stage](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-2.stdout.log:1377>)
## What `SerializeResolvedWorld` does
**[CODE]** `BeginPlay` calls `InitializeVoxelForgeCoreWorld` synchronously; that function calls `SerializeResolvedWorld` before converting the result to UTF-8 and calling Core’s `ResolvedWorldSnapshot::FromJson`. [BeginPlay](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:2720>), [export and parse](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelWorld.cpp:7658>)
**[CODE]** The exporter reflects over Settings and nested Voxel objects with `TFieldIterator<FProperty>`, handles arrays/maps/sets/structs, serializes resolved strata and passages, and synchronously loads terrain-operation assets. It then builds or imports a world assembly, rebuilds the resolved layout, writes canonical manifest JSON, parses that manifest back into an Unreal JSON object, and writes the full snapshot JSON. [Reflection](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:966>), [asset load](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:2172>), [manifest build](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:1565>), [JSON embed/write](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:2036>)
**[TRACE]** L92 measures the whole exporter at **465.6 ms FI / 468.0 ms SW** and `FromJson` at **18.9 / 19.3 ms**. The route-search logs align with about **452 ms** inside the SW exporter window, so generic asset reflection and JSON handling are not supported as the main cause of the 466 ms. Their individual shares were not timed. [L92 timing and attribution note](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux92/REPORT.md:9>), [SW route logs](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-3.log:928>)
**[CODE]** Core’s public snapshot API currently exposes `FromJson`, getters, and layout helpers; the snapshot’s data constructor is private. A direct handoff is possible with a new typed Core builder, but the adapter would still need to map the resolved Unreal assets into Core-owned data. [Snapshot API](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/include/VoxelForgeCore/VoxelForgeCore.h:1546>)
**[INFERENCE]** Direct typed construction could remove JSON encode/decode work, but it would not remove the route search. The measured ceiling for the parser plus the exporter’s non-route remainder is roughly **35 ms gross**; actual net savings may be smaller because a typed builder must still resolve and validate the owner data. **Falsifier:** a typed A/B that saves substantially more than that while generating the same plan would show unmeasured JSON work is larger than the current timing decomposition suggests.
**[CODE]** Running the existing exporter unchanged off-thread is unsafe: it reads Unreal `UObject` properties and calls `LoadSynchronous`. A split is possible: snapshot UObject-backed values on the game thread, then build the route/manifest from immutable Core inputs on a worker. **[INFERENCE]** That would reduce the game-thread hitch, but it will not reduce first-request wall time unless the work can overlap independent startup or use a precomputed manifest. **Falsifier:** a worker-thread run of the unchanged exporter that is shown safe for all UObject access and measurably reduces first admission without overlap.
## Smallest changes and measurements
1. **[INFERENCE] First SW experiment: enable the existing deterministic parallel sign-edge repair.** Set `Request.parallelSignEdgeRepair=true`; Core already has a parallel density evaluation path with sorted, deterministic publication. The current sign-edge stage is **1.94 s**, so that is the hard upper bound. L55 measured a different headless FI workload falling from **535 ms to 47 ms** with the same approach; using that ratio gives a rough SW estimate of **about 1.77 s saved**, not a result for this Unreal case. [Parallel implementation](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Core/src/ShapeWorldInternal.h:12103>), [prior L55 result](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux55/REPORT.md:56>)
**[INFERENCE]** Cheapest confirmation: A/B that one request flag at the same SW spawn and worker count; compare existing `sign_edge_distances`, `ShapeStage`, `core_bready`, and output hashes. Keep the serial path if the SW hashes differ or the stage barely moves. **Falsifier:** the paired run saves under roughly 100 ms, or changes the exact SW outputs.
2. **[INFERENCE] For the separate ~0.45 s exporter cost, use an already generated manifest through the existing override path when a seed/layout-matched artifact is available.** `AttachValidatedWorldAssembly` parses and validates an imported manifest instead of building `BuildSurfaceStratumPlan` and searching candidates; preserving the existing manifest hash preserves the route plan and does not change the passage composer. Expected saving is **about 0.4–0.45 s**, subject to the artifact matching the resolved seed and strata. [Override branch](</home/jahni/VoxelM/Plugins/VoxelForge/Source/VoxelForge/Private/VoxelForgeCoreAdapter.cpp:1577>)
**[INFERENCE]** Cheapest confirmation: one fixed-seed trace using the identical manifest; check that route-candidate logs disappear, hashes remain identical, and `SerializeResolvedWorld` falls by roughly the route-search span. **Falsifier:** the route search still runs, hashes change, or the exporter falls by much less than 0.4 s.
3. **[INFERENCE] Treat direct typed handoff as a small cleanup, not the startup fix.** It can target the roughly **19 ms** parse and some residual JSON work, but not the sign-edge repair or route search. **Falsifier:** a direct-builder A/B removes hundreds of milliseconds without changing route planning; that would show the current residual estimate is wrong.
4. **[TRACE][INFERENCE] Do not tune the legacy 6/6 clip values or raise the compile task priority as the first fix.** Core already runs 3/8, and launch-to-start queue delay is only **0.05–1.59 ms**; priority could still affect CPU progress, but the trace isolates a much larger serial substage. **Falsifier:** a same-input priority A/B materially reduces `sign_edge_distances` or the shape-stage wall time. [Task priority and queue delay](</home/jahni/VoxelM/Plugins/VoxelForge/Saved/Linux/l92/unreal-arrival/after-direct-json-sw-on-2.trace.jsonl:23>)
**[TRACE]** The headless L84/L86/L87 shape timings show that the compiler can finish in roughly **0.25–0.4 s** for those runs, but they do not falsify the R43 finding: R43’s SW camera hits the SurfaceWorld region and triggers the measured 10.9M serial sign corrections. **[INFERENCE]** A headless trace with the same request bounds, spawn, and repair mode would be the clean comparison. **Falsifier:** that matched headless run also takes about 2 s in `sign_edge_distances`. [L84](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux84/REPORT.md>), [L86](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux86/REPORT.md>), [L87](</home/jahni/VoxelM/Plugins/VoxelForge/Standalone/Research/WorldAssemblerM3/Linux87/REPORT.md>)
@@ -0,0 +1,66 @@
# Linux93 — explicit passage carve reach
## R and acceptance bar
Before measurement, the bar was: **zero sign flips, maximum surface displacement ≤1 cm, maximum normal change ≤2°, and all passage audits pass.**
I chose **R = 2.5 m beyond the tube surface**, with the final 0.5 m smoothly fading to identity. The code’s local terms are a 2.25 m positive-source reach floor and a 0.24 m wall-relief/source allowance (0.21 m relief plus 0.03 m margin); mouth-floor relief is separately capped at 0.20 m. Wider short-span decks and mouth/transition envelopes are separate paths, retained behind their existing feature guards. R is an experiment, not a proof that those separate envelopes fit inside the carve radius. I also measured R=1.5, 2.0 and 4.0 m.
The instrument reported `GenerateTile -> ApplyResolvedStrateComposition -> ApplyResolvedStratePassageCarves`, comparing density, mesh-edge crossings and normals. It did not use the L91 source-gradient probe. Each reach covered the full desired LOD0–2 set in S0/FI/TN/S3: 5,312 tiles and 174,736,448 samples per reach. Source stamp: `938a849b053aa7e5bc9bf5fcaf51a73590d408c15bc9d8f0564fec685e68921d`.
## Effect
Worst displacement and normal change are across all four strata; moved crossings and pairing failures are totals. Every row had zero sign flips and zero edge-crossing mismatches.
| R (m) | Moved crossings | Max displacement (cm) | Max normal change | Normal pairing failures | Bar |
|---:|---:|---:|---:|---:|---|
| 1.5 | 4,303 | 85.136 | 144.823° | 65 | Fail |
| 2.0 | 1,910 | 41.106 | 118.485° | 57 | Fail |
| 2.5 | 922 | 1.555 | 106.628° | 57 | Fail |
| 4.0 | 916 | 0.632 | 53.193° | 57 | Fail |
R=2.5 exceeds the displacement limit and misses the normal limit by a wide margin. R=4 meets the displacement limit but still fails normals. The effect audits completed with zero generation failures and zero invalid comparisons; full same-world passage audits were not run after this gate failed.
## Census and prototype
The L90 census was not rerun because the effect bar failed. The requested active-p90 (about 4–6) and fallback (<10%) stops therefore have no L93 measurements; the previous 10 m baseline was p90=13 and 18.28% fallback. The compiled evaluator prototype on `passage/1-2/0` was not started because it depends on a passing census.
## Bounded-only readiness
Cold headless runs compared default reach with R=2.5 m, L81 padding 0, and passage-composer profiling. Each mode had one warmup and three alternating measured pairs. Counts below are complete LOD0–2 near sets; times are medians in seconds.
| Stratum | W8 default → R=2.5 | W12 default → R=2.5 |
|---|---:|---:|
| S0 | 0.975 → 0.897 | 0.976 → 0.929 |
| FI | 2.354 → 2.307 | 2.181 → 2.158 |
| TN | 2.356 → 2.229 | 2.156 → 2.032 |
| S3 | 1.276 → 1.371 | 1.100 → 1.169 |
All runs completed their near sets: S0 1,408, FI 1,216, TN 1,344, S3 1,344 tiles. The work table sums the four per-stratum median counters. Positive deltas mean more counted work with bounded reach.
| Work counter | W8 default → R=2.5 (Δ) | W12 default → R=2.5 (Δ) |
|---|---:|---:|
| Tile-bound checks | 21,697,558 → 15,820,579 (−27.1%) | 23,141,444 → 15,820,579 (−31.6%) |
| Tile-bound rejects | 15,393,408 → 15,702,098 (+2.0%) | 16,114,028 → 15,702,098 (−2.6%) |
| Passage iterations skipped by tile bound | 46,180,224 → 47,106,294 (+2.0%) | 48,342,084 → 47,106,294 (−2.6%) |
| Negative-bound checks / rejects | 5,506,163 / 2,500,536 → 3,461,477 / 3,286,103 (checks −37.1%, rejects +31.4%) | 5,705,127 / 2,699,500 → 3,767,727 / 3,592,353 (checks −34.0%, rejects +33.1%) |
| Passage iterations | 33,137,208 → 32,209,659 (−2.8%) | 38,207,001 → 39,438,384 (+3.2%) |
| Carve segment visits | 78,166,733 → 77,908,735 (−0.3%) | 101,322,676 → 106,806,150 (+5.4%) |
| Support segment visits | 31,466,498 → 30,406,353 (−3.4%) | 37,630,363 → 38,810,022 (+3.1%) |
| Mouth route checks | 38,701,878 → 37,198,938 (−3.9%) | 47,097,975 → 47,996,583 (+1.9%) |
| Relief field calls | 56,100,413 → 51,745,464 (−7.8%) | 66,227,624 → 64,386,389 (−2.8%) |
The skip counters do not show a consistent work reduction: several active-loop counters rise at W12, and S3 readiness regresses at both worker counts. This is not a readiness win.
## Same-world evidence and disposition
The bounded candidate is rejected. No candidate peer-hash comparison at W1/W8/W12 or across Clang/GCC, bounded passage-audit suite, mouth/mid-tunnel captures, version bump, or hash repin was done. The evaluator remains version 214 and the default reach remains unbounded. The Clang fast tier on the default path passed: 274 checks, 269 PASS and 5 expected diagnostics, in 285.9 s; its W1/W8/W12 checks matched. Standalone diagnostic builds took 65.49 s (Clang) and 89.39 s (GCC). No Unreal source changed, so no Unreal build was run.
## Failed and superseded runs
- The first fast-tier launch stopped before tests because its expected binary did not exist. After building the stamped binaries, the fast tier passed.
- An early readiness parser incorrectly required a composer-profile row for every near tile; the profiler emits rows only for active tiles. The parser was corrected and the final matrix validated complete near-tile coverage. Earlier fixed-5 m support-floor readiness data is superseded and excluded.
- Final effect runs completed but intentionally reported FAIL against the stated effect bar. No run exceeded 30 minutes.
- Build, headless measurement and verifier processes were pinned to CPUs 0–11; headless runs also had the 6 GiB address-space limit. A few read-only status/source/JSON inspection commands during consolidation were not pinned. No measurement or build ran in those commands.
Logs and machine-readable summaries are under `Saved/Linux/l93/`.
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
"""L80-style cold near-readiness A/B for the bounded carve and L81 reach skip."""
from __future__ import annotations
import argparse
import json
import re
import statistics
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l93/readiness"
DATA = ROOT / "Standalone/data/owner_world.json"
BINARY = ROOT / "Saved/Linux/l93/bin/VoxelForgeCoreHeadless-clang19"
STRATA = {
"S0": {"id": 0, "camera": (8.0, 16.0, -372.2626953125), "near": 1408},
"FI": {"id": 1, "camera": (25.8369140625, 3.19921875, -737.0), "near": 1216},
"TN": {"id": 2, "camera": (19.166015625, -14.2001953125, -753.3740234375), "near": 1344},
"S3": {"id": 3, "camera": (-20.0625, -5.068359375, -900.353515625), "near": 1344},
}
MODES = {"unbounded": "0", "bounded": "2.5"}
PIPELINE = re.compile(r"^\[StreamPipeline\] (.*)$", re.M)
NEAR = re.compile(r"^\[WorldAssemblerNearLODReady\] lods=0-2 tiles=(\d+)/(\d+) "
r"cold_ready_s=([0-9.]+)$", re.M)
PROFILE = re.compile(r"^\[PassageComposerTile\] key=\((-?\d+),(-?\d+),(-?\d+),lod(\d+)\) (.*)$", re.M)
FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)")
WORK_FIELDS = (
"samples", "queries", "passage_iterations", "tile_bound_checks",
"tile_bound_rejects", "tile_bound_skipped_iterations", "negative_bounds",
"negative_rejects", "positive_bounds", "positive_rejects",
"carve_segment_visits", "support_segment_visits", "support_capsule_checks",
"later_bore_checks", "other_capsule_checks", "mouth_route_segment_checks",
"relief_field_calls", "smoothstep_evaluations",
)
def parse_fields(line: str) -> dict[str, str]:
return dict(FIELDS.findall(line))
def run(stratum: str, workers: int, mode: str, phase: str, replicate: int) -> dict:
OUT.mkdir(parents=True, exist_ok=True)
spec = STRATA[stratum]
label = f"{stratum.lower()}-w{workers}-{mode}-{phase}{replicate}"
log = OUT / f"{label}.log"
camera = ",".join(f"{value:.12f}" for value in spec["camera"]) + ",0,0"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", "env",
f"VOXELFORGE_L93_PASSAGE_CARVE_REACH_METRES={MODES[mode]}",
"VOXELFORGE_L81_PASSAGE_BOUND_PADDING_VOXELS=0", "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}",
"--profile-lod-work", "--profile-passage-composer",
"--stream-scheduler-policy=3",
]
start = time.monotonic()
try:
with log.open("w", encoding="utf-8") as stream:
proc = subprocess.run(command, cwd=ROOT, stdout=stream,
stderr=subprocess.STDOUT, check=False, timeout=1750)
except subprocess.TimeoutExpired as exc:
raise RuntimeError(f"readiness run exceeded 1,750 seconds: {log}") from exc
output = log.read_text(encoding="utf-8", errors="replace")
near = NEAR.search(output)
pipeline = PIPELINE.search(output)
if proc.returncode or near is None or pipeline is None:
raise RuntimeError(f"readiness run failed or required output missing: {log}; exit={proc.returncode}")
pipeline_fields = parse_fields(pipeline.group(1))
by_key: dict[tuple[int, int, int, int], dict[str, int]] = {}
for match in PROFILE.finditer(output):
key = tuple(int(value) for value in match.groups()[:4])
if key[3] > 2:
continue
fields = parse_fields(match.group(5))
by_key[key] = {name: int(fields.get(name, "0")) for name in WORK_FIELDS}
work = {name: sum(values[name] for values in by_key.values()) for name in WORK_FIELDS}
expected = spec["near"]
row = {
"stratum": stratum, "workers": workers, "mode": mode,
"phase": phase, "replicate": replicate, "exit_code": proc.returncode,
"wall_s": round(time.monotonic() - start, 3),
"lod02_ready_s": float(near.group(3)),
"near_tiles": f"{near.group(1)}/{near.group(2)}",
"expected_near_tiles": expected,
"profiled_near_tiles": len(by_key),
"unprofiled_near_tiles": max(0, expected - len(by_key)),
"whole_view_ready_s": float(pipeline_fields["whole_view_ready"].removesuffix("s")),
"whole_tiles": int(pipeline_fields["whole_tiles"].split("/")[0]),
"work": work,
"log": str(log.relative_to(ROOT)),
}
print("[L93BoundedReadinessRun] " + json.dumps(row, sort_keys=True), flush=True)
return row
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--stratum", choices=tuple(STRATA), required=True)
parser.add_argument("--workers", choices=(8, 12), type=int, required=True)
args = parser.parse_args()
if not BINARY.is_file() or not DATA.is_file():
raise SystemExit(f"missing input: {BINARY} or {DATA}")
rows = []
for mode in MODES:
run(args.stratum, args.workers, mode, "warmup", 0)
orders = (("unbounded", "bounded"), ("bounded", "unbounded"),
("unbounded", "bounded"))
for replicate, order in enumerate(orders, 1):
for mode in order:
rows.append(run(args.stratum, args.workers, mode, "measured", replicate))
(OUT / f"runs-partial-{args.stratum.lower()}-w{args.workers}.json").write_text(
json.dumps(rows, indent=2) + "\n", encoding="utf-8")
summary = {"stratum": args.stratum, "workers": args.workers,
"measured_pairs": 3, "runs": rows}
for mode in MODES:
subset = [row for row in rows if row["mode"] == mode]
summary[f"{mode}_lod02_ready_s"] = [row["lod02_ready_s"] for row in subset]
summary[f"{mode}_lod02_ready_median_s"] = statistics.median(
row["lod02_ready_s"] for row in subset)
summary[f"{mode}_whole_ready_s"] = [row["whole_view_ready_s"] for row in subset]
summary[f"{mode}_whole_ready_median_s"] = statistics.median(
row["whole_view_ready_s"] for row in subset)
summary[f"{mode}_work_median"] = {
name: statistics.median(row["work"][name] for row in subset)
for name in WORK_FIELDS}
path = OUT / f"summary-{args.stratum.lower()}-w{args.workers}.json"
path.write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8")
print("[L93BoundedReadinessSummary] " + json.dumps(summary, sort_keys=True), flush=True)
valid = all(row["near_tiles"].split("/") == [str(row["expected_near_tiles"])] * 2
and 0 < row["profiled_near_tiles"] <= row["expected_near_tiles"]
for row in rows)
return 0 if valid else 14
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""Compare bounded passage-carve reaches over each owner's complete near view."""
from __future__ import annotations
import json
import argparse
import re
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
OUT = ROOT / "Saved/Linux/l93/effects"
DATA = ROOT / "Standalone/data/owner_world.json"
BINARY = ROOT / "Saved/Linux/l93/bin/VoxelForgeCoreHeadless-clang19"
STRATA = {
"S0": {"camera": (8.0, 16.0, -372.2626953125), "near": 1408},
"FI": {"camera": (25.8369140625, 3.19921875, -737.0), "near": 1216},
"TN": {"camera": (19.166015625, -14.2001953125, -753.3740234375), "near": 1344},
"S3": {"camera": (-20.0625, -5.068359375, -900.353515625), "near": 1344},
}
REACHES = (1.5, 2.0, 2.5, 4.0)
STAMP = re.compile(r"^\[VoxelForgeSourceStamp\] sha256=(\S+)$", re.M)
COVERAGE = re.compile(r"^\[L93PassageReachCoverage\] (.*)$", re.M)
SUMMARY = re.compile(r"^\[L93PassageReachSummary\] (.*)$", re.M)
AUDIT = re.compile(r"^\[L93PassageReachAudit\] (.*)$", re.M)
FIELDS = re.compile(r"([a-zA-Z0-9_]+)=([^ ]+)")
def parse_fields(line: str) -> dict[str, str]:
return dict(FIELDS.findall(line))
def run(stratum: str) -> dict:
OUT.mkdir(parents=True, exist_ok=True)
spec = STRATA[stratum]
camera = ",".join(f"{value:.12f}" for value in spec["camera"]) + ",0,0"
log = OUT / f"{stratum.lower()}-reach-effects.log"
command = [
"taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", "env",
"VOXELFORGE_L81_PASSAGE_BOUND_PADDING_VOXELS=0", "timeout", "1740s",
str(BINARY), str(DATA), "--world-assembler-prototype", "--stream-benchmark",
"--stream-pipeline", "--workers=8", "--clip-radius=3", "--max-clip-level=8",
"--max-level=2", f"--camera={camera}", "--audit-passage-carve-reach",
]
started = time.monotonic()
try:
with log.open("w", encoding="utf-8") as stream:
proc = subprocess.run(command, cwd=ROOT, stdout=stream,
stderr=subprocess.STDOUT, check=False, timeout=1750)
except subprocess.TimeoutExpired as exc:
raise RuntimeError(f"reach effect audit exceeded 1,750 seconds: {log}") from exc
output = log.read_text(encoding="utf-8", errors="replace")
coverage = COVERAGE.search(output)
summaries = [parse_fields(match.group(1)) for match in SUMMARY.finditer(output)]
audit = AUDIT.search(output)
stamp = STAMP.search(output)
expected = spec["near"]
coverage_fields = parse_fields(coverage.group(1)) if coverage else {}
coverage_ok = (int(coverage_fields.get("tiles", "0")) == expected
and int(coverage_fields.get("lod0", "0"))
+ int(coverage_fields.get("lod1", "0"))
+ int(coverage_fields.get("lod2", "0")) == expected)
rows = []
for summary in summaries:
reach = float(summary["reach_m"])
tile_counts = summary["tiles"].split("/")
passed = (len(tile_counts) == 2 and int(tile_counts[0]) == expected
and int(tile_counts[1]) == expected
and summary["status"] == "PASS")
rows.append({
"reach_m": reach,
"tiles": summary["tiles"],
"samples": int(summary["samples"]),
"changed_samples": int(summary["changed_samples"]),
"sign_flips": int(summary["sign_flips"]),
"edge_crossing_mismatches": int(summary["edge_crossing_mismatches"]),
"moved_crossings": int(summary["moved_crossings"]),
"max_displacement_cm": float(summary["max_displacement_cm"]),
"max_normal_degrees": float(summary["max_normal_degrees"]),
"normal_pairing_failures": int(summary["normal_pairing_failures"]),
"status": "PASS" if passed else "FAIL",
})
row = {
"stratum": stratum,
"exit_code": proc.returncode,
"wall_s": round(time.monotonic() - started, 3),
"expected_near_tiles": expected,
"coverage": coverage_fields or None,
"coverage_ok": coverage_ok,
"reaches": rows,
"audit": parse_fields(audit.group(1)) if audit else None,
"source_stamp": stamp.group(1) if stamp else None,
"log": str(log.relative_to(ROOT)),
}
(OUT / f"{stratum.lower()}-reach-effects.json").write_text(
json.dumps(row, indent=2) + "\n", encoding="utf-8")
print("[L93CarveReachRun] " + json.dumps(row, sort_keys=True), flush=True)
return row
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--stratum", choices=tuple(STRATA), required=True)
args = parser.parse_args()
if not BINARY.is_file() or not DATA.is_file():
raise SystemExit(f"missing input: {BINARY} or {DATA}")
rows = [run(args.stratum)]
summaries: dict[str, dict] = {}
for reach in REACHES:
samples = [row for run_row in rows for row in run_row["reaches"]
if row["reach_m"] == reach]
summaries[f"{reach:g}"] = {
"strata": len(samples),
"sign_flips": sum(row["sign_flips"] for row in samples),
"edge_crossing_mismatches": sum(row["edge_crossing_mismatches"] for row in samples),
"max_displacement_cm": max((row["max_displacement_cm"] for row in samples), default=0.0),
"max_normal_degrees": max((row["max_normal_degrees"] for row in samples), default=0.0),
"normal_pairing_failures": sum(row["normal_pairing_failures"] for row in samples),
"changed_samples": sum(row["changed_samples"] for row in samples),
"status": "PASS" if len(samples) == len(rows)
and all(row["status"] == "PASS" for row in samples) else "FAIL",
}
result = {"runs": rows, "reach_summary": summaries}
(OUT / f"summary-{args.stratum.lower()}.json").write_text(
json.dumps(result, indent=2) + "\n", encoding="utf-8")
print("[L93CarveReachSummary] " + json.dumps(result, sort_keys=True), flush=True)
return 0 if all(row["coverage_ok"] and row["source_stamp"]
and row["audit"] and row["audit"].get("status") == "PASS"
for row in rows) and all(item["status"] == "PASS"
for item in summaries.values()) else 14
if __name__ == "__main__":
raise SystemExit(main())
@@ -60,6 +60,7 @@ namespace
bool AuditBasePageEquivalence=false;
bool AuditRouteParity=false;
bool AuditPassageSourceClamp=false;
bool AuditPassageCarveReach=false;
bool RegionCrossing=false;
bool AuditTileShapeReadiness=false;
int DiagnosticSlowShapeCompileMs=0;
@@ -1462,6 +1463,7 @@ namespace
" --audit-base-page-equivalence (hash one tile through both shape routes)\n"
" --audit-route-parity (compare page, native-only, exact-query and mesh routes)\n"
" --audit-passage-source-clamp (compare passage source floors 2,3,4,6 over all near tiles)\n"
" --audit-passage-carve-reach (compare post-composer reaches 1.5,2,2.5,4 m over all near tiles)\n"
" --audit-tile-shape-readiness (run a deliberately mis-marked tile against the native-only guard)\n"
" --diagnostic-slow-shape-compile-ms=N (diagnostic overlap control; default 0)\n"
" --render-distance-chunks=N (0 disables the extra far ring)\n"
@@ -1539,6 +1541,7 @@ namespace
else if(arg=="--audit-base-page-equivalence")options.AuditBasePageEquivalence=true;
else if(arg=="--audit-route-parity")options.AuditRouteParity=true;
else if(arg=="--audit-passage-source-clamp")options.AuditPassageSourceClamp=true;
else if(arg=="--audit-passage-carve-reach")options.AuditPassageCarveReach=true;
else if(arg=="--region-crossing")options.RegionCrossing=true;
else if(arg=="--audit-tile-shape-readiness")options.AuditTileShapeReadiness=true;
else if(arg=="--auto-surface-camera")options.AutoSurfaceCamera=true;
@@ -2280,5 +2283,5 @@ int main(int argc,char** argv)
options.StreamingSchedulerPolicy,options.MovingCameraTrace,
options.MovingCameraSpeedMetersPerSecond,options.MovingCameraDurationSeconds,
options.MovingCameraDwellSeconds,options.ColdWorkerTimeline,
options.AuditPassageSourceClamp);
options.AuditPassageSourceClamp,options.AuditPassageCarveReach);
}
+49 -21
View File
@@ -386,9 +386,22 @@ namespace StandaloneStreamBenchmark
inline int AuditPassageSourceClamp(VoxelForgeCore::World& Shape,
const FStandaloneDesiredTileSet& Desired,
const VoxelForgeCore::ResolvedLayoutSnapshotV3* Layout,
std::uint32_t CoreVoxelSizeMicrons)
std::uint32_t CoreVoxelSizeMicrons,bool bAuditCarveReach=false)
{
constexpr std::array<double,4> Floors={2.0,3.0,4.0,6.0};
constexpr std::array<double,4> SourceFloors={2.0,3.0,4.0,6.0};
constexpr std::array<double,4> CarveReaches={1.5,2.0,2.5,4.0};
const auto& Candidates=bAuditCarveReach?CarveReaches:SourceFloors;
const char* const valueName=bAuditCarveReach?"reach_m":"floor_vox";
const char* const coverageTag=bAuditCarveReach
?"L93PassageReachCoverage":"L91PassageClampCoverage";
const char* const tileTag=bAuditCarveReach
?"L93PassageReachTile":"L91PassageClampTile";
const char* const tileFailureTag=bAuditCarveReach
?"L93PassageReachTileFailure":"L91PassageClampTileFailure";
const char* const summaryTag=bAuditCarveReach
?"L93PassageReachSummary":"L91PassageClampSummary";
const char* const auditTag=bAuditCarveReach
?"L93PassageReachAudit":"L91PassageClampAudit";
std::vector<VoxelForgeCore::TileKey> keys;
std::array<std::uint64_t,3> expectedByLod{};
for(const FVoxelTileKey& tile:Desired.Tiles)
@@ -399,10 +412,11 @@ namespace StandaloneStreamBenchmark
}
if(keys.empty())
{
std::printf("[L91PassageClampAudit] status=FAIL reason=no_lod0_2_tiles\n");
std::printf("[%s] status=FAIL reason=no_lod0_2_tiles\n",auditTag);
return 14;
}
std::printf("[L91PassageClampCoverage] tiles=%zu lod0=%llu lod1=%llu lod2=%llu mode=full_desired_near_set\n",
std::printf("[%s] tiles=%zu lod0=%llu lod1=%llu lod2=%llu mode=full_desired_near_set\n",
coverageTag,
keys.size(),static_cast<unsigned long long>(expectedByLod[0]),
static_cast<unsigned long long>(expectedByLod[1]),
static_cast<unsigned long long>(expectedByLod[2]));
@@ -412,6 +426,8 @@ namespace StandaloneStreamBenchmark
baseOptions.forceFullDensityCapture=true;
baseOptions.skipUvAndColors=true;
baseOptions.skipMaterialGroups=true;
baseOptions.diagnosticPassageSourceFloorVoxels=0.0;
baseOptions.diagnosticPassageCarveReachMetres=0.0;
VoxelForgeCore::TileGenerationOptions candidateOptions=baseOptions;
candidateOptions.profilePassageComposer=true;
std::array<std::uint64_t,4> tileCount{},sampleCount{},changedSamples{},signFlips{},
@@ -429,22 +445,27 @@ namespace StandaloneStreamBenchmark
if(!base)
{
++generationFailures;
std::printf("[L91PassageClampTileFailure] mode=base key=(%d,%d,%d,lod%d) error=%s\n",
key.coordinate.x,key.coordinate.y,key.coordinate.z,key.lod,error.c_str());
std::printf("[%s] mode=base key=(%d,%d,%d,lod%d) error=%s\n",
tileFailureTag,key.coordinate.x,key.coordinate.y,key.coordinate.z,
key.lod,error.c_str());
continue;
}
if(!bAuditCarveReach)
GatherPassageSourceGradients(Shape,*base,Layout,gradientStats);
for(std::size_t floorIndex=0;floorIndex<Floors.size();++floorIndex)
for(std::size_t floorIndex=0;floorIndex<Candidates.size();++floorIndex)
{
candidateOptions.diagnosticPassageSourceFloorVoxels=Floors[floorIndex];
if(bAuditCarveReach)
candidateOptions.diagnosticPassageCarveReachMetres=Candidates[floorIndex];
else
candidateOptions.diagnosticPassageSourceFloorVoxels=Candidates[floorIndex];
error.clear();
const auto candidate=Shape.generateTile(key,candidateOptions,error);
if(!candidate)
{
++generationFailures;
std::printf("[L91PassageClampTileFailure] floor_vox=%.0f key=(%d,%d,%d,lod%d) error=%s\n",
Floors[floorIndex],key.coordinate.x,key.coordinate.y,key.coordinate.z,
key.lod,error.c_str());
std::printf("[%s] %s=%.2f key=(%d,%d,%d,lod%d) error=%s\n",
tileFailureTag,valueName,Candidates[floorIndex],key.coordinate.x,
key.coordinate.y,key.coordinate.z,key.lod,error.c_str());
continue;
}
const FPassageClampComparison comparison=ComparePassageClampMeshes(
@@ -476,8 +497,9 @@ namespace StandaloneStreamBenchmark
movedRegions[floorIndex][region]+=comparison.movedEdgeRegions[region];
normalRegions[floorIndex][region]+=comparison.normalVertexRegions[region];
}
std::printf("[L91PassageClampTile] floor_vox=%.0f key=(%d,%d,%d,lod%d) samples=%llu changed=%llu sign_flips=%llu moved_edges=%llu max_displacement_cm=%.6g normal_vertices=%llu max_normal_degrees=%.6g changed_mesh=%d\n",
Floors[floorIndex],key.coordinate.x,key.coordinate.y,key.coordinate.z,key.lod,
std::printf("[%s] %s=%.2f key=(%d,%d,%d,lod%d) samples=%llu changed=%llu sign_flips=%llu moved_edges=%llu max_displacement_cm=%.6g normal_vertices=%llu max_normal_degrees=%.6g changed_mesh=%d\n",
tileTag,valueName,Candidates[floorIndex],key.coordinate.x,
key.coordinate.y,key.coordinate.z,key.lod,
static_cast<unsigned long long>(comparison.samples),
static_cast<unsigned long long>(comparison.changedSamples),
static_cast<unsigned long long>(comparison.signFlips),
@@ -489,7 +511,7 @@ namespace StandaloneStreamBenchmark
}
bool acceptedAtAllFloors=generationFailures==0&&invalidComparisons==0
&&keys.size()>0;
for(std::size_t floorIndex=0;floorIndex<Floors.size();++floorIndex)
for(std::size_t floorIndex=0;floorIndex<Candidates.size();++floorIndex)
{
const double meanDisplacement=sharedCrossings[floorIndex]
?sumDisplacementCm[floorIndex]/sharedCrossings[floorIndex]:0.0;
@@ -501,8 +523,9 @@ namespace StandaloneStreamBenchmark
&&maxNormalAngle[floorIndex]<=2.0
&&normalPairingFailures[floorIndex]==0;
acceptedAtAllFloors=acceptedAtAllFloors&&accepted;
std::printf("[L91PassageClampSummary] floor_vox=%.0f tiles=%llu/%zu samples=%llu changed_samples=%llu sign_flips=%llu edge_crossing_mismatches=%llu shared_crossings=%llu moved_crossings=%llu max_displacement_cm=%.6g mean_displacement_cm=%.6g changed_mesh_tiles=%llu normal_vertices=%llu changed_normal_vertices=%llu max_normal_degrees=%.6g mean_normal_degrees=%.6g normal_pairing_failures=%llu moved_regions=(wall:%llu,floor:%llu,mouth:%llu,other:%llu) normal_regions=(wall:%llu,floor:%llu,mouth:%llu,other:%llu) status=%s\n",
Floors[floorIndex],static_cast<unsigned long long>(tileCount[floorIndex]),
std::printf("[%s] %s=%.2f tiles=%llu/%zu samples=%llu changed_samples=%llu sign_flips=%llu edge_crossing_mismatches=%llu shared_crossings=%llu moved_crossings=%llu max_displacement_cm=%.6g mean_displacement_cm=%.6g changed_mesh_tiles=%llu normal_vertices=%llu changed_normal_vertices=%llu max_normal_degrees=%.6g mean_normal_degrees=%.6g normal_pairing_failures=%llu moved_regions=(wall:%llu,floor:%llu,mouth:%llu,other:%llu) normal_regions=(wall:%llu,floor:%llu,mouth:%llu,other:%llu) status=%s\n",
summaryTag,valueName,Candidates[floorIndex],
static_cast<unsigned long long>(tileCount[floorIndex]),
keys.size(),static_cast<unsigned long long>(sampleCount[floorIndex]),
static_cast<unsigned long long>(changedSamples[floorIndex]),
static_cast<unsigned long long>(signFlips[floorIndex]),
@@ -538,6 +561,7 @@ namespace StandaloneStreamBenchmark
std::accumulate(gradientStats.gradientMagnitudes.begin(),
gradientStats.gradientMagnitudes.end(),0.0)
/gradientStats.gradientMagnitudes.size();
if(!bAuditCarveReach)
std::printf("[L91PassageSourceGradient] surface_source_crossings=%llu sampled_near_zero=%llu gradient_samples=%zu step_vox=1 source_abs_limit_vox=2 p50=%.6g p90=%.6g max=%.6g mean=%.6g status=%s\n",
static_cast<unsigned long long>(gradientStats.candidateCrossings),
static_cast<unsigned long long>(gradientStats.sourceNearZeroSamples),
@@ -545,7 +569,10 @@ namespace StandaloneStreamBenchmark
percentile(gradientStats.gradientMagnitudes,0.9),
gradientStats.gradientMagnitudes.empty()?0.0:gradientStats.gradientMagnitudes.back(),
gradientMean,gradientStats.gradientMagnitudes.size()>=64?"MEASURED":"LOW_SAMPLE");
std::printf("[L91PassageClampAudit] tiles=%zu generation_failures=%llu invalid_comparisons=%llu status=%s\n",
if(bAuditCarveReach)
std::printf("[L93PassageReachInstrument] path=GenerateTile_to_ApplyResolvedStrateComposition_to_ApplyResolvedStratePassageCarves stage=post_rough_sdf_max blend=0.5m transition=identity_outside_reach support_mouth_deferred=unchanged comparison=paired_density_mesh_edges_normals\n");
std::printf("[%s] tiles=%zu generation_failures=%llu invalid_comparisons=%llu bar=sign_flips_0_displacement_cm_le_1_normal_degrees_le_2 status=%s\n",
auditTag,
keys.size(),static_cast<unsigned long long>(generationFailures),
static_cast<unsigned long long>(invalidComparisons),
acceptedAtAllFloors?"PASS":"FAIL");
@@ -2305,7 +2332,8 @@ namespace StandaloneStreamBenchmark
bool bLinux77Profile=false,int32 SchedulerPolicy=-1,
bool bMovingCameraTrace=false,double MovingCameraSpeedMetersPerSecond=0.0,
double MovingCameraDurationSeconds=12.0,double MovingCameraDwellSeconds=5.0,
bool bColdWorkerTimeline=false,bool bAuditPassageSourceClamp=false)
bool bColdWorkerTimeline=false,bool bAuditPassageSourceClamp=false,
bool bAuditPassageCarveReach=false)
{
using Clock=std::chrono::steady_clock;
const std::clock_t ColdCpuOrigin=std::clock();
@@ -2475,7 +2503,7 @@ namespace StandaloneStreamBenchmark
||bAuditOreVeinYield||bAuditLandmarkReachability||bAuditStrateTransitions
||bAuditResolvedLayoutPassages||bAuditResolvedLayoutBoundaries
||bAuditTileShapeReadiness||bAuditBasePageEquivalence||bAuditRouteParity
||bAuditPassageSourceClamp;
||bAuditPassageSourceClamp||bAuditPassageCarveReach;
const bool bDeferFarWorld=bIncludeFarWorld&&!bMovingCameraTrace&&!bFarWorldAudit;
VoxelForgeCore::ShapeBuildRequest ShapeRequest;
ShapeRequest.minVoxel={FineMin.X,FineMin.Y,FineMin.Z};
@@ -2555,11 +2583,11 @@ namespace StandaloneStreamBenchmark
Streamer.Stop();
std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;
}
if(bAuditPassageSourceClamp)
if(bAuditPassageSourceClamp||bAuditPassageCarveReach)
{
Streamer.Stop();
return AuditPassageSourceClamp(Shape,Desired,ResolvedLayout,
World.CoreVoxelSizeMicrons);
World.CoreVoxelSizeMicrons,bAuditPassageCarveReach);
}
if(bAuditNativeCaves)
{