Round (Codex; reviewed by me against PERF-SAMPLED.md). Revert: voxel.WormNoiseMode / voxel.WormLatticeStep, their storage and their switches are REMOVED. VoxelWormField has one path again, exact Perlin with the N1 short circuit. Kept: bEnableWorms (asset), WormsForceOff (measurement only), the exact block skip (default 0). Ablation instrument: 14 development-only, world-changing force-off bits (voxel.TunnelAblate*), applied on the fused, op-stack/classifier, cached SDF/core and modifier/floor paths. They resolve once per process, are hashed into the generation fingerprint, and are compiled to zero in UE_BUILD_SHIPPING (VoxelDensityAblation.cpp). They are a measurement instrument, never a gameplay or multiplayer switch. Defaults exact: canonical export OBJ b3e5f4c3..9b377, worms-region 311CA42C / 75,482 triangles, capability 20,830 / 10,909, and 841/841 keyed tiles identical to NextHeadStaticTrace_20260913. Static worker seconds saved by removing ONE component (two off runs vs the interleaved all-on 33.06 s; baseline noise 0.27%): tunnel SDF 11.4%, cave warp 10.3%, passage carving 10.1%, landing posts 9.9%, passage structural posts 5.6%, worms 2.4%, native floor 2.2%, origin spine 1.6%, room SDF 1.6%, everything else <= 1.1% Moving (2+2 runs each) confirms the top five at 6.0-11.6%. Tunnel SDF off cuts LOD0 generation p95 104 -> 83 ms: it owns the slow tail. The positive savings sum to 58% of the static total; the other 42% is shared. The rows are not additive. Unexplained: tunnel-core OFF made the static total 2.9x SLOWER (95.5 s) while LOD0 generation got faster (p50 64.7 -> 60.6 ms) and triangles fell. The report blames the changed field, which does not fit; more likely a slow fallback path in coarse tiles. That row is not a cost measurement. Ledger: every Unreal process exited 0 and verified the loaded DLL; two PowerShell parser errors happened before any process started. No crashes or retries. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TaFdXhTdYMkW1xrV6ApT6Y
132 lines
5.6 KiB
C++
132 lines
5.6 KiB
C++
// VoxelDensityAblation.cpp
|
|
// Development-only TunnelNetwork ablation controls.
|
|
|
|
#include "VoxelDensityAblation.h"
|
|
|
|
#include "HAL/IConsoleManager.h"
|
|
#include "Misc/CommandLine.h"
|
|
#include "Misc/Parse.h"
|
|
|
|
#include <atomic>
|
|
|
|
namespace
|
|
{
|
|
constexpr uint32 UnresolvedMask = 0xFFFFFFFFu;
|
|
std::atomic<uint32> GResolvedMask(UnresolvedMask);
|
|
|
|
#if !UE_BUILD_SHIPPING
|
|
int32 GCaveWarp = 0;
|
|
int32 GDetailOps = 0;
|
|
int32 GRoomSDF = 0;
|
|
int32 GTunnelSDF = 0;
|
|
int32 GTunnelCore = 0;
|
|
int32 GPassageCarving = 0;
|
|
int32 GPassageStructuralPosts = 0;
|
|
int32 GNativeFloor = 0;
|
|
int32 GDisturbances = 0;
|
|
int32 GOriginSpine = 0;
|
|
int32 GBoundarySeal = 0;
|
|
int32 GLandingPosts = 0;
|
|
int32 GXYEdgeSeal = 0;
|
|
int32 GPitChimneySDF = 0;
|
|
|
|
#define VF_ABLATION_CVAR(Name, Storage) \
|
|
FAutoConsoleVariableRef CVar##Storage( \
|
|
Name, Storage, \
|
|
TEXT("WORLD-CHANGING DEVELOPMENT-ONLY measurement override. Forces this " \
|
|
"TunnelNetwork density stage off; never use as a gameplay switch. " \
|
|
"All peers and regenerated worlds must use the same value. Resolved once " \
|
|
"per process. 0=on, 1=off."), ECVF_Default)
|
|
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateCaveWarp"), GCaveWarp);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateDetailOps"), GDetailOps);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateRoomSDF"), GRoomSDF);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateTunnelSDF"), GTunnelSDF);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateTunnelCore"), GTunnelCore);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblatePassageCarving"), GPassageCarving);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblatePassageStructuralPosts"), GPassageStructuralPosts);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateNativeFloor"), GNativeFloor);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateDisturbances"), GDisturbances);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateOriginSpine"), GOriginSpine);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateBoundarySeal"), GBoundarySeal);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateLandingPosts"), GLandingPosts);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblateXYEdgeSeal"), GXYEdgeSeal);
|
|
VF_ABLATION_CVAR(TEXT("voxel.TunnelAblatePitChimneySDF"), GPitChimneySDF);
|
|
|
|
#undef VF_ABLATION_CVAR
|
|
|
|
uint32 ResolveValue(const TCHAR* Name, int32& Storage)
|
|
{
|
|
int32 Value = Storage;
|
|
FParse::Value(FCommandLine::Get(), Name, Value);
|
|
Storage = Value != 0 ? 1 : 0;
|
|
return Storage != 0 ? 1u : 0u;
|
|
}
|
|
|
|
uint32 ResolveMask()
|
|
{
|
|
uint32 Mask = 0;
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateCaveWarp="), GCaveWarp)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::CaveWarp);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateDetailOps="), GDetailOps)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::DetailOps);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateRoomSDF="), GRoomSDF)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::RoomSDF);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateTunnelSDF="), GTunnelSDF)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::TunnelSDF);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateTunnelCore="), GTunnelCore)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::TunnelCore);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblatePassageCarving="), GPassageCarving)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::PassageCarving);
|
|
Mask |= ResolveValue(
|
|
TEXT("voxel.TunnelAblatePassageStructuralPosts="), GPassageStructuralPosts)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::PassageStructuralPosts);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateNativeFloor="), GNativeFloor)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::NativeFloor);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateDisturbances="), GDisturbances)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::Disturbances);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateOriginSpine="), GOriginSpine)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::OriginSpine);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateBoundarySeal="), GBoundarySeal)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::BoundarySeal);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateLandingPosts="), GLandingPosts)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::LandingPosts);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblateXYEdgeSeal="), GXYEdgeSeal)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::XYEdgeSeal);
|
|
Mask |= ResolveValue(TEXT("voxel.TunnelAblatePitChimneySDF="), GPitChimneySDF)
|
|
* static_cast<uint32>(VoxelDensityAblation::EStage::PitChimneySDF);
|
|
return Mask;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
namespace VoxelDensityAblation
|
|
{
|
|
uint32 GetResolvedMask()
|
|
{
|
|
uint32 Existing = GResolvedMask.load(std::memory_order_acquire);
|
|
if (Existing != UnresolvedMask)
|
|
{
|
|
return Existing;
|
|
}
|
|
|
|
#if UE_BUILD_SHIPPING
|
|
constexpr uint32 Resolved = 0;
|
|
#else
|
|
const uint32 Resolved = ResolveMask();
|
|
#endif
|
|
uint32 Expected = UnresolvedMask;
|
|
if (!GResolvedMask.compare_exchange_strong(
|
|
Expected, Resolved, std::memory_order_release, std::memory_order_acquire))
|
|
{
|
|
return Expected;
|
|
}
|
|
|
|
UE_LOG(LogTemp, Display,
|
|
TEXT("[VoxelForgeTunnelAblation] resolved mask=0x%08x "
|
|
"(world-changing development measurement overrides; 0=all on)"),
|
|
Resolved);
|
|
return Resolved;
|
|
}
|
|
}
|