Files
VoxelForge/Source/VoxelForge/Public/VoxelStartupTrace.h
T
Fr0zkaandClaude Opus 5.5 5c519f5206 streaming: one supplemental far apply per frame when the budget is half unused (L121)
After the normal visible-apply count is reached and <50% of the 2 ms budget is spent, apply one horizon
result (off during startup boost; voxel.StreamingFarApplySupplement=0 disables). 30 m/s UE, 5 pairs:
far holes 4.38% -> 2.70%, far finish-to-apply p50 1.105 -> 0.114 s, worst tick 14.74 ms (<15.43),
near coverage +0.3 pt, arrival whole-view -313 ms. Geometry unchanged (24/24 hashes), fast tier green.
Adds trace-only RMC proxy publication timing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
2026-10-30 08:03:18 +01:00

120 lines
4.3 KiB
C++

// Bounded, opt-in startup trace for the complete streaming path.
// The trace is deliberately independent of the shared Unreal log: callers provide an
// absolute output path and every record is one JSON object per line.
#pragma once
#include "CoreMinimal.h"
namespace VoxelForgeStartupTrace
{
struct VOXELFORGE_API FTileSample
{
int32 TileX = 0;
int32 TileY = 0;
int32 TileZ = 0;
int32 Level = -1;
int32 WorkPriority = 0;
int32 Verdict = -1; // Mixed=0, AllSolid=1, AllAir=2, -1=not classified (early path)
uint64 RequestOrdinal = 0;
uint64 GenerationOrdinal = 0;
uint64 RequestStartCycles = 0;
uint64 WorkerTaskStartCycles = 0;
uint64 WorkerTaskEndCycles = 0;
uint32 WorkerThreadId = 0;
bool bResidentAtRequest = false;
bool bSealedSolidProof = false;
bool bEmpty = true;
int32 Vertices = 0;
int32 Triangles = 0;
uint64 GeometryBytes = 0;
// This is worker-result -> game-thread mesh submission. Collision readiness is a later
// per-tile RMC completion event recorded separately as collision_ready.
double RequestToApplySeconds = 0.0;
double QueueWaitSeconds = 0.0;
double WorkerQueueSeconds = 0.0;
double ResultQueueSeconds = 0.0;
double WorkerTaskSeconds = 0.0;
double GenerationSeconds = 0.0;
double CoreGenerateSeconds = 0.0;
double MeshCopySeconds = 0.0;
double StreamBuildSeconds = 0.0;
double ClassifySeconds = 0.0;
double MeshSeconds = 0.0;
double StreamSeconds = 0.0;
double ApplySeconds = 0.0;
};
struct VOXELFORGE_API FApplyFrameSample
{
uint64 Frame = 0;
double FrameSeconds = 0.0;
double SpeedCmPerSecond = 0.0;
double ApplySeconds = 0.0;
double DrainSeconds = 0.0;
int32 ActiveTasks = 0;
int32 RunningWorkerTasks = 0;
int32 TaskCap = 0;
int32 PendingTiles = 0;
int32 PendingResultsEstimate = 0;
int32 ResultsDrained = 0;
int32 ApplyResultsByLevelTotal = 0;
int32 MeshesApplied = 0;
int32 SupplementalFarApplies = 0;
int32 MaxApplies = 0;
double ApplyBudgetMilliseconds = 0.0;
bool bCountLimitReached = false;
bool bTimeLimitReached = false;
TStaticArray<int32, 9> PendingByLevel{};
TStaticArray<int32, 9> ApplyResultsByLevel{};
TStaticArray<int32, 9> MeshesAppliedByLevel{};
TStaticArray<double, 9> ApplySecondsByLevel{};
};
struct VOXELFORGE_API FWriteMetrics
{
double JsonWriteMilliseconds = 0.0;
double ArchiveSerializeMilliseconds = 0.0;
};
/** Starts when -voxel.StartupTraceFile=<absolute path> is present. */
VOXELFORGE_API void BeginFromCommandLine();
VOXELFORGE_API bool IsActive();
/** Returns and resets startup-trace writes performed by the current game-thread frame. */
VOXELFORGE_API FWriteMetrics ConsumeCurrentThreadWriteMetrics();
/** FieldsJson is the contents after the type/timestamp object prefix, without braces. */
VOXELFORGE_API void RecordEvent(const TCHAR* Type, const FString& FieldsJson = FString());
VOXELFORGE_API void RecordRequest(const FTileSample& Sample, uint32 Epoch,
uint32 DesiredEpoch = 0);
VOXELFORGE_API void StageBegin(const TCHAR* Name);
VOXELFORGE_API void StageEnd(const TCHAR* Name);
VOXELFORGE_API void RecordTile(const FTileSample& Sample);
/** One game-thread result-drain sample, including worker occupancy and per-LOD applies. */
/** Echantillon de vidage des resultats, avec occupation des travailleurs et applications par LOD. */
VOXELFORGE_API void RecordApplyFrame(const FApplyFrameSample& Sample);
/** Writes the final bounded summary and closes the file. Safe to call more than once. */
VOXELFORGE_API void Finish(const TCHAR* Reason);
/** RAII helper for stages which have early-return failure paths. */
class VOXELFORGE_API FStageScope
{
public:
explicit FStageScope(const TCHAR* InName);
~FStageScope();
FStageScope(const FStageScope&) = delete;
FStageScope& operator=(const FStageScope&) = delete;
private:
FString Name;
bool bActive = false;
};
}