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
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-30 08:03:18 +01:00
1 parent 161565936c
commit 5c519f5206
8 files changed
+1115 -5

No files matched your search

@@ -423,6 +423,7 @@ void RecordApplyFrame(const FApplyFrameSample& Sample)
"\"active_tasks\":%d,\"running_workers\":%d,\"task_cap\":%d,"
"\"pending_tiles\":%d,\"pending_results_estimate\":%d,"
"\"results_drained\":%d,\"apply_results\":%d,\"meshes_applied\":%d,\"max_applies\":%d,"
"\"supplemental_far_applies\":%d,"
"\"apply_budget_ms\":%s,\"count_limit_reached\":%d,\"time_limit_reached\":%d,"
"\"pending_by_lod\":%s,\"apply_results_by_lod\":%s,"
"\"meshes_by_lod\":%s,\"apply_ms_by_lod\":%s"),
@@ -432,7 +433,8 @@ void RecordApplyFrame(const FApplyFrameSample& Sample)
Sample.RunningWorkerTasks, Sample.TaskCap, Sample.PendingTiles,
Sample.PendingResultsEstimate, Sample.ResultsDrained, Sample.ApplyResultsByLevelTotal,
Sample.MeshesApplied,
Sample.MaxApplies, *Number(Sample.ApplyBudgetMilliseconds),
Sample.MaxApplies, Sample.SupplementalFarApplies,
*Number(Sample.ApplyBudgetMilliseconds),
Sample.bCountLimitReached ? 1 : 0, Sample.bTimeLimitReached ? 1 : 0,
*PendingByLevel, *ApplyResultsByLevel, *MeshesByLevel, *ApplyMillisecondsByLevel));
}
+91 -4
View File
@@ -268,6 +268,12 @@ namespace
GVoxelForgeStreamingResultBacklogCap,
TEXT("Maximum queued results plus admitted tile tasks; 0 disables the safety cap. This is separate from the worker-slot cap."));
int32 GVoxelForgeStreamingFarApplySupplement = 1;
FAutoConsoleVariableRef CVarVoxelForgeStreamingFarApplySupplement(
TEXT("voxel.StreamingFarApplySupplement"),
GVoxelForgeStreamingFarApplySupplement,
TEXT("After the normal visible-apply count is reached, allow one far mesh apply when half of the frame time budget remains; 0 disables the supplemental far lane."));
int32 GVoxelForgeStreamingReadyQueueDepth = 64;
FAutoConsoleVariableRef CVarVoxelForgeStreamingReadyQueueDepth(
TEXT("voxel.StreamingReadyQueueDepth"),
@@ -2223,6 +2229,12 @@ void AVoxelWorld::BeginPlay()
}
FParse::Value(FCommandLine::Get(), TEXT("voxel.StreamingStartupApplyBoost="),
GVoxelForgeStreamingStartupApplyBoost);
if (FParse::Value(FCommandLine::Get(), TEXT("voxel.StreamingFarApplySupplement="),
GVoxelForgeStreamingFarApplySupplement))
{
GVoxelForgeStreamingFarApplySupplement =
GVoxelForgeStreamingFarApplySupplement != 0 ? 1 : 0;
}
// Headless BuildHost does not reliably apply arbitrary console-variable command-line tokens
// before BeginPlay; parse the test switches explicitly so A/B runs exercise the requested path.
// BuildHost sans interface n'applique pas toujours les CVar arbitraires avant BeginPlay ;
@@ -2737,6 +2749,7 @@ void AVoxelWorld::BeginPlay()
"\"streaming_collision_lookahead\":%d,\"core_region_concurrent_admission\":%d,"
"\"collision_gate\":%d,"
"\"streaming_result_backlog_cap\":%d,\"streaming_startup_apply_boost\":%d,"
"\"streaming_far_apply_supplement\":%d,"
"\"streaming_background_worker_reserve\":%d,\"core_parallel_for_background_priority\":%d,"
"\"streaming_tile_background_low\":%d,\"streaming_tile_background_normal\":%d,"
"\"core_column_cache_direct_mapped\":%d,"
@@ -2758,6 +2771,7 @@ void AVoxelWorld::BeginPlay()
GVoxelForgeStreamingCollisionLookahead, GVoxelForgeCoreRegionConcurrentAdmission,
GVoxelForgeCollisionGate,
GVoxelForgeStreamingResultBacklogCap, GVoxelForgeStreamingStartupApplyBoost,
GVoxelForgeStreamingFarApplySupplement,
GVoxelForgeStreamingBackgroundWorkerReserve,
GVoxelForgeCoreParallelForBackgroundPriority,
GVoxelForgeStreamingTileBackgroundLow,
@@ -9881,6 +9895,7 @@ void AVoxelWorld::ProcessPendingChunks()
const double ApplyBudgetSeconds =
static_cast<double>(ApplyBudgetMilliseconds) * 0.001;
int32 MeshesApplied = 0;
int32 SupplementalFarApplies = 0;
int32 ResultsDrained = 0;
int32 ApplyResultsByLevelTotal = 0;
double ApplySeconds = 0.0;
@@ -9888,6 +9903,8 @@ void AVoxelWorld::ProcessPendingChunks()
TStaticArray<int32, 9> MeshesAppliedByLevel{};
TStaticArray<double, 9> ApplySecondsByLevel{};
bool bTimeBudgetHit = false;
bool bForceSupplementalFarDequeue = false;
bool bDequeuedSupplementalFar = false;
const auto RecordApplyFrame = [&]()
{
if (!VoxelForgeStartupTrace::IsActive()) return;
@@ -9911,6 +9928,7 @@ void AVoxelWorld::ProcessPendingChunks()
Sample.ResultsDrained = ResultsDrained;
Sample.ApplyResultsByLevelTotal = ApplyResultsByLevelTotal;
Sample.MeshesApplied = MeshesApplied;
Sample.SupplementalFarApplies = SupplementalFarApplies;
Sample.MaxApplies = MaxApplies;
Sample.ApplyBudgetMilliseconds = ApplyBudgetMilliseconds;
Sample.bCountLimitReached = MeshesApplied >= MaxApplies;
@@ -9939,6 +9957,7 @@ void AVoxelWorld::ProcessPendingChunks()
FChunkResult DequeuedChunk;
const auto DequeueNextResult = [&]() -> bool
{
bDequeuedSupplementalFar = false;
if (bStep1UploadCorpusReleased
&& Step1HeldApplyCursor < Step1HeldApplyResults.Num())
{
@@ -9954,8 +9973,19 @@ void AVoxelWorld::ProcessPendingChunks()
// Mirror the admission order. A horizon result that completed earlier must not consume
// the game-thread apply budget ahead of collision support, an edit, or ordinary LOD0.
if (CriticalProcessQueue.Dequeue(DequeuedChunk)
|| EditedProcessQueue.Dequeue(DequeuedChunk)
|| NearProcessQueue.Dequeue(DequeuedChunk)
|| EditedProcessQueue.Dequeue(DequeuedChunk))
{
RecordStreamingResultDequeued(DequeuedChunk);
return true;
}
if (bForceSupplementalFarDequeue)
{
if (!ProcessQueue.Dequeue(DequeuedChunk)) return false;
bDequeuedSupplementalFar = true;
RecordStreamingResultDequeued(DequeuedChunk);
return true;
}
if (NearProcessQueue.Dequeue(DequeuedChunk)
|| ProcessQueue.Dequeue(DequeuedChunk))
{
RecordStreamingResultDequeued(DequeuedChunk);
@@ -10104,6 +10134,10 @@ void AVoxelWorld::ProcessPendingChunks()
if (bMeshApplied)
{
++MeshesApplied;
if (bDequeuedSupplementalFar && ResultLevel >= 3)
{
++SupplementalFarApplies;
}
if (ResultLevel >= 0 && ResultLevel < 9)
{
++MeshesAppliedByLevel[ResultLevel];
@@ -10122,6 +10156,19 @@ void AVoxelWorld::ProcessPendingChunks()
}
if (MeshesApplied >= MaxApplies)
{
const double DrainElapsedSeconds = FPlatformTime::ToSeconds64(
FPlatformTime::Cycles64() - DrainStartCycles);
const bool bCanSupplementFar = MeshesApplied == MaxApplies
&& SupplementalFarApplies == 0
&& !bUseStartupApplyBoost
&& GVoxelForgeStreamingFarApplySupplement != 0
&& ApplyBudgetSeconds > 0.0
&& DrainElapsedSeconds < ApplyBudgetSeconds * 0.5;
if (bCanSupplementFar)
{
bForceSupplementalFarDequeue = true;
continue;
}
break;
}
}
@@ -15360,6 +15407,8 @@ bool AVoxelWorld::ApplyMeshToTile(FChunkResult& Result)
const int32 NumIndices = Result.NumTriangles * 3;
const int32 FirstCapIndex = FMath::Clamp(
NumIndices - Result.NumCeilingTriangles * 3, 0, NumIndices);
TFuture<ERealtimeMeshProxyUpdateStatus> ProxyPublicationFuture;
bool bHasProxyPublicationFuture = false;
{
TRACE_CPUPROFILER_EVENT_SCOPE(VoxelForge_RMC_CreateSections);
if (bHasGroundTris)
@@ -15369,9 +15418,10 @@ bool AVoxelWorld::ApplyMeshToTile(FChunkResult& Result)
const FRealtimeMeshStreamRange GroundRange =
URealtimeMeshBlueprintFunctionLibrary::MakeStreamRange(
0, Result.NumVertices, 0, FirstCapIndex);
RTMesh->CreateSection(
ProxyPublicationFuture = RTMesh->CreateSection(
FRealtimeMeshSectionKey::CreateForPolyGroup(GroupKey, 0),
GroundConfig, GroundRange, /*bShouldCreateCollision*/ bWantsCollision);
bHasProxyPublicationFuture = true;
}
if (bHasCeilingTris)
{
@@ -15380,11 +15430,48 @@ bool AVoxelWorld::ApplyMeshToTile(FChunkResult& Result)
const FRealtimeMeshStreamRange CapRange =
URealtimeMeshBlueprintFunctionLibrary::MakeStreamRange(
0, Result.NumVertices, FirstCapIndex, NumIndices);
RTMesh->CreateSection(
ProxyPublicationFuture = RTMesh->CreateSection(
FRealtimeMeshSectionKey::CreateForPolyGroup(GroupKey, 1),
CapConfig, CapRange, /*bShouldCreateCollision*/ bWantsCollision);
bHasProxyPublicationFuture = true;
}
}
const uint64 ProxyPublicationSubmitCycles = FPlatformTime::Cycles64();
if (bTraceRmcTiming && bHasProxyPublicationFuture)
{
const TWeakObjectPtr<AVoxelWorld> WeakWorld(this);
const TWeakObjectPtr<URealtimeMeshComponent> WeakComponent(MeshComp);
const FVoxelTileKey PublishedTile = Tile;
const uint64 RequestOrdinal = Result.RequestOrdinal;
const uint64 ApplyStartedCycles = ApplyStartCycles;
ProxyPublicationFuture.Next(
[WeakWorld, WeakComponent, PublishedTile, RequestOrdinal,
ApplyStartedCycles, ProxyPublicationSubmitCycles](
ERealtimeMeshProxyUpdateStatus Status)
{
if (!VoxelForgeStartupTrace::IsActive()) return;
const uint64 PublishedCycles = FPlatformTime::Cycles64();
const URealtimeMeshComponent* Component = WeakComponent.Get();
VoxelForgeStartupTrace::RecordEvent(TEXT("rmc_proxy_published"), FString::Printf(
TEXT("\"tile\":[%d,%d,%d],\"level\":%d,\"request_ordinal\":%llu,"
"\"proxy_update_status\":%d,\"apply_to_proxy_ms\":%.3f,"
"\"section_submit_to_proxy_ms\":%.3f,\"component_visible\":%d,"
"\"world_valid\":%d"),
PublishedTile.Coord.X, PublishedTile.Coord.Y, PublishedTile.Coord.Z,
PublishedTile.Level, static_cast<unsigned long long>(RequestOrdinal),
static_cast<int32>(Status),
ApplyStartedCycles != 0 && PublishedCycles >= ApplyStartedCycles
? FPlatformTime::ToSeconds64(PublishedCycles - ApplyStartedCycles) * 1000.0
: 0.0,
ProxyPublicationSubmitCycles != 0
&& PublishedCycles >= ProxyPublicationSubmitCycles
? FPlatformTime::ToSeconds64(
PublishedCycles - ProxyPublicationSubmitCycles) * 1000.0
: 0.0,
Component && Component->IsVisible() ? 1 : 0,
WeakWorld.IsValid() ? 1 : 0));
});
}
if (bTraceRmcTiming)
{
TraceSectionConfigMilliseconds = FPlatformTime::ToSeconds64(
@@ -59,6 +59,7 @@ namespace VoxelForgeStartupTrace
int32 ResultsDrained = 0;
int32 ApplyResultsByLevelTotal = 0;
int32 MeshesApplied = 0;
int32 SupplementalFarApplies = 0;
int32 MaxApplies = 0;
double ApplyBudgetMilliseconds = 0.0;
bool bCountLimitReached = false;