perf(streaming): reserve destination reveal capacity

Join destination scheduling to the canonical reveal generation, protect its share across every typed frame-budget dimension, and prevent stale work from clearing a replacement reservation. Remove forced incomplete materialization and project retail's centered portal wait cue while the authored tunnel remains active.

Tests: Release build clean; 91 focused reservation/reveal tests; full solution 8,158 passed, 5 skipped.

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
Erik 2026-07-24 19:39:23 +02:00
parent 98f1ac8934
commit 2ff8f844b0
33 changed files with 870 additions and 230 deletions

View file

@ -1024,14 +1024,14 @@ public sealed class LandblockPresentationPipelineTests
MaxGpuUploadBytes: 1_000_000,
MaxGlRetireOperations: 1_000,
DestinationReserveFraction: 0.75f));
controller.PriorityLandblockId = priorityId;
controller.BeginDestinationReservation(1, priorityId, 0);
Assert.Throws<InvalidOperationException>(() => controller.Tick(0x70, 0x70));
Assert.Empty(outbox);
Assert.False(state.IsLoaded(laterId));
Assert.True(state.IsLoaded(unloadId));
controller.PriorityLandblockId = 0;
controller.EndDestinationReservation(1);
controller.Tick(0x70, 0x70);
Assert.True(state.IsLoaded(priorityId));

View file

