feat(worms): asset-owned worm off switch; offline stack symboliser -- cheap-worm default to be reverted

Worms round (Codex; reviewed by me against its report and PERF-SAMPLED.md).

Part 1, a real off switch: UVoxelStrateDefinition::bEnableWorms (default true, so existing assets
are unchanged). It is deliberately not in FStrateGenerationParams, so the 83-field memo-key guard
is untouched. It resolves after composer candidates, season vectors and boundary blending, is
included in the generation fingerprint, and clamps composer overrides, so a roll cannot re-enable
it. With strength 0 the fused path skips the worm block, the op-stack builder omits the worm
source, and the interval/classifier paths do no worm work. Proof: disabled == hand-zeroed control
byte for byte (70D310A4, 74,672 triangles), capability 20,856 / 10,917, connected, zero worm rows
in the symbolised sampler. voxel.WormsForceOff is a dev-only, world-changing measurement
override, included in the fingerprint.

Part 0: the sampler writes a module map (733 modules, identity checked), and a post-exit
offline symboliser (VoxelStackOfflineSymbolizer, editor module) rebuilds the all-LOD / LOD0 /
LOD1+ exclusive / inclusive / source-line tables. A planted cost was found (5 named rows) and then
removed. DbgHelp still never runs in the measured process.

Part 2, "cheap worms": FAILED to deliver, and the default is wrong. No candidate was faster:
lattice-2/4 gave no gain, and value noise was within noise static and ~2.1% WORSE in moving worker
seconds. Yet this commit carries voxel.WormNoiseMode=1 (value noise) as the default, a field change
(29/64 test tiles) with no benefit, selected after value-noise variants were tried until one
passed capability (three were rejected at 20,821-20,828). The next round reverts the default to
exact Perlin (mode 0) and removes the no-gain world-changing experiment modes.

The finding that matters: disabling worms entirely (WormsForceOff A/B, two interleaved runs each)
saves only ~2.5% static and ~3.4% moving worker time. The sampler's "worm line
VoxelGenerator.cpp:3985 = 19.4% of LOD0" was a misattribution of inlined noise code to one PDB
line. Line-level attribution of inlined code must be confirmed by ablation before a round targets
it. That is why the worm block skip (26b3476) found nothing.

Runs: the full ledger is in PERF-SAMPLED.md. Failures: one moving wrapper hit the graceful-close
timeout and was rerun; the first offline-symboliser commandlet hit the DDC no-writable-nodes fatal
(crash folder UECC-...CE75ACD5, 08:01) and was retried with the writable Saved\DDC.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaFdXhTdYMkW1xrV6ApT6Y
This commit is contained in:
Fr0zkaandClaude Opus 5 committed 2026-09-14 08:19:50 +02:00
1 parent 11f0c1335b
commit c132243b30
15 files changed
+2406 -552

No files matched your search

+27 -27
View File
@@ -13,6 +13,7 @@
#include "VoxelDiffLayer.h"
#include "VoxelBiomeDefinition.h"
#include "VoxelNoise.h" // T2.a: float, SIMD-batched gradient-noise core
#include "VoxelWormField.h"
#include "VoxelDensityPrimitives.h" // spine / seals / passage — shared with the operator stack
#include "VoxelDensityOpStack.h" // OPSTACK Phase 1: the opt-in per-strate operator stack
#include "VoxelHeightOp.h" // IVoxelBiomeField — the adapter below implements it
@@ -858,6 +859,14 @@ bool VoxelGenLOD::GetThreadTileCacheWindow(
&& Extent <= static_cast<int64>(CHUNK_SIZE) * 64;
}
void VoxelGenLOD::SetThreadTileContext(
const FIntVector& OriginVoxels,
int32 CellsPerAxis)
{
TileOriginVoxels = OriginVoxels;
TileCellsPerAxis = CellsPerAxis;
}
bool VoxelGenLOD::ShouldUseSpatialIndex(bool bFusedPath)
{
VF_ParseSpatialIndexSwitch();
@@ -4239,10 +4248,10 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
// already computed by Step 4 — free): full strength at the network, smooth fade to zero
// at Range. Worms become braids/shortcuts hugging the cave system; no isolated speckle.
// Range = 0 → unmasked legacy behaviour. Bonus: fully-masked voxels skip both Perlins.
VoxelDensityProfile::FScopedTimer FusedWormTimer(
VoxelDensityProfile::EBucket::FusedWorm);
if (Params.WormStrength > 0.0f && Params.WormThreshold > 0.0f)
{
VoxelDensityProfile::FScopedTimer FusedWormTimer(
VoxelDensityProfile::EBucket::FusedWorm);
float NetworkMask = 1.0f;
if (Params.WormNetworkRange > 0.0f)
{
@@ -4267,7 +4276,10 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
}
bool bWormBlockProofComputed = false;
const bool bSkipWormBlock = GVoxelForgeWormBlockSkip != 0
const int32 WormLatticeStep = VoxelWormField::GetLatticeStep();
const bool bSkipWormBlock = VoxelWormField::GetNoiseMode() == 0
&& WormLatticeStep <= 1
&& GVoxelForgeWormBlockSkip != 0
&& VF_TryGetWormBlockSkip(
DensityCacheOwnerId, SeedU, ParamsFingerprint, LayoutVersion,
WorldX, WorldY, WorldZ, Params, bWormBlockProofComputed);
@@ -4286,37 +4298,25 @@ float UVoxelGenerator::GetDensityWithParams(float WorldX, float WorldY, float Wo
}
else
{
const float WormZFreq = Params.WormFrequency * Params.WormHorizontalBias;
const float N1 = FMath::Abs(VoxelNoise::Perlin3D(FVector3f(
WorldX * Params.WormFrequency + VoxelHash::SeedOffset(SeedU, 1.0f),
WorldY * Params.WormFrequency + VoxelHash::SeedOffset(SeedU, 1.7f),
EffectiveZ * WormZFreq + VoxelHash::SeedOffset(SeedU, 2.3f)
)) * VOXEL_NOISE_SCALE);
const VoxelWormField::FParameters WormParameters{
Params.WormFrequency,
Params.WormHorizontalBias,
Params.VerticalScale,
SeedU};
const float WormValue = VoxelWormField::Evaluate(
WorldX, WorldY, WorldZ, Params.WormThreshold,
WormParameters, WormLatticeStep);
// N2 >= 0, so if N1 alone already clears the threshold the sum can't carve —
// skip the second Perlin entirely (most voxels; bit-identical output).
if (N1 < Params.WormThreshold)
if (WormValue < Params.WormThreshold)
{
const float N2 = FMath::Abs(VoxelNoise::Perlin3D(FVector3f(
WorldX * Params.WormFrequency + VoxelHash::SeedOffset(SeedU, 1.0f) + 137.0f,
WorldY * Params.WormFrequency + VoxelHash::SeedOffset(SeedU, 1.7f) + 259.0f,
EffectiveZ * WormZFreq + VoxelHash::SeedOffset(SeedU, 2.3f) + 431.0f
)) * VOXEL_NOISE_SCALE);
const float WormValue = N1 + N2;
if (WormValue < Params.WormThreshold)
{
const float t = 1.0f - (WormValue / Params.WormThreshold);
Density -= t * Params.WormStrength * NetworkMask;
}
const float t = 1.0f - (WormValue / Params.WormThreshold);
Density -= t * Params.WormStrength * NetworkMask;
}
}
}
FusedWormTimer.End();
}
FusedWormTimer.End();
//=========================================================================
// STEP 6: STRATE BOUNDARY SEAL (haut + bas)
//=========================================================================