feat(stats): stat VoxelForge -- make tile skipping and the column memo observable
The plugin had ZERO stat counters, so every claim this refactor makes was harness-only: "skipped correctly" and "skipped nothing" render identically. CODEX-TASK-001 and -002, executed by Codex (gpt-5.6-luna xhigh), reviewed against the source. Eight DWORD counters in a new stat group: GenerateTileResult -- TilesClassified / SkippedAllSolid / SkippedAllAir / Meshed ClassifyTile bAnyCave exit -- TilesOpStackSolid / TilesOpStackAir FSurfaceColumnSource::GetColumn -- ColumnMemoHit / ColumnMemoMiss The op-stack counters are separate from the lumped skip counters on purpose: ClassifyTile also proves AllSolid on its hand-written bedrock-gap path with no strate opted in, so the lumped number cannot show a before/after. The op-stack pair is zero BY CONSTRUCTION until a strate ticks the flag. GetColumn is instrumented and deliberately NOT fixed -- the instrument and the fix in one build would make each other unreadable. Verified against UE_5.7 Stats.h rather than assumed (first stats use in this plugin, no in-repo precedent): all four macro arities, and INC_DWORD_STAT -> FThreadStats::AddMessage, so the worker-thread safety both sites need holds by mechanism. Not built -- Jahni builds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7909c4f2ca
commit
eb317d9933
7 files changed
+131
-1
No files matched your search
@@ -11,6 +11,7 @@
|
||||
#include "VoxelTerrainOpDefinition.h"
|
||||
#include "VoxelContentManager.h"
|
||||
#include "VoxelDensityVolume.h"
|
||||
#include "VoxelStats.h"
|
||||
// IWYU (FPSemantics = Precise ⇒ plus de PCH partagé) : GetPlayerPosition déréférence le pawn, donc
|
||||
// APawn doit être COMPLET — `Casts.h` n'en donne qu'une déclaration avant. APlayerController était
|
||||
// complet par transitivité seulement : on l'inclut explicitement, c'est exactement la fragilité
|
||||
@@ -1502,11 +1503,24 @@ void AVoxelWorld::GenerateTileResult(const FVoxelTileKey& Tile, const FIntVector
|
||||
if (!bSheetTile && !bWantCapture && Generator && Mesher && Mesher->IsoLevel == 0.0f)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(VoxelForge_ClassifyTile);
|
||||
bTrivialEmpty = (Generator->ClassifyTile(OriginVoxels, Step, Cells) != EVoxelTileClass::Mixed);
|
||||
INC_DWORD_STAT(STAT_VoxelForgeTilesClassified);
|
||||
const EVoxelTileClass Verdict = Generator->ClassifyTile(OriginVoxels, Step, Cells);
|
||||
if (Verdict == EVoxelTileClass::AllSolid)
|
||||
{
|
||||
INC_DWORD_STAT(STAT_VoxelForgeTilesSkippedAllSolid);
|
||||
}
|
||||
else if (Verdict == EVoxelTileClass::AllAir)
|
||||
{
|
||||
INC_DWORD_STAT(STAT_VoxelForgeTilesSkippedAllAir);
|
||||
}
|
||||
bTrivialEmpty = (Verdict != EVoxelTileClass::Mixed);
|
||||
}
|
||||
|
||||
// F18 — feuille : deux heightfields sol/cap échantillonnés par colonne (pas de marching
|
||||
// cubes, pas de classifieur — la classe de surface est vraie par construction).
|
||||
// `TilesMeshed` peut dépasser `TilesClassified` : les tuiles qui ratent cette porte sont
|
||||
// maillées sans classification. / `TilesMeshed` may exceed `TilesClassified`: tiles that
|
||||
// fail this gate are meshed without classification.
|
||||
FVoxelMeshData MeshData;
|
||||
if (!bTrivialEmpty)
|
||||
{
|
||||
@@ -1517,6 +1531,7 @@ void AVoxelWorld::GenerateTileResult(const FVoxelTileKey& Tile, const FIntVector
|
||||
: Mesher->GenerateMesh(OriginVoxels, Step, Cells,
|
||||
bWantCapture ? &Result.CaptureGrid : nullptr,
|
||||
BandVoxLo, BandVoxHi);
|
||||
INC_DWORD_STAT(STAT_VoxelForgeTilesMeshed);
|
||||
}
|
||||
|
||||
// T1.f — build the RMC geometry buffers HERE (worker), not on the game thread. Empty/all-air
|
||||
|
||||
Reference in new issue
Block a user