@ -46,22 +46,23 @@ public sealed class LocalPlayerTeleportControllerTests
harness.Controller.OfferDestination(
destination,
teleportTimestampAdvanced: true);
Assert.Empty(harness.Streaming.PriorityWrites);
Assert.Empty(harness.Streaming.Reservations);
harness.Controller.OnTeleportStarted(7);
Assert.Equal(1, harness.Input.EndCount);
Assert.Equal(1, harness.Mode.EnterPortalCount);
Assert.Equal(Matrix4x4.Identity, harness.Presentation.BeginProjection);
Assert.Equal((0x2021FFFFu, LocalPlayerTeleportController.NearRingRadius),
Assert.Single(harness.Streaming.PriorityWrites));
Assert.Equal(
(1L, 0x20210001u, WorldRevealReadinessBarrier.OutdoorNeighborhoodRadius),
Assert.Single(harness.Streaming.Reservations));
Assert.True(harness.Reveal.Snapshot.IsActive);
Assert.Equal(WorldRevealKind.Portal, harness.Reveal.Snapshot.Kind);
harness.Controller.OfferDestination(
destination,
teleportTimestampAdvanced: false);
Assert.Single(harness.Streaming.PriorityWrites);
Assert.Single(harness.Streaming.Reservations);
}
[Fact]
@ -89,7 +90,7 @@ public sealed class LocalPlayerTeleportControllerTests
Assert.True(harness.Controller.IsActive);
Assert.Equal(0x20210001u, harness.Controller.ActiveDestinationCell);
Assert.NotNull(harness.Presentation.BeginProjection);
Assert.Single(harness.Streaming.PriorityWrites);
Assert.Single(harness.Streaming.Reservations);
}
[Fact]
@ -105,14 +106,14 @@ public sealed class LocalPlayerTeleportControllerTests
teleportTimestampAdvanced: true);
Assert.Equal(0u, harness.Controller.ActiveDestinationCell);
Assert.Empty(harness.Streaming.PriorityWrites);
Assert.Empty(harness.Streaming.Reservations);
harness.Mode.Controller = new PlayerMovementController(new PhysicsEngine());
harness.Mode.Controller.SetPosition(Vector3.Zero, 0x20210001u, Vector3.Zero);
harness.Controller.Tick(0.016f);
Assert.Equal(0x20210001u, harness.Controller.ActiveDestinationCell);
Assert.Single(harness.Streaming.PriorityWrites);
Assert.Single(harness.Streaming.Reservations);
}
[Fact]
@ -158,7 +159,6 @@ public sealed class LocalPlayerTeleportControllerTests
Assert.Empty(harness.Streaming.Recenters);
Assert.Equal(new Vector3(20f, 30f, 4f), harness.Placement.Position);
Assert.Equal(0x20210123u, harness.Placement.CellId);
Assert.False(harness.Placement.Forced);
}
[Fact]
@ -188,7 +188,7 @@ public sealed class LocalPlayerTeleportControllerTests
}
[Fact]
public void ReadinessHold_UsesWallClockAndForcesExactlyAtTenSeconds()
public void ReadinessHold_NeverRevealsIncompleteWorldAndShowsWaitCueAfterFiveSeconds()
{
var harness = new Harness(worldReady: false);
harness.Controller.OnTeleportStarted(5);
@ -197,15 +197,18 @@ public sealed class LocalPlayerTeleportControllerTests
teleportTimestampAdvanced: true);
harness.Presentation.EmitPlaceWhenReady = true;
harness.Controller.Tick(9.5f);
harness.Controller.Tick(4.9f);
Assert.False(Assert.Single(harness.Presentation.WorldReadyValues));
Assert.False(harness.Presentation.WaitCueValues[^1]);
Assert.Equal(default, harness.Placement.Position);
harness.Controller.Tick(0.5f);
harness.Controller.Tick(0.1f);
harness.Controller.Tick(30f);
Assert.True(harness.Presentation.WorldReadyValues[^1]);
Assert.True(harness.Placement.Forced);
Assert.Equal(new Vector3(1f, 2f, 3f), harness.Placement.Position);
Assert.All(harness.Presentation.WorldReadyValues, Assert.False);
Assert.True(harness.Presentation.WaitCueValues[^1]);
Assert.Equal(default, harness.Placement.Position);
Assert.True(harness.Reveal.WaitCueShown);
}
[Fact]
@ -223,7 +226,6 @@ public sealed class LocalPlayerTeleportControllerTests
harness.Controller.Tick(0.016f);
Assert.True(Index(order, "placement") < Index(order, "[world-reveal] event=materialized"));
Assert.True(Index(order, "[world-reveal] event=materialized") < Index(order, "priority-clear"));
Assert.Equal(1, harness.Reveal.PortalMaterializationCount);
}
@ -249,6 +251,8 @@ public sealed class LocalPlayerTeleportControllerTests
Assert.False(harness.Controller.IsActive);
Assert.Equal(0u, harness.Controller.ActiveDestinationCell);
Assert.Equal(1, harness.Session.LoginCompleteCount);
Assert.True(harness.Reveal.Snapshot.Completed);
Assert.False(harness.Reveal.Snapshot.Cancelled);
}
[Fact]
@ -261,7 +265,7 @@ public sealed class LocalPlayerTeleportControllerTests
teleportTimestampAdvanced: true);
harness.Controller.OnTeleportStarted(11);
harness.Controller.Tick(LocalPlayerTeleportController.MaximumWorldHoldSeconds);
harness.Controller.Tick(30f);
Assert.Equal(default, harness.Placement.Position);
Assert.Equal(0u, harness.Controller.ActiveDestinationCell);
@ -318,7 +322,7 @@ public sealed class LocalPlayerTeleportControllerTests
harness.Controller.OfferDestination(
Position(0x20210001u, 20, 1f, 2f, 3f),
teleportTimestampAdvanced: true);
harness.Streaming.PriorityClearCount = 0;
harness.Streaming.ReservationEnds.Clear();
harness.Placement.OnPlace = () => harness.Controller.OnTeleportStarted(21);
harness.Presentation.Enqueue(TeleportAnimEvent.Place);
@ -327,7 +331,7 @@ public sealed class LocalPlayerTeleportControllerTests
Assert.True(harness.Controller.IsActive);
Assert.Equal(0u, harness.Controller.ActiveDestinationCell);
Assert.Equal(0, harness.Reveal.PortalMaterializationCount);
Assert.Equal(1, harness.Streaming.PriorityClearCount);
Assert.Single(harness.Streaming.ReservationEnds);
}
[Fact]
@ -418,7 +422,7 @@ public sealed class LocalPlayerTeleportControllerTests
var position = new Vector3(12f, 24f, 6f);
Quaternion rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, 0.5f);
placement.Place(position, cell, rotation, forced: false);
placement.Place(position, cell, rotation);
Assert.Equal(entity.Position, controllerSlot.Controller.Position);
Assert.Equal(entity.ParentCellId, controllerSlot.Controller.CellId);
@ -560,7 +564,8 @@ public sealed class LocalPlayerTeleportControllerTests
prepareCompositeTextures: (_, _) => { },
invalidateCompositeTextures: () => { },
isSpawnClaimUnhydratable: _ => false,
log: order.Add);
log: order.Add,
streaming: Streaming);
Controller = new LocalPlayerTeleportController(
Authority,
Input,
@ -619,7 +624,9 @@ public sealed class LocalPlayerTeleportControllerTests
}
}
private sealed class FakeStreaming : ILocalPlayerTeleportStreamingOperations
private sealed class FakeStreaming
: ILocalPlayerTeleportStreamingOperations,
IWorldRevealStreamingScheduler
{
private readonly List<string> _order;
@ -636,9 +643,10 @@ public sealed class LocalPlayerTeleportControllerTests
public bool RecenterPending;
public bool ResetResult = true;
public bool LastResetWasSessionEnding;
public int PriorityClearCount;
public readonly List<(int X, int Y, bool Sealed)> Recenters = new();
public readonly List<(uint Landblock, int Radius)> PriorityWrites = new();
public readonly List<(long Generation, uint Cell, int Radius)>
Reservations = new();
public readonly List<long> ReservationEnds = new();
public bool BeginRecenter(int x, int y, bool isSealedDungeon)
{
@ -655,13 +663,17 @@ public sealed class LocalPlayerTeleportControllerTests
public bool IsSealedDungeon(uint cellId) =>
(cellId & 0xFFFFu) >= 0x0100u;
public void SetPriority(uint landblockId, int radius) =>
PriorityWrites.Add((landblockId, radius));
public void BeginDestinationReservation(
long revealGeneration,
uint destinationCell,
int requiredRenderRadius) =>
Reservations.Add(
(revealGeneration, destinationCell, requiredRenderRadius));
public void ClearPriority()
public void EndDestinationReservation(long revealGeneration)
{
PriorityClearCount++;
_order.Add("priority-clear");
ReservationEnds.Add(revealGeneration);
_order.Add("reservation-end");
}
}
@ -674,16 +686,14 @@ public sealed class LocalPlayerTeleportControllerTests
public Vector3 Position;
public uint CellId;
public Quaternion Rotation;
public bool Forced;
public Action? OnPlace;
public void Place(Vector3 position, uint cellId, Quaternion rotation, bool forced)
public void Place(Vector3 position, uint cellId, Quaternion rotation)
{
_order.Add("placement");
Position = position;
CellId = cellId;
Rotation = rotation;
Forced = forced;
OnPlace?.Invoke();
}
}
@ -731,6 +741,7 @@ public sealed class LocalPlayerTeleportControllerTests
public Matrix4x4? BeginProjection;
public bool EmitPlaceWhenReady;
public readonly List<bool> WorldReadyValues = new();
public readonly List<bool> WaitCueValues = new();
public int DisposeFailuresRemaining;
public int DisposeCount;
@ -760,6 +771,7 @@ public sealed class LocalPlayerTeleportControllerTests
public void TickTunnel(float deltaSeconds) => _order.Add("tunnel-tick");
public void EnterTunnel() => IsPortalViewportVisible = true;
public void ExitTunnel() => IsPortalViewportVisible = false;
public void SetWaitCue(bool visible) => WaitCueValues.Add(visible);
public void Reset()
{

View file

@ -200,6 +200,7 @@ public sealed class StreamingCompletionQueueTests
result,
estimate,
priority,
priority == StreamingCompletionPriority.Destination ? 1L : 0L,
result.Generation,
sequence,
Stopwatch.GetTimestamp());

