fix(streaming): preserve portal destination ownership

Detach old-world spatial ownership atomically, prioritize destination retirement dependencies, and reveal the viewport at the retail transition edge. Give private paperdoll views independent mesh ownership and retain dormant ACE entities so portal revisits preserve server objects without extending active GPU lifetimes.
This commit is contained in:
Erik 2026-07-25 08:35:12 +02:00
parent 2c848d4167
commit 823936ec31
57 changed files with 2551 additions and 324 deletions

View file

@ -11,6 +11,17 @@ namespace AcDream.App.Tests.Streaming;
public sealed class StreamingWorkBudgetTests
{
[Fact]
public void DefaultProfile_UsesElapsedTimeAsTheMicroOperationGuard()
{
Assert.Equal(
4_096,
StreamingWorkBudgetOptions.Default.MaxEntityOperations);
Assert.Equal(
2.0,
StreamingWorkBudgetOptions.Default.MaxUpdateMilliseconds);
}
private static StreamingWorkBudget Budget(
double milliseconds = 2,
int completions = 4,
@ -563,15 +574,17 @@ public sealed class StreamingWorkBudgetTests
Assert.Equal([center], applied);
Assert.Equal(1, controller.WorkDiagnostics.DeferredCompletions);
Assert.Equal(2, controller.WorkDiagnostics.LastFrame.YieldCount);
Assert.Equal(1, 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([center], applied);
Assert.Equal(1, controller.WorkDiagnostics.DeferredCompletions);
Assert.Equal(0, controller.WorkDiagnostics.LastFrame.Used.GlRetireOperations);
controller.EndDestinationReservation(1);
for (int i = 0;
i < 4
&& (controller.WorkDiagnostics.DeferredCompletions != 0
@ -586,13 +599,51 @@ public sealed class StreamingWorkBudgetTests
}
[Fact]
public void StaleGenerationResultsConsumeAdmissionButRetainNoPayload()
public void IncompleteReveal_DoesNotStarveOrdinaryWorkBeforeDestinationArrives()
{
uint center = StreamingRegion.EncodeLandblockIdForTest(32, 32);
var source = new QueueCompletionSource(
Loaded(center, generation: 1),
Loaded(StreamingRegion.EncodeLandblockIdForTest(32, 33), generation: 1),
Loaded(center));
uint ordinary = StreamingRegion.EncodeLandblockIdForTest(33, 33);
var source = new QueueCompletionSource(Loaded(ordinary));
var applied = new List<uint>();
StreamingController controller = Controller(
source,
id => applied.Add(id),
WorkOptions(admissions: 4, cpuBytes: 1_000));
controller.BeginDestinationReservation(1, center, 0);
controller.Tick(32, 32);
Assert.Equal([ordinary], applied);
Assert.Equal(0, controller.WorkDiagnostics.NearBacklog);
source.Enqueue(Loaded(center));
controller.Tick(32, 32);
Assert.Equal([ordinary, center], applied);
Assert.Equal(0, controller.WorkDiagnostics.NearBacklog);
controller.EndDestinationReservation(1);
controller.Tick(32, 32);
Assert.Equal([ordinary, center], applied);
Assert.Equal(0, controller.WorkDiagnostics.DeferredCompletions);
}
[Fact]
public void StaleGenerationResultsDrainWithoutStarvingCurrentGeneration()
{
uint center = StreamingRegion.EncodeLandblockIdForTest(32, 32);
LandblockStreamResult[] results =
[
.. Enumerable.Range(0, 625)
.Select(index => Loaded(
StreamingRegion.EncodeLandblockIdForTest(
32 + index % 25,
32 + index / 25),
generation: 1)),
Loaded(center),
];
var source = new QueueCompletionSource(results);
int applied = 0;
StreamingController controller = Controller(
source,
@ -601,15 +652,12 @@ public sealed class StreamingWorkBudgetTests
controller.Tick(32, 32);
Assert.Equal(0, applied);
Assert.Equal(1, source.BacklogCount);
Assert.Equal(1, applied);
Assert.Equal(0, source.BacklogCount);
Assert.Equal(0, controller.WorkDiagnostics.DeferredCompletions);
Assert.Equal(0, controller.WorkDiagnostics.DeferredAdoptedCpuBytes);
Assert.Equal(2, controller.WorkDiagnostics.LastFrame.Used.CompletionAdmissions);
Assert.Equal(0, controller.WorkDiagnostics.LastFrame.Used.AdoptedCpuBytes);
controller.Tick(32, 32);
Assert.Equal(1, applied);
Assert.Equal(1, controller.WorkDiagnostics.LastFrame.Used.CompletionAdmissions);
Assert.Equal(44, controller.WorkDiagnostics.LastFrame.Used.AdoptedCpuBytes);
}
private static StreamingController Controller(
@ -688,6 +736,9 @@ public sealed class StreamingWorkBudgetTests
public int BacklogCount => _results.Count;
public void Enqueue(LandblockStreamResult result) =>
_results.Enqueue(result);
public bool TryPeek(out LandblockStreamResult? result)
{
if (_results.TryPeek(out LandblockStreamResult? peeked))