perf(tunnels): memoise the room mouth -- room ownership now cheaper than before the change

The room-wins rule cost +55% static / +36% moving worker CPU because every sample re-answered the room-mouth question. A bounded exact memo around BuildRoomMouth (4096 sets x 4 ways, 7.49 MiB, keyed on every geometry-affecting room/tunnel input) removes that: hit rate 99.91% static / 99.89% moving, and VF_FindRoomFloorCrossingWorld (19.5%/17.1% inclusive), VF_FindRoomMouthBoundary (16.0%/14.0%) and VF_EvaluateRoomLandingDensity leave the sampler's top 30 entirely.

vs the tip DLL (bf9384a runtime), same staged owner map: worker sum 29.003 s vs 30.749 s static (-5.7%), 57.232 s vs 60.923 s moving (-6.1%), request p95 -3.3% / -8.4%. Geometry unchanged by construction: canonical hash 86A99075, 64/64 tile hashes, OBJ SHA 7E0D8109..C543, identical across a repeat run and with -voxel.CrtFma3=0. Walk Connected 42,870 / 17,413; tunnel-attributed solid inside rooms 0; mouth amplitude 1.4903 cm; TilePostReachProof and DetSinCos pass. The crossing test was not rerun (the memo returns the same values; its PASS stands at 248.43 m / 26.584 s).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5 committed 2026-09-18 03:41:38 +02:00
1 parent 76bc8bce97
commit 1c642fd182
5 files changed
+890 -71

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -3747,6 +3747,8 @@ namespace
FTunnelCoreWorldEvaluation LastTunnelCoreWorldEvaluation; FTunnelCoreWorldEvaluation LastTunnelCoreWorldEvaluation;
FVector LastTunnelCoreEvaluationPosition = FVector::ZeroVector; FVector LastTunnelCoreEvaluationPosition = FVector::ZeroVector;
bool bLastTunnelCoreWorldEvaluationValid = false; bool bLastTunnelCoreWorldEvaluationValid = false;
bool bLastRoomOwnsBottom = false;
bool bLastRoomOwnsBottomValid = false;
/** ÉTAPE C1 — les params de la strate avec l'op de CETTE salle appliqué par-dessus. /** ÉTAPE C1 — les params de la strate avec l'op de CETTE salle appliqué par-dessus.
* Mémo par voxel : invalidé au début de chaque `Eval`, calculé au PREMIER modificateur * Mémo par voxel : invalidé au début de chaque `Eval`, calculé au PREMIER modificateur
@@ -3800,6 +3802,7 @@ namespace
S.ActiveCache = Sample.RoomCache; S.ActiveCache = Sample.RoomCache;
S.NearestRoom = Sample.NearestRoomIndex; S.NearestRoom = Sample.NearestRoomIndex;
S.bLocalParamsValid = false; S.bLocalParamsValid = false;
S.bLastRoomOwnsBottomValid = false;
} }
bool TryGetLastTunnelCoreWorldEvaluation( bool TryGetLastTunnelCoreWorldEvaluation(
@@ -3827,7 +3830,8 @@ namespace
S.LastTunnelCoreWorldEvaluation = VoxelCaveMorphology::EvaluateTunnelCoreWorld( S.LastTunnelCoreWorldEvaluation = VoxelCaveMorphology::EvaluateTunnelCoreWorld(
Position.X, Position.Y, Position.Z, GetCache(), nullptr, Position.X, Position.Y, Position.Z, GetCache(), nullptr,
VoxelGenLOD::ShouldUseSpatialIndex(false), VoxelGenLOD::ShouldUseSpatialIndex(false),
&S.LastWarpedPosition); &S.LastWarpedPosition,
S.bLastRoomOwnsBottomValid ? &S.bLastRoomOwnsBottom : nullptr);
S.LastTunnelCoreEvaluationPosition = Position; S.LastTunnelCoreEvaluationPosition = Position;
S.bLastTunnelCoreWorldEvaluationValid = true; S.bLastTunnelCoreWorldEvaluationValid = true;
} }
@@ -3922,6 +3926,7 @@ namespace
FState& S = State(); FState& S = State();
S.LastWorldPosition = FVector(WorldX, WorldY, WorldZ); S.LastWorldPosition = FVector(WorldX, WorldY, WorldZ);
S.bLastTunnelCoreWorldEvaluationValid = false; S.bLastTunnelCoreWorldEvaluationValid = false;
S.bLastRoomOwnsBottomValid = false;
// ⚠️ REMIS À -1 INCONDITIONNELLEMENT, ce que l'original ne fait pas : chez lui // ⚠️ REMIS À -1 INCONDITIONNELLEMENT, ce que l'original ne fait pas : chez lui
// `NearestRoomIdx` est un `thread_local` qui, quand `RoomDensity <= 0`, garde la valeur // `NearestRoomIdx` est un `thread_local` qui, quand `RoomDensity <= 0`, garde la valeur
@@ -4184,7 +4189,9 @@ namespace
const FVector WorldTunnelPosition(WorldX, WorldY, WorldZ); const FVector WorldTunnelPosition(WorldX, WorldY, WorldZ);
float CaveSDF = VoxelCaveMorphology::EvaluateSDFCached( float CaveSDF = VoxelCaveMorphology::EvaluateSDFCached(
WarpedX, WarpedY, WarpedZ, GetCache(), P.SDFBlendRadius, WarpedX, WarpedY, WarpedZ, GetCache(), P.SDFBlendRadius,
&S.NearestRoom, bUseSpatialIndex, &WorldTunnelPosition); &S.NearestRoom, bUseSpatialIndex, &WorldTunnelPosition,
&S.bLastRoomOwnsBottom);
S.bLastRoomOwnsBottomValid = true;
//--------------------------------------------------------------- //---------------------------------------------------------------
// PITS & CHEMINÉES — coordonnées RÉELLES, SmoothMin dans le même canal SDF // PITS & CHEMINÉES — coordonnées RÉELLES, SmoothMin dans le même canal SDF
@@ -4275,7 +4282,8 @@ namespace
{ {
S.LastTunnelCoreWorldEvaluation = VoxelCaveMorphology::EvaluateTunnelCoreWorld( S.LastTunnelCoreWorldEvaluation = VoxelCaveMorphology::EvaluateTunnelCoreWorld(
WorldX, WorldY, WorldZ, GetCache(), nullptr, WorldX, WorldY, WorldZ, GetCache(), nullptr,
bUseSpatialIndex, &S.LastWarpedPosition); bUseSpatialIndex, &S.LastWarpedPosition,
&S.bLastRoomOwnsBottom);
S.LastTunnelCoreEvaluationPosition = S.LastWorldPosition; S.LastTunnelCoreEvaluationPosition = S.LastWorldPosition;
S.bLastTunnelCoreWorldEvaluationValid = true; S.bLastTunnelCoreWorldEvaluationValid = true;
+53 -9
View File
@@ -3294,6 +3294,10 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
float BlockTunnelCoreSweptFloorRadius = 0.0f; float BlockTunnelCoreSweptFloorRadius = 0.0f;
bool bUsedFusedEvaluator = false; bool bUsedFusedEvaluator = false;
FTunnelCoreWorldEvaluation FusedTunnelCore; FTunnelCoreWorldEvaluation FusedTunnelCore;
bool bRoomOwnsBottom = false;
bool bRoomOwnsBottomValid = false;
FVector NativeWarpedPosition = FVector::ZeroVector;
bool bNativeWarpedPositionValid = false;
// Le seul point d'entrée de la pile dans le chemin de production. Elle rend la convention // Le seul point d'entrée de la pile dans le chemin de production. Elle rend la convention
// MC (négatif = solide) comme les fonctions d'archétype, donc les disturbances et la couche // MC (négatif = solide) comme les fonctions d'archétype, donc les disturbances et la couche
@@ -3322,7 +3326,9 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
WorldX, WorldY, WorldZ, CP_Tunnel, CP_TunnelFP, LayoutVersion, WorldX, WorldY, WorldZ, CP_Tunnel, CP_TunnelFP, LayoutVersion,
/*bApplyLegacyStructuralPosts=*/false, /*bApplyLegacyStructuralPosts=*/false,
&FusedTunnelCore, &FusedTunnelCore,
/*bCollectFusedDiagnostics=*/true); /*bCollectFusedDiagnostics=*/true,
&bRoomOwnsBottom);
bRoomOwnsBottomValid = true;
} }
const bool bIntegerLatticePoint = const bool bIntegerLatticePoint =
@@ -3434,7 +3440,12 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
// Underwater shares tunnel rock (water table is a render-side overlay). // Underwater shares tunnel rock (water table is a render-side overlay).
Result = GetDensityWithParams(WorldX, WorldY, WorldZ, CP_Tunnel, Result = GetDensityWithParams(WorldX, WorldY, WorldZ, CP_Tunnel,
CP_TunnelFP, LayoutVersion, CP_TunnelFP, LayoutVersion,
/*bApplyLegacyStructuralPosts=*/false); break; /*bApplyLegacyStructuralPosts=*/false,
nullptr, false, &bRoomOwnsBottom,
&NativeWarpedPosition);
bRoomOwnsBottomValid = true;
bNativeWarpedPositionValid = true;
break;
} }
DensityCoreTimer.End(); DensityCoreTimer.End();
@@ -3475,18 +3486,27 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
{ {
VoxelDensityProfile::FScopedTimer ProfileTimer( VoxelDensityProfile::FScopedTimer ProfileTimer(
VoxelDensityProfile::EBucket::TunnelCorePosts); VoxelDensityProfile::EBucket::TunnelCorePosts);
FVector RoomQueryPosition(WorldX, WorldY, WorldZ); FVector RoomQueryPosition;
if (bNativeWarpedPositionValid)
{
RoomQueryPosition = NativeWarpedPosition;
}
else
{
RoomQueryPosition = FVector(WorldX, WorldY, WorldZ);
if (CP_Tunnel.VerticalScale != 1.0f && CP_Tunnel.VerticalScale > 0.0f) if (CP_Tunnel.VerticalScale != 1.0f && CP_Tunnel.VerticalScale > 0.0f)
{ {
RoomQueryPosition.Z = WorldZ / CP_Tunnel.VerticalScale; RoomQueryPosition.Z = WorldZ / CP_Tunnel.VerticalScale;
} }
RoomQueryPosition = VoxelCaveMorphology::ApplyCaveWarp( RoomQueryPosition = VoxelCaveMorphology::ApplyCaveWarp(
RoomQueryPosition, CP_Tunnel, static_cast<uint32>(Seed)); RoomQueryPosition, CP_Tunnel, static_cast<uint32>(Seed));
}
PreDisturbanceTunnelCore = VoxelCaveMorphology::EvaluateTunnelCoreWorld( PreDisturbanceTunnelCore = VoxelCaveMorphology::EvaluateTunnelCoreWorld(
WorldX, WorldY, WorldZ, ActiveTunnelCoreCache->Cache, nullptr, WorldX, WorldY, WorldZ, ActiveTunnelCoreCache->Cache, nullptr,
VoxelGenLOD::ShouldUseSpatialIndex( VoxelGenLOD::ShouldUseSpatialIndex(
CP_UseOpStack ? bUsedFusedEvaluator : true), CP_UseOpStack ? bUsedFusedEvaluator : true),
&RoomQueryPosition); &RoomQueryPosition,
bRoomOwnsBottomValid ? &bRoomOwnsBottom : nullptr);
bHavePreDisturbanceTunnelCore = true; bHavePreDisturbanceTunnelCore = true;
} }
@@ -3679,19 +3699,28 @@ float UVoxelGenerator::GetDensityAt(float WorldX, float WorldY, float WorldZ) co
{ {
VoxelDensityProfile::FScopedTimer ProfileTimer( VoxelDensityProfile::FScopedTimer ProfileTimer(
VoxelDensityProfile::EBucket::TunnelCorePosts); VoxelDensityProfile::EBucket::TunnelCorePosts);
FVector RoomQueryPosition(WorldX, WorldY, WorldZ); FVector RoomQueryPosition;
if (bNativeWarpedPositionValid)
{
RoomQueryPosition = NativeWarpedPosition;
}
else
{
RoomQueryPosition = FVector(WorldX, WorldY, WorldZ);
if (CP_Tunnel.VerticalScale != 1.0f && CP_Tunnel.VerticalScale > 0.0f) if (CP_Tunnel.VerticalScale != 1.0f && CP_Tunnel.VerticalScale > 0.0f)
{ {
RoomQueryPosition.Z = WorldZ / CP_Tunnel.VerticalScale; RoomQueryPosition.Z = WorldZ / CP_Tunnel.VerticalScale;
} }
RoomQueryPosition = VoxelCaveMorphology::ApplyCaveWarp( RoomQueryPosition = VoxelCaveMorphology::ApplyCaveWarp(
RoomQueryPosition, CP_Tunnel, static_cast<uint32>(Seed)); RoomQueryPosition, CP_Tunnel, static_cast<uint32>(Seed));
}
TunnelCore = VoxelCaveMorphology::EvaluateTunnelCoreWorld( TunnelCore = VoxelCaveMorphology::EvaluateTunnelCoreWorld(
WorldX, WorldY, WorldZ, ActiveTunnelCoreCache->Cache, WorldX, WorldY, WorldZ, ActiveTunnelCoreCache->Cache,
nullptr, nullptr,
VoxelGenLOD::ShouldUseSpatialIndex( VoxelGenLOD::ShouldUseSpatialIndex(
CP_UseOpStack ? bUsedFusedEvaluator : true), CP_UseOpStack ? bUsedFusedEvaluator : true),
&RoomQueryPosition); &RoomQueryPosition,
bRoomOwnsBottomValid ? &bRoomOwnsBottom : nullptr);
bHaveTunnelCore = true; bHaveTunnelCore = true;
} }
if (bHaveTunnelCore) if (bHaveTunnelCore)
@@ -3828,7 +3857,9 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
uint32 ParamsFingerprint, uint32 LayoutVersion, uint32 ParamsFingerprint, uint32 LayoutVersion,
bool bApplyLegacyStructuralPosts, bool bApplyLegacyStructuralPosts,
FTunnelCoreWorldEvaluation* OutTunnelCore, FTunnelCoreWorldEvaluation* OutTunnelCore,
bool bCollectFusedDiagnostics) const bool bCollectFusedDiagnostics,
bool* OutRoomOwnsBottom,
FVector* OutWarpedPosition) const
{ {
//========================================================================= //=========================================================================
// STRATE DENSITY FUNCTION (Morphology Pipeline) // STRATE DENSITY FUNCTION (Morphology Pipeline)
@@ -3859,6 +3890,14 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
{ {
*OutTunnelCore = FTunnelCoreWorldEvaluation(); *OutTunnelCore = FTunnelCoreWorldEvaluation();
} }
if (OutRoomOwnsBottom != nullptr)
{
*OutRoomOwnsBottom = false;
}
if (OutWarpedPosition != nullptr)
{
*OutWarpedPosition = FVector::ZeroVector;
}
if (bCollectFusedDiagnostics && VoxelDensityProfile::AreCountersEnabled()) if (bCollectFusedDiagnostics && VoxelDensityProfile::AreCountersEnabled())
{ {
VoxelDensityProfile::AddCounter( VoxelDensityProfile::AddCounter(
@@ -3930,6 +3969,10 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
WarpedY += WarpY * VOXEL_NOISE_SCALE * WS; WarpedY += WarpY * VOXEL_NOISE_SCALE * WS;
WarpedZ += WarpZ * VOXEL_NOISE_SCALE * WS; WarpedZ += WarpZ * VOXEL_NOISE_SCALE * WS;
} }
if (OutWarpedPosition != nullptr)
{
*OutWarpedPosition = FVector(WarpedX, WarpedY, WarpedZ);
}
//========================================================================= //=========================================================================
// STEP 4: SDF MORPHOLOGY (rooms + tunnels) — CACHED PER CHUNK // STEP 4: SDF MORPHOLOGY (rooms + tunnels) — CACHED PER CHUNK
@@ -4187,7 +4230,8 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
SDFCache, Params.SDFBlendRadius, SDFCache, Params.SDFBlendRadius,
&NearestRoomIdx, &NearestRoomIdx,
bUseSpatialIndex, bUseSpatialIndex,
&WorldTunnelPosition &WorldTunnelPosition,
OutRoomOwnsBottom
); );
// ── PIT & CHIMNEY SDF INTEGRATION ── // ── PIT & CHIMNEY SDF INTEGRATION ──
@@ -4307,7 +4351,7 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
const FVector RoomQueryPosition(WarpedX, WarpedY, WarpedZ); const FVector RoomQueryPosition(WarpedX, WarpedY, WarpedZ);
*OutTunnelCore = VoxelCaveMorphology::EvaluateTunnelCoreWorld( *OutTunnelCore = VoxelCaveMorphology::EvaluateTunnelCoreWorld(
WorldX, WorldY, WorldZ, SDFCache, nullptr, bUseSpatialIndex, WorldX, WorldY, WorldZ, SDFCache, nullptr, bUseSpatialIndex,
&RoomQueryPosition); &RoomQueryPosition, OutRoomOwnsBottom);
} }
//========================================================================= //=========================================================================
+10 -2
View File
@@ -1049,6 +1049,10 @@ namespace VoxelCaveMorphology
// supplied, rooms remain at the query position but the tunnel // supplied, rooms remain at the query position but the tunnel
// uses its authored world chain. Null preserves the legacy // uses its authored world chain. Null preserves the legacy
// all-query behavior. // all-query behavior.
// @param OutRoomOwnsBottom — optional out: true when the query position is inside any
// cached room's raw authored shape. When the caller evaluates
// the tunnel core for this same sample, pass this result back
// to EvaluateTunnelCoreWorld to avoid a second room query.
// (Room shape variety is baked into FCachedRoom by BuildChunkCache — no per-voxel roll.) // (Room shape variety is baked into FCachedRoom by BuildChunkCache — no per-voxel roll.)
// @return negative = inside cave, positive = solid rock // @return negative = inside cave, positive = solid rock
VOXELFORGE_API float EvaluateSDFCached( VOXELFORGE_API float EvaluateSDFCached(
@@ -1057,7 +1061,8 @@ namespace VoxelCaveMorphology
float SDFBlendRadius, float SDFBlendRadius,
int32* OutNearestRoomIdx = nullptr, int32* OutNearestRoomIdx = nullptr,
bool bUseSpatialIndex = true, bool bUseSpatialIndex = true,
const FVector* WorldTunnelPosition = nullptr const FVector* WorldTunnelPosition = nullptr,
bool* OutRoomOwnsBottom = nullptr
); );
// Evaluate the raw union of cached graph-tunnel capsules. This is intentionally separate from // Evaluate the raw union of cached graph-tunnel capsules. This is intentionally separate from
@@ -1087,7 +1092,10 @@ namespace VoxelCaveMorphology
// The room graph is evaluated in warped coordinates while the tunnel core is evaluated in // The room graph is evaluated in warped coordinates while the tunnel core is evaluated in
// the authored world frame. Pass the former when available so room ownership is tested in // the authored world frame. Pass the former when available so room ownership is tested in
// the same domain as the generic room field. // the same domain as the generic room field.
const FVector* RoomQueryPosition = nullptr const FVector* RoomQueryPosition = nullptr,
// Optional result from EvaluateSDFCached for this exact sample. When supplied, it avoids
// repeating the room-shape containment query; null preserves standalone-call behavior.
const bool* CachedRoomOwnsBottom = nullptr
); );
// Per-tile broad reach for the world-space core/floor post. The bound includes the swept // Per-tile broad reach for the world-space core/floor post. The bound includes the swept
+8 -1
View File
@@ -240,7 +240,14 @@ public:
FTunnelCoreWorldEvaluation* OutTunnelCore = nullptr, FTunnelCoreWorldEvaluation* OutTunnelCore = nullptr,
// Diagnostics are opt-in so ordinary/reference calls do not pay // Diagnostics are opt-in so ordinary/reference calls do not pay
// for fused-path counters. // for fused-path counters.
bool bCollectFusedDiagnostics = false) const; bool bCollectFusedDiagnostics = false,
// Optional same-sample hand-off from EvaluateSDFCached. This is
// only a room-shape ownership bit; it does not alter the scalar
// result and avoids a duplicate room-index query in native paths.
bool* OutRoomOwnsBottom = nullptr,
// Optional same-sample warped position. Native GetDensityAt uses
// this to feed the core post without applying the cave warp twice.
FVector* OutWarpedPosition = nullptr) const;
/** /**
* Densité pour une strate Slab (FlatPlain / CrystalChamber). * Densité pour une strate Slab (FlatPlain / CrystalChamber).