View file

@ -117,6 +117,110 @@ public sealed class StreamingWorkBudgetTests
meter.Snapshot.LastLimit);
}
[Fact]
public void ActiveReveal_ProtectsDestinationShareAcrossEveryCountAndByteDimension()
{
var meter = new StreamingWorkMeter(
Budget(
milliseconds: 100,
completions: 4,
cpuBytes: 100,
entityOperations: 8,
gpuBytes: 100,
retireOperations: 4),
static () => 0,
timestampFrequency: 1_000,
destinationReservationActive: true);
StreamingWorkCost unreservedShare = new(
CompletionAdmissions: 1,
AdoptedCpuBytes: 25,
EntityOperations: 2,
GpuUploadBytes: 25,
GlRetireOperations: 1);
Assert.Equal(
StreamingWorkAdmission.Admitted,
meter.TryReserve(unreservedShare, "ordinary"));
meter.Complete();
Assert.Equal(
StreamingWorkAdmission.Yielded,
meter.TryReserve(
new StreamingWorkCost(CompletionAdmissions: 1),
"ordinary-over-reserve"));
using (meter.EnterLane(StreamingWorkLane.Destination))
{
Assert.Equal(
StreamingWorkAdmission.Admitted,
meter.TryReserve(
new StreamingWorkCost(
CompletionAdmissions: 3,
AdoptedCpuBytes: 75,
EntityOperations: 6,
GpuUploadBytes: 75,
GlRetireOperations: 3),
"destination"));
meter.Complete();
}
StreamingWorkMeterSnapshot snapshot = meter.Snapshot;
Assert.Equal(unreservedShare, snapshot.NonDestinationUsed);
Assert.Equal(3, snapshot.DestinationUsed.CompletionAdmissions);
Assert.Equal(100, snapshot.Used.AdoptedCpuBytes);
Assert.Equal(100, snapshot.Used.GpuUploadBytes);
}
[Fact]
public void InactiveReveal_DoesNotApplyDestinationReservation()
{
var meter = new StreamingWorkMeter(
Budget(completions: 4),
static () => 0,
timestampFrequency: 1_000,
destinationReservationActive: false);
Assert.Equal(
StreamingWorkAdmission.Admitted,
meter.TryReserve(
new StreamingWorkCost(CompletionAdmissions: 4),
"ordinary"));
meter.Complete();
Assert.Equal(4, meter.Snapshot.NonDestinationUsed.CompletionAdmissions);
Assert.Equal(0, meter.Snapshot.DestinationUsed.CompletionAdmissions);
}
[Fact]
public void ActiveReveal_ProtectsDestinationWallClockAfterOrdinaryShareIsSpent()
{
long now = 0;
var meter = new StreamingWorkMeter(
Budget(milliseconds: 100),
() => now,
timestampFrequency: 1_000,
destinationReservationActive: true);
Assert.Equal(
StreamingWorkAdmission.Admitted,
meter.TryReserve(default, "ordinary"));
now = 25;
meter.Complete();
Assert.Equal(
StreamingWorkAdmission.Yielded,
meter.TryReserve(default, "ordinary-after-25ms"));
using (meter.EnterLane(StreamingWorkLane.Destination))
{
Assert.Equal(
StreamingWorkAdmission.Admitted,
meter.TryReserve(default, "destination"));
now = 99;
meter.Complete();
}
Assert.Equal(2, meter.Snapshot.CompletedOperations);
}
[Fact]
public void MeterUsesInjectedMonotonicClockAndRecordsOverrunAndFailure()
{
@ -427,21 +531,32 @@ public sealed class StreamingWorkBudgetTests
cpuBytes: 1_000,
gpuBytes: 44,
retireOperations: 1));
controller.PriorityLandblockId = center;
controller.BeginDestinationReservation(1, center, 0);
controller.Tick(32, 32);
Assert.Equal([center], applied);
Assert.Equal(1, controller.WorkDiagnostics.DeferredCompletions);
Assert.Equal(1, controller.WorkDiagnostics.LastFrame.YieldCount);
Assert.Equal(2, controller.WorkDiagnostics.LastFrame.YieldCount);
Assert.Equal(44, controller.WorkDiagnostics.LastFrame.Used.GpuUploadBytes);
Assert.Equal(0, controller.WorkDiagnostics.LastFrame.Used.GlRetireOperations);
controller.Tick(32, 32);
Assert.Equal([center, ordinary], applied);
Assert.Equal(0, controller.WorkDiagnostics.DeferredCompletions);
Assert.Equal(0, controller.WorkDiagnostics.LastFrame.Used.GlRetireOperations);
for (int i = 0;
i < 4
&& (controller.WorkDiagnostics.DeferredCompletions != 0
|| source.BacklogCount != 0);
i++)
{
controller.Tick(32, 32);
}
Assert.Equal(0, controller.WorkDiagnostics.DeferredCompletions);
Assert.Equal(0, source.BacklogCount);
}
[Fact]

