streaming: restore same-level refill; early admission on by default; fixed UE harness (L172)

Scheduler stable-sorts the whole level and checks capacity per admission (refill when slots free mid-pass); regression
test with the old partial-sort path as negative control. Harness repoints Source/Standalone/uplugin together, records
root HEAD/status, builds baselines from fresh worktrees, gates on DWARF struct sizes (480/480/480).
Frame-resolution arrival: A/A p90 36.8 ms; fixed-on vs fixed-off -12.2 ms median (4/10 slower). 30 m/s: near 43.3 ->
55.3%, far holes 1.8 -> 0%, p99 <= 7.46 ms, worst <= 12.3 ms.
Defaults: StreamingFastTravelWaitForAllCriticalTiles=0, StreamingFastTravelApplyBudgetMilliseconds=1.0,
StreamingIncrementalDesiredSet=1, CoreRegionConcurrentAdmission=1, StreamingFastTravelForwardFirst=0,
StreamingRebuildOnCoreRegionCompletion=1, StreamingCoreDesiredCacheByCenter=0, audits 0.
Source/: VoxelWorld.cpp, VoxelStreamingAdmissionOrder.h (new).

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-11-02 20:27:24 +01:00
1 parent 9d088ef96c
commit 52cb3d7a23
7 files changed
+1149 -24

No files matched your search

@@ -0,0 +1,28 @@
#pragma once
#include <algorithm>
namespace VoxelStreamingAdmissionOrder
{
template <typename Iterator, typename Less>
void StableSortCandidates(Iterator First, Iterator Last, Less Compare)
{
std::stable_sort(First, Last, Compare);
}
template <typename Range, typename IsAtCapacity, typename SubmitCandidate,
typename OnCapacityReached>
void AdmitInOrder(const Range& Candidates, IsAtCapacity AtCapacity,
SubmitCandidate Submit, OnCapacityReached CapacityReached)
{
for (const auto& Candidate : Candidates)
{
if (AtCapacity())
{
CapacityReached();
break;
}
Submit(Candidate);
}
}
}
+20 -24
View File
@@ -2,6 +2,7 @@
// Implementation of the voxel world manager
#include "VoxelWorld.h"
#include "VoxelStreamingAdmissionOrder.h"
#include "VoxelDiffLayer.h"
#include "RealtimeMeshComponent.h"
#include "RealtimeMeshSimple.h"
@@ -262,7 +263,7 @@ namespace
GVoxelForgeCoreRegionConcurrentAdmission,
TEXT("Allow tiles independent of a pending Core region compile to proceed; 0 restores the global streaming stop."));
int32 GVoxelForgeStreamingFastTravelWaitForAllCriticalTiles = 1;
int32 GVoxelForgeStreamingFastTravelWaitForAllCriticalTiles = 0;
FAutoConsoleVariableRef CVarVoxelForgeStreamingFastTravelWaitForAllCriticalTiles(
TEXT("voxel.StreamingFastTravelWaitForAllCriticalTiles"),
GVoxelForgeStreamingFastTravelWaitForAllCriticalTiles,
@@ -361,7 +362,7 @@ namespace
TEXT("voxel.StreamingStartupApplyBoost"),
GVoxelForgeStreamingStartupApplyBoost,
TEXT("Bounded cold-view upload budget (default on): 1 allows a 14 ms / 24-mesh cap until the initial desired set and walkable ring are ready; 0 uses the authored per-frame budget."));
float GVoxelForgeStreamingFastTravelApplyBudgetMilliseconds = 0.0f;
float GVoxelForgeStreamingFastTravelApplyBudgetMilliseconds = 1.0f;
FAutoConsoleVariableRef CVarVoxelForgeStreamingFastTravelApplyBudgetMilliseconds(
TEXT("voxel.StreamingFastTravelApplyBudgetMilliseconds"),
GVoxelForgeStreamingFastTravelApplyBudgetMilliseconds,
@@ -14265,17 +14266,14 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
{
const uint64 TraceLevelSortStartCycles = bTraceStreamingScheduler
? FPlatformTime::Cycles64() : 0;
const int32 LevelSubmissionCount = FMath::Min(
LevelTiles.Num(), FMath::Max(
0, AdmissionCap - GetGenerationAdmissionCount()));
const bool bUseForwardFirstOrder =
GVoxelForgeStreamingFastTravelForwardFirst != 0
&& bPolicy3FastTravel && Level <= 2;
if (LevelSubmissionCount > 0 && bUseForwardFirstOrder)
if (bUseForwardFirstOrder)
{
SortNearTilesForwardFirst(LevelTiles);
}
else if (LevelSubmissionCount > 0)
else
{
FVector Heading = GetActorTransform().InverseTransformVectorNoScale(PlayerHeading);
if (Heading.IsNearlyZero() && IsValid(PlayerPawn))
@@ -14288,12 +14286,10 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
const double TileSizeCm = static_cast<double>(VF_ClipLevelExtentVoxels(Level))
* GetActiveVoxelSizeCm();
const bool bUseFastNearLeadOrder = bPolicy3FastTravel && Level <= 2;
// The full order is deterministic because the comparator breaks every tie
// with the tile coordinates. Select only the prefix this admission pass can
// submit; sorting every outstanding key made a small worker cap pay O(N log N).
std::partial_sort(LevelTiles.GetData(),
LevelTiles.GetData() + LevelSubmissionCount,
LevelTiles.GetData() + LevelTiles.Num(),
// Keep the complete stable order. Capacity can open while this pass is
// submitting; truncating to the pass-start count starves this level's refill.
VoxelStreamingAdmissionOrder::StableSortCandidates(
LevelTiles.GetData(), LevelTiles.GetData() + LevelTiles.Num(),
[&](const FVoxelTileKey& A, const FVoxelTileKey& B)
{
const FVector CenterA(
@@ -14348,7 +14344,6 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
if (A.Coord.Y != B.Coord.Y) return A.Coord.Y < B.Coord.Y;
return A.Coord.Z < B.Coord.Z;
});
LevelTiles.SetNum(LevelSubmissionCount, EAllowShrinking::No);
}
if (bTraceStreamingScheduler)
{
@@ -14358,18 +14353,19 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
}
const uint64 TraceLevelAdmissionStartCycles = bTraceStreamingScheduler
? FPlatformTime::Cycles64() : 0;
for (const FVoxelTileKey& T : LevelTiles)
{
if (GetGenerationAdmissionCount() >= AdmissionCap)
VoxelStreamingAdmissionOrder::AdmitInOrder(LevelTiles,
[&]() { return GetGenerationAdmissionCount() >= AdmissionCap; },
[&](const FVoxelTileKey& T)
{
if (PendingTiles.Contains(T)) return;
if (LoadedTiles.Contains(T)) return;
SubmitTileWithTraceCount(T, Priority);
++Submitted;
},
[&]()
{
if (Level >= 0 && Level < 9) { ++SchedulerLevelCapBreaks[Level]; }
break;
}
if (PendingTiles.Contains(T)) continue;
if (LoadedTiles.Contains(T)) continue;
SubmitTileWithTraceCount(T, Priority);
++Submitted;
}
});
if (bTraceStreamingScheduler)
{
LevelAdmissionMilliseconds += FPlatformTime::ToSeconds64(