perf(generation): exact reach gating for the tunnel core (per tile) and passage carving (per 8^3 block)
Applies ce4d878's decide-once-then-prove pattern to the two largest exact targets from the re-rank
(tunnel core 20.8%, passage carving 9.1%). Codex; reviewed by me.
Measured first, where the time is:
core world: far 223,860 vs near 35,515,979 cycles -> tile gate only; the core is
near-dominated (~99%)
core tail: far 363,440 vs near 20,110,219
passage, tile: far 7,315,426 vs near 30,168,796 -> refined to an 8^3 block gate
passage, 8^3: far 11,233,384 vs near 26,250,838
The core already uses the tunnel spatial index. An exact skip cannot remove its cost: that cost is
in tiles near tunnels. The remaining lever there is the field-changing SDF/core merge (next).
- Core reach per tile, from lattice plus halo: swept capsule reach, floor band, floor-profile
deviation, relief bound, room-mouth ownership. The GetDensityAt tail is identity unless
bSupportFloor, bRoomFloor or CoreSDF < -inset.
- Passage carving per 8^3 block: capsule-chain and landing-room domains, the carve threshold and
the SmoothMin K/6 margin. Malformed descriptors stay candidates (conservative).
- voxel.TileReachCostDiagnostics (default 0) for the far/near cost split.
Soundness: the final-field debug comparison ran 130,285,889 comparisons with 0 differences; shrunk
reach (0.5) produced 140,035 differences (60,098 in the final field) and failed as required.
Field exact: canonical 07C14005 / b3e5f4c3..9b377, 64/64 per-tile ledger identical, capability
20,830 / 10,909, strate-crossing and sealed-proof tests pass.
Final DEFAULT build vs the committed-tip DLL (same command line, two interleaved runs each):
static worker 28.84 -> 28.10 s (-2.6%) LOD0 p50 53.3 -> 51.5 ms p95 94.4 -> 93.1 ms
moving worker 61.39 -> 60.61 s (-1.3%) LOD0 p50 50.9 -> 49.7 ms p95 92.21 -> 92.27 ms (flat,
+0.06%, within noise)
Maintenance note: these reach proofs must track tunnel/passage geometry. The next round adds an
automation test for the final-field comparison so a geometry change cannot silently break them.
Ledger: 15 builds (one C2065 fixed, one access-denied path retry); rejected TileOnly/BlockLookup
variants were slower; one hung diagnostic (a non-owner PID) was stopped; wrapper quoting failures
launched no editor. No crash folders.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaFdXhTdYMkW1xrV6ApT6Y
This commit is contained in:
1 parent
0208e93606
commit
a668833ef5
8 files changed
+1062
-30
No files matched your search
@@ -33,6 +33,12 @@ namespace
|
||||
TEXT("Scale the per-tile post reach for deliberate soundness tests. Default 1.0 is exact; "
|
||||
"values below 1 intentionally shrink the guard."));
|
||||
|
||||
int32 GVoxelForgeTileReachCostDiagnostics = 0;
|
||||
FAutoConsoleVariableRef CVarVoxelForgeTileReachCostDiagnostics(
|
||||
TEXT("voxel.TileReachCostDiagnostics"),
|
||||
GVoxelForgeTileReachCostDiagnostics,
|
||||
TEXT("Measure core/passage density cost split by tile reach; no field gate."));
|
||||
|
||||
bool GVoxelForgeTilePostReachSwitchesParsed = false;
|
||||
|
||||
void VF_ParseTilePostReachSwitches()
|
||||
@@ -44,18 +50,24 @@ namespace
|
||||
GVoxelForgeTilePostReachSwitchesParsed = true;
|
||||
int32 DebugValue = GVoxelForgeTilePostReachDebug;
|
||||
float ScaleValue = GVoxelForgeTilePostReachScale;
|
||||
int32 CostDiagnosticsValue = GVoxelForgeTileReachCostDiagnostics;
|
||||
FParse::Value(
|
||||
FCommandLine::Get(), TEXT("voxel.TilePostReachDebug="), DebugValue);
|
||||
FParse::Value(
|
||||
FCommandLine::Get(), TEXT("voxel.TilePostReachScale="), ScaleValue);
|
||||
FParse::Value(
|
||||
FCommandLine::Get(), TEXT("voxel.TileReachCostDiagnostics="), CostDiagnosticsValue);
|
||||
GVoxelForgeTilePostReachDebug = DebugValue != 0 ? 1 : 0;
|
||||
if (!VoxelMath::IsFinite(ScaleValue) || ScaleValue <= 0.0f)
|
||||
{
|
||||
ScaleValue = 1.0f;
|
||||
}
|
||||
GVoxelForgeTilePostReachScale = FMath::Min(ScaleValue, 1.0f);
|
||||
GVoxelForgeTileReachCostDiagnostics = CostDiagnosticsValue != 0 ? 1 : 0;
|
||||
VoxelGenLOD::GTilePostReachDebugEnabled.store(
|
||||
GVoxelForgeTilePostReachDebug != 0, std::memory_order_relaxed);
|
||||
VoxelGenLOD::GTileReachCostDiagnosticsEnabled.store(
|
||||
GVoxelForgeTileReachCostDiagnostics != 0, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void VF_ParseOperatorBlockSwitch()
|
||||
@@ -284,6 +296,23 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
GVoxelForgeTilePostReachDebug != 0);
|
||||
TGuardValue<bool> TilePostReachBypassGuard(
|
||||
VoxelGenLOD::bTilePostReachBypass, false);
|
||||
TGuardValue<bool> TileReachDiagnosticGuard(
|
||||
VoxelGenLOD::bTileReachDiagnosticTile, true);
|
||||
TGuardValue<bool> TileCoreReachProofGuard(
|
||||
VoxelGenLOD::bTileCoreReachProofEnabled, false);
|
||||
TGuardValue<bool> TileCoreReachDecisionGuard(
|
||||
VoxelGenLOD::bTileCoreReachDecisionRecorded, false);
|
||||
TGuardValue<float> TileReachScaleGuard(
|
||||
VoxelGenLOD::TileReachScale, GVoxelForgeTilePostReachScale);
|
||||
const float ReachScale = GVoxelForgeTilePostReachScale;
|
||||
const int32 ReachBlocksPerAxis = FMath::DivideAndRoundUp(
|
||||
CellsPerAxis, VoxelGenLOD::TileReachBlockCells);
|
||||
TGuardValue<int32> TileReachBlocksGuard(
|
||||
VoxelGenLOD::TileReachBlocksPerAxis, ReachBlocksPerAxis);
|
||||
TGuardValue<int32> TileReachBlockIndexGuard(
|
||||
VoxelGenLOD::TileReachBlockIndex, INDEX_NONE);
|
||||
TGuardValue<bool> TileBlockReachValidGuard(
|
||||
VoxelGenLOD::bTileBlockReachValid, false);
|
||||
uint8 TilePostReachFlags = VoxelGenLOD::AllTilePostReach;
|
||||
if (Generator->StrateManager != nullptr)
|
||||
{
|
||||
@@ -297,8 +326,9 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
static_cast<float>(static_cast<int64>(OriginVoxels.X) + Extent),
|
||||
static_cast<float>(static_cast<int64>(OriginVoxels.Y) + Extent),
|
||||
static_cast<float>(static_cast<int64>(OriginVoxels.Z) + Extent)));
|
||||
const float ReachScale = GVoxelForgeTilePostReachScale;
|
||||
TilePostReachFlags = 0;
|
||||
// Core stays conservative until the tile-window tunnel cache is built. Passage carving
|
||||
// is manager-owned and can be decided immediately from the same lattice+halo box.
|
||||
TilePostReachFlags = VoxelGenLOD::TunnelCoreReachable;
|
||||
if (Generator->StrateManager->AnyOriginLandingNearLattice(
|
||||
LatticeWithHalo, OriginVoxels, Step, ReachScale))
|
||||
{
|
||||
@@ -309,6 +339,11 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
{
|
||||
TilePostReachFlags |= VoxelGenLOD::PassageLandingReachable;
|
||||
}
|
||||
if (Generator->StrateManager->AnyPassageCarvingNearLattice(
|
||||
LatticeWithHalo, OriginVoxels, Step, ReachScale))
|
||||
{
|
||||
TilePostReachFlags |= VoxelGenLOD::PassageCarvingReachable;
|
||||
}
|
||||
if (Generator->StrateManager->AnyPassageStructuralPostNearLattice(
|
||||
LatticeWithHalo, OriginVoxels, Step, ReachScale))
|
||||
{
|
||||
@@ -317,6 +352,30 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
}
|
||||
TGuardValue<uint8> TilePostReachFlagsGuard(
|
||||
VoxelGenLOD::TilePostReachFlags, TilePostReachFlags);
|
||||
for (int32 BlockZ = 0; BlockZ < ReachBlocksPerAxis; ++BlockZ)
|
||||
{
|
||||
for (int32 BlockY = 0; BlockY < ReachBlocksPerAxis; ++BlockY)
|
||||
{
|
||||
for (int32 BlockX = 0; BlockX < ReachBlocksPerAxis; ++BlockX)
|
||||
{
|
||||
const int32 BlockIndex =
|
||||
((BlockZ * ReachBlocksPerAxis) + BlockY) * ReachBlocksPerAxis + BlockX;
|
||||
uint8 BlockFlags = TilePostReachFlags;
|
||||
if (Generator->StrateManager != nullptr
|
||||
&& (TilePostReachFlags & VoxelGenLOD::PassageCarvingReachable) != 0
|
||||
&& !Generator->StrateManager->AnyPassageCarvingNearLattice(
|
||||
VoxelGenLOD::MakeTileReachBlockBox(
|
||||
OriginVoxels, Step, CellsPerAxis,
|
||||
BlockX, BlockY, BlockZ),
|
||||
OriginVoxels, Step, ReachScale))
|
||||
{
|
||||
BlockFlags &= ~VoxelGenLOD::PassageCarvingReachable;
|
||||
}
|
||||
VoxelGenLOD::TileBlockReachFlags[BlockIndex] = BlockFlags;
|
||||
}
|
||||
}
|
||||
}
|
||||
VoxelGenLOD::bTileBlockReachValid = true;
|
||||
VoxelGenLOD::RecordTileReachMask(TilePostReachFlags);
|
||||
// COUPE DE CONTENU PAR STRATE — restreint le maillage (et l'échantillonnage) aux cellules
|
||||
// dont l'intervalle Z chevauche la bande [BandZMinVox, BandZMaxVox] (voxels inclusifs).
|
||||
@@ -660,6 +719,15 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
else
|
||||
{
|
||||
// World voxel = tile origin + grid offset scaled by the cell size (Step).
|
||||
const int32 ReachBlockX = FMath::Clamp(gx, 0, CellsPerAxis - 1)
|
||||
/ VoxelGenLOD::TileReachBlockCells;
|
||||
const int32 ReachBlockY = FMath::Clamp(gy, 0, CellsPerAxis - 1)
|
||||
/ VoxelGenLOD::TileReachBlockCells;
|
||||
const int32 ReachBlockZ = FMath::Clamp(gz, 0, CellsPerAxis - 1)
|
||||
/ VoxelGenLOD::TileReachBlockCells;
|
||||
VoxelGenLOD::TileReachBlockIndex =
|
||||
((ReachBlockZ * ReachBlocksPerAxis) + ReachBlockY)
|
||||
* ReachBlocksPerAxis + ReachBlockX;
|
||||
DensityGrid[LocalIndex] = Generator->GetDensityAt(
|
||||
OriginVoxels.X + gx * Step,
|
||||
OriginVoxels.Y + gy * Step,
|
||||
|
||||
Reference in new issue
Block a user