View file

@ -13,7 +13,9 @@ public sealed class WorldRevealCoordinatorTests
public int InvalidateCount { get; private set; }
public int PrepareCount { get; private set; }
public WorldRevealCoordinator Build(List<string>? logs = null) => new(
public WorldRevealCoordinator Build(
List<string>? logs = null,
IWorldRevealStreamingScheduler? streaming = null) => new(
isRenderNeighborhoodReady: (_, _) => RenderReady,
isSpawnCellReady: _ => CollisionReady,
isTerrainNeighborhoodReady: (_, _) => CollisionReady,
@ -25,7 +27,8 @@ public sealed class WorldRevealCoordinatorTests
CompositesReady = false;
},
isSpawnClaimUnhydratable: _ => false,
log: logs is null ? null : new Action<string>(logs.Add));
log: logs is null ? null : new Action<string>(logs.Add),
streaming: streaming);
}
[Fact]
@ -34,7 +37,7 @@ public sealed class WorldRevealCoordinatorTests
var state = new State { CompositesReady = true };
WorldRevealCoordinator coordinator = state.Build();
long generation = coordinator.Begin(WorldRevealKind.Login);
long generation = coordinator.Begin(WorldRevealKind.Login, 0x11340021u);
Assert.Equal(1, generation);
Assert.Equal(1, state.InvalidateCount);
@ -52,7 +55,7 @@ public sealed class WorldRevealCoordinatorTests
CollisionReady = true,
};
WorldRevealCoordinator coordinator = state.Build();
coordinator.Begin(WorldRevealKind.Login);
coordinator.Begin(WorldRevealKind.Login, outdoorCell);
WorldRevealReadinessSnapshot first = coordinator.PrepareAndEvaluate(outdoorCell);
state.CompositesReady = true;
@ -76,7 +79,7 @@ public sealed class WorldRevealCoordinatorTests
CompositesReady = true,
};
WorldRevealCoordinator coordinator = state.Build(logs);
coordinator.Begin(WorldRevealKind.Portal);
coordinator.Begin(WorldRevealKind.Portal, outdoorCell);
state.CompositesReady = true;
Assert.True(coordinator.Evaluate(outdoorCell).IsReady);
@ -103,7 +106,7 @@ public sealed class WorldRevealCoordinatorTests
CompositesReady = true,
};
WorldRevealCoordinator coordinator = state.Build();
coordinator.Begin(WorldRevealKind.Portal);
coordinator.Begin(WorldRevealKind.Portal, 0x11340021u);
coordinator.Cancel();
coordinator.PrepareAndEvaluate(0x11340021u);
@ -137,8 +140,8 @@ public sealed class WorldRevealCoordinatorTests
isSpawnClaimUnhydratable: _ => false,
quiescence: quiescence);
Assert.Equal(1, coordinator.Begin(WorldRevealKind.Login));
Assert.Equal(2, coordinator.Begin(WorldRevealKind.Portal));
Assert.Equal(1, coordinator.Begin(WorldRevealKind.Login, 0x11340021u));
Assert.Equal(2, coordinator.Begin(WorldRevealKind.Portal, 0x11340021u));
Assert.False(availability.IsWorldAvailable);
Assert.Equal(2, availability.QuiescedGeneration);
Assert.Equal(1, audio.SuspendCalls);
@ -149,6 +152,30 @@ public sealed class WorldRevealCoordinatorTests
Assert.Equal(1, audio.ResumeCalls);
}
[Fact]
public void RevealGeneration_OwnsExactDestinationReservationUntilCompletion()
{
var state = new State();
var scheduler = new RecordingDestinationScheduler();
WorldRevealCoordinator coordinator = state.Build(streaming: scheduler);
long first = coordinator.Begin(
WorldRevealKind.Portal,
0x11340021u);
long second = coordinator.Begin(
WorldRevealKind.Portal,
0x20210123u);
Assert.Equal(
[
(first, 0x11340021u, 1),
(second, 0x20210123u, 0),
],
scheduler.Begins);
coordinator.Complete();
Assert.Equal([second], scheduler.Ends);
}
private sealed class RecordingAudioQuiescence : AcDream.App.Audio.IWorldAudioQuiescence
{
public int SuspendCalls { get; private set; }
@ -157,4 +184,21 @@ public sealed class WorldRevealCoordinatorTests
public void SuspendWorldAudio() => SuspendCalls++;
public void ResumeWorldAudio() => ResumeCalls++;
}
private sealed class RecordingDestinationScheduler
: IWorldRevealStreamingScheduler
{
public List<(long Generation, uint Cell, int Radius)> Begins { get; } = [];
public List<long> Ends { get; } = [];
public void BeginDestinationReservation(
long revealGeneration,
uint destinationCell,
int requiredRenderRadius) =>
Begins.Add(
(revealGeneration, destinationCell, requiredRenderRadius));
public void EndDestinationReservation(long revealGeneration) =>
Ends.Add(revealGeneration);
}
}

