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:
1 parent
11f0c1335b
commit
c132243b30
15 files changed
+2406
-552
No files matched your search
@@ -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)
|
||||
//=========================================================================
|
||||
|
||||
Reference in new issue
Block a user