streaming: far LODs keep a share while near work is pending (L79); no more horizon starvation

L78's strict near-first order starved far LODs at 30 m/s (100% far holes, never completed).
Unreal policy 2: once the collision ring is ready, LOD0-2 keep their reserve and far tiles are
admitted as low-priority Horizon work; headless gives far work 1 of every 16 requests.
Moving camera, far holes while moving: 1.4 m/s L77 8% / L78 29% / L79 31%; 30 m/s L77 8% /
L78 100% / L79 72% (completes on dwell). Near readiness while moving at 30 m/s: 52 / 51 / 67%.
Still worse than L77 for fast travel -> speed-adaptive policy next. World unchanged (v213).
Fast tier PASS; Linux UE host builds.

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-27 20:17:35 +01:00
1 parent ec20994a8e
commit 2c8a26c0d0
11 files changed
+833 -30

No files matched your search

+63 -18
View File
@@ -208,6 +208,12 @@ namespace
GVoxelForgeStreamingCoarseFirst,
TEXT("Prioritize walkable tiles, then finish LOD0-2 before far clipmap work; controls far-level order."));
int32 GVoxelForgeStreamingSchedulerPolicy = 2;
FAutoConsoleVariableRef CVarVoxelForgeStreamingSchedulerPolicy(
TEXT("voxel.StreamingSchedulerPolicy"),
GVoxelForgeStreamingSchedulerPolicy,
TEXT("Streaming order: 0=L77 coarse-first, 1=L78 strict near-first, 2=L79 fair far share."));
int32 GVoxelForgeStreamingDynamicNearReserve = 1;
FAutoConsoleVariableRef CVarVoxelForgeStreamingDynamicNearReserve(
TEXT("voxel.StreamingDynamicNearReserve"),
@@ -11949,6 +11955,9 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
const int32 NearAdmissionCap = bPawnMoving ? MaxTasks : TotalAdmissionCap;
const int32 CoarseTaskCap = FMath::Max(1, MaxTasks - NearTaskReserve) + ReadyQueueDepth;
constexpr int32 FirstFarLevel = 3;
const int32 SchedulerPolicy = FMath::Clamp(GVoxelForgeStreamingSchedulerPolicy, 0, 2);
const int32 FirstCoarseLevel = FMath::Max(
2, Settings ? Settings->FullResClipLevels : 2);
const bool bUseCoarseFirstOrder = GVoxelForgeStreamingCoarseFirst != 0
&& bWalkableRingReadyForReserve;
int32 SchedulerSubmittedByLevel[9] = {};
@@ -12449,34 +12458,60 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
return true;
};
// The support and collision-critical set drains first. Then LOD0, LOD1, and LOD2
// use the near lane. Far tiles are not admitted until every requested near tile is ready.
if (AreCriticalTilesReady() && bWalkableRingReadyForReserve)
{
for (int32 Level = 0; Level <= 2 && Level <= MaxDesiredLevel; ++Level)
{
const EVoxelTileWorkPriority Priority = Level == 0
? EVoxelTileWorkPriority::LOD0 : EVoxelTileWorkPriority::Horizon;
SubmitLevel(Level, Priority, NearAdmissionCap, true);
}
}
if (AreNearLODTilesReady())
// Policy 0 reconstructs L77's coarse-first admission order for the moving-camera control.
if (SchedulerPolicy == 0)
{
if (bUseCoarseFirstOrder)
{
for (int32 Level = MaxDesiredLevel; Level >= FirstFarLevel; --Level)
for (int32 Level = MaxDesiredLevel; Level >= FirstCoarseLevel; --Level)
{
SubmitLevel(Level, EVoxelTileWorkPriority::Horizon,
CoarseTaskCap, true);
}
for (int32 Level = 0; Level < FirstCoarseLevel && Level <= MaxDesiredLevel; ++Level)
{
const EVoxelTileWorkPriority Priority = Level == 0
? EVoxelTileWorkPriority::LOD0 : EVoxelTileWorkPriority::Horizon;
SubmitLevel(Level, Priority,
Priority == EVoxelTileWorkPriority::LOD0 ? NearAdmissionCap : CoarseTaskCap,
true);
}
}
else
{
SubmitLevel(0, EVoxelTileWorkPriority::LOD0, NearAdmissionCap, false);
for (int32 Level = 1; Level <= MaxDesiredLevel; ++Level)
{
SubmitLevel(Level, EVoxelTileWorkPriority::Horizon,
CoarseTaskCap, false);
if (GetGenerationAdmissionCount() >= CoarseTaskCap) break;
}
}
}
else
{
const bool bNearAdmissionReady = AreCriticalTilesReady()
&& bWalkableRingReadyForReserve;
if (bNearAdmissionReady)
{
for (int32 Level = 0; Level <= 2 && Level <= MaxDesiredLevel; ++Level)
{
const EVoxelTileWorkPriority Priority = Level == 0
? EVoxelTileWorkPriority::LOD0 : EVoxelTileWorkPriority::Horizon;
SubmitLevel(Level, Priority, NearAdmissionCap, true);
}
}
// L78 waits for all requested near tiles. L79 keeps a one-task far lane open
// after critical requests; CoarseTaskCap reserves the remaining admissions for near work.
const bool bFarAdmissionReady = SchedulerPolicy == 1
? AreNearLODTilesReady() : true;
if (bFarAdmissionReady)
{
for (int32 Level = FirstFarLevel; Level <= MaxDesiredLevel; ++Level)
{
SubmitLevel(Level, EVoxelTileWorkPriority::Horizon,
CoarseTaskCap, false);
CoarseTaskCap, bUseCoarseFirstOrder);
if (GetGenerationAdmissionCount() >= CoarseTaskCap)
{
if (Level >= 0 && Level < 9) { ++SchedulerLevelCapBreaks[Level]; }
@@ -12643,7 +12678,16 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
> ResultBacklogCapStopsAtUpdateEntry;
for (int32 Level = 0; Level < 9; ++Level)
{
AdmissionCapByLevel[Level] = Level <= 2 ? NearAdmissionCap : CoarseTaskCap;
if (SchedulerPolicy == 0)
{
AdmissionCapByLevel[Level] = bUseCoarseFirstOrder
? (Level >= FirstCoarseLevel || Level > 0 ? CoarseTaskCap : NearAdmissionCap)
: (Level == 0 ? NearAdmissionCap : CoarseTaskCap);
}
else
{
AdmissionCapByLevel[Level] = Level <= 2 ? NearAdmissionCap : CoarseTaskCap;
}
if (DesiredMissingByLevel[Level] <= 0) continue;
if (bAllChunksLoaded)
@@ -12730,7 +12774,7 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
"\"core_region_concurrent_admission\":%d,"
"\"max_tasks\":%d,\"ready_queue_depth\":%d,"
"\"total_admission_cap\":%d,\"near_admission_cap\":%d,"
"\"near_reserve\":%d,"
"\"near_reserve\":%d,\"scheduler_policy\":%d,"
"\"coarse_cap\":%d,\"first_far_level\":%d,"
"\"submission_stop_level\":%d,\"submission_stop_cap\":%d,"
"\"pending_entry\":%d,\"pending_after\":%d,\"admission_occupancy\":%d,"
@@ -12754,7 +12798,8 @@ void AVoxelWorld::UpdateChunksAroundPosition(const FVector& CenterPosition, APaw
GVoxelForgeStreamingCoarseFirst, GVoxelForgeStreamingDynamicNearReserve,
GVoxelForgeStreamingLegacyPendingResultCap,
GVoxelForgeCoreRegionConcurrentAdmission, MaxTasks, ReadyQueueDepth,
TotalAdmissionCap, NearAdmissionCap, NearTaskReserve, CoarseTaskCap, FirstFarLevel,
TotalAdmissionCap, NearAdmissionCap, NearTaskReserve, SchedulerPolicy,
CoarseTaskCap, FirstFarLevel,
SchedulerOrderStopLevel, SchedulerOrderStopCap,
PendingTilesAtUpdateEntry, PendingTiles.Num(), AdmissionOccupancy, ActiveTaskGuard,
ActiveGenerationWorkerCount.load(std::memory_order_relaxed), PendingResultsEstimate,