View file

@ -0,0 +1,37 @@
using AcDream.App.UI;
namespace AcDream.App.Tests.UI;
public sealed class PortalWaitNoticeControllerTests
{
[Fact]
public void Notice_IsCenteredOverlayAndDisposesFromRetainedRoot()
{
var root = new UiRoot
{
Width = 1280f,
Height = 720f,
};
using (var controller = new PortalWaitNoticeController(root))
{
UiText text = Assert.IsType<UiText>(Assert.Single(root.Children));
Assert.False(text.Visible);
Assert.True(text.Centered);
Assert.True(text.ClickThrough);
Assert.Equal(root.Width, text.Width);
Assert.Equal(root.Height, text.Height);
controller.Set("In Portal Space - Please Wait...");
Assert.True(text.Visible);
UiText.Line line = Assert.Single(text.LinesProvider!());
Assert.Equal("In Portal Space - Please Wait...", line.Text);
controller.Set(null);
Assert.False(text.Visible);
}
Assert.Empty(root.Children);
}
}

View file

@ -18,7 +18,7 @@ public class StreamingControllerPriorityApplyTests
generation);
[Fact]
public void PriorityLandblock_WinsExecutionOrderAfterBoundedAdmission()
public void DestinationReservation_WinsExecutionOrderAfterBoundedAdmission()
{
uint priority = StreamingRegion.EncodeLandblockIdForTest(169, 180);
var outbox = new Queue<LandblockStreamResult>(new LandblockStreamResult[]
@ -48,7 +48,7 @@ public class StreamingControllerPriorityApplyTests
workBudgetOptions: GenerousBudget())
{ MaxCompletionsPerFrame = 4 };
ctrl.PriorityLandblockId = priority;
ctrl.BeginDestinationReservation(1, priority, 0);
ctrl.Tick(169, 180);
Assert.NotEmpty(applied);
@ -87,10 +87,10 @@ public class StreamingControllerPriorityApplyTests
nearRadius: 4,
farRadius: 12)
{ MaxCompletionsPerFrame = 4 };
ctrl.PriorityLandblockId = priority;
ctrl.BeginDestinationReservation(1, priority, 0);
ctrl.Tick(169, 180); // priority + some others
ctrl.PriorityLandblockId = 0u;
ctrl.EndDestinationReservation(1);
ctrl.Tick(169, 180); // drains the deferred remainder
ctrl.Tick(169, 180);
@ -101,7 +101,7 @@ public class StreamingControllerPriorityApplyTests
[Fact]
public void PriorityNeverArrives_noThrow_noLoss_noDoubleApply()
{
// While a PriorityLandblockId is set but the matching completion never
// While a reveal reservation is active but its matching completion never
// arrives (e.g. the load failed), ordinary results still enter the typed
// Near/Far queues and advance under the same budget without loss.
uint priority = StreamingRegion.EncodeLandblockIdForTest(169, 180);
@ -134,7 +134,7 @@ public class StreamingControllerPriorityApplyTests
{ MaxCompletionsPerFrame = 4 };
// Set a priority id that will NEVER appear in the outbox.
ctrl.PriorityLandblockId = priority;
ctrl.BeginDestinationReservation(1, priority, 0);
// Tick several times — should not throw and every non-priority completion
// must still be applied without duplication.
@ -160,6 +160,30 @@ public class StreamingControllerPriorityApplyTests
MaxGlRetireOperations: 10_000,
DestinationReserveFraction: 0.75f);
[Fact]
public void DestinationReservation_StaleGenerationCannotClearReplacement()
{
var controller = new StreamingController(
enqueueLoad: (_, _) => { },
enqueueUnload: _ => { },
drainCompletions: _ => Array.Empty<LandblockStreamResult>(),
applyTerrain: (_, _) => { },
state: new GpuWorldState(),
nearRadius: 1,
farRadius: 2);
controller.BeginDestinationReservation(1, 0x11340021u, 1);
controller.BeginDestinationReservation(2, 0x20210123u, 0);
controller.EndDestinationReservation(1);
Assert.Equal(2, controller.ActiveRevealGeneration);
Assert.Equal(0x2021FFFFu, controller.DestinationLandblockId);
Assert.Equal(0, controller.DestinationRadius);
controller.EndDestinationReservation(2);
Assert.Equal(0, controller.ActiveRevealGeneration);
}
[Fact]
public void DeferredCompaction_ApplyFailureRetainsExactResultWithoutReplayingCommittedPrefix()
{
@ -199,8 +223,8 @@ public class StreamingControllerPriorityApplyTests
farRadius: 12)
{
MaxCompletionsPerFrame = 3,
PriorityLandblockId = priority,
};
ctrl.BeginDestinationReservation(1, priority, 0);
Assert.Throws<InvalidOperationException>(() => ctrl.Tick(169, 180));
Assert.Equal([first], applied);
@ -215,7 +239,6 @@ public class StreamingControllerPriorityApplyTests
[Fact]
public void ForceReloadWindow_DiscardsBufferedCompletionsFromOldWindow()
{
uint priority = StreamingRegion.EncodeLandblockIdForTest(169, 180);
var outbox = new Queue<LandblockStreamResult>(
Enumerable.Range(0, 6)
.Select(i => (LandblockStreamResult)LoadedOf(
@ -243,8 +266,7 @@ public class StreamingControllerPriorityApplyTests
MaxGpuUploadBytes: 1_000_000,
MaxGlRetireOperations: 1_000,
DestinationReserveFraction: 0.75f))
{ MaxCompletionsPerFrame = 4, PriorityLandblockId = priority };
{ MaxCompletionsPerFrame = 4 };
ctrl.Tick(169, 180);
Assert.Equal(4, applied.Count);
applied.Clear();
@ -452,7 +474,8 @@ public class StreamingControllerPriorityApplyTests
state: state,
nearRadius: 0,
farRadius: 0,
onLandblockLoaded: loadedCallbacks.Add);
onLandblockLoaded: loadedCallbacks.Add,
workBudgetOptions: GenerousBudget());
ctrl.Tick(10, 10);