perf(streaming): quiesce retired generations and budget teardown

Publish the retail blocking-for-cells edge before deferred recenter work, freeze old-world presentation/simulation/audio, and advance full-window retirement from exact metered entity and owner cursors. This removes synchronous portal teardown without allowing retained owners to remain observable.
This commit is contained in:
Erik 2026-07-24 18:29:52 +02:00
parent b8f6317fe1
commit bb16f74fd4
38 changed files with 1691 additions and 170 deletions

View file

@ -384,7 +384,8 @@ internal sealed class FrameRootCompositionPhase
retailPViewCells,
worldScenePasses,
d.RenderRange,
worldSceneDiagnostics);
worldSceneDiagnostics,
live.WorldAvailability);
Fault(FrameRootCompositionPoint.WorldRendererCreated);
bindings = new FrameRootRuntimeBindings();
@ -469,7 +470,8 @@ internal sealed class FrameRootCompositionPhase
live.WorldState,
session.LiveSession,
session.LocalPlayerFrame,
session.LiveSpatialReconciler);
session.LiveSpatialReconciler,
live.WorldAvailability);
var cameraFrame = new CameraFrameController(
host.CameraController,
d.InputCapture,
@ -496,7 +498,8 @@ internal sealed class FrameRootCompositionPhase
new StopwatchClientMonotonicTimeSource()),
session.LocalTeleport,
new PlayerModeAutoEntryFramePhase(session.PlayerModeAutoEntry),
cameraFrame);
cameraFrame,
live.WorldAvailability);
Fault(FrameRootCompositionPoint.UpdateRootCreated);
var bindingsLease = scope.Own(

View file

@ -78,6 +78,7 @@ internal sealed record LivePresentationResult(
EntitySpawnAdapter EntitySpawnAdapter,
EntityScriptActivator EntityScriptActivator,
RetailStaticAnimatingObjectScheduler StaticAnimationScheduler,
WorldGenerationAvailabilityState WorldAvailability,
GpuWorldState WorldState,
LiveEntityRuntime LiveEntities,
ProjectileController ProjectileController,
@ -319,10 +320,12 @@ internal sealed class LivePresentationCompositionPhase
staticAnimationScheduler.Unregister,
(entity, info) => staticAnimationScheduler.Rebind(entity, info));
var worldAvailability = new WorldGenerationAvailabilityState();
var worldState = new GpuWorldState(
wbSpawnAdapter,
d.ClassificationCache.InvalidateLandblock,
entityScriptActivator);
entityScriptActivator,
worldAvailability);
bindings = new LivePresentationRuntimeBindings();
if (d.DevWorldEntities is { } devWorldEntities)
{
@ -524,6 +527,7 @@ internal sealed class LivePresentationCompositionPhase
entitySpawnAdapter,
entityScriptActivator,
staticAnimationScheduler,
worldAvailability,
worldState,
liveEntities,
projectileController,
@ -568,6 +572,7 @@ internal sealed class LivePresentationCompositionPhase
EntitySpawnAdapter entitySpawnAdapter,
EntityScriptActivator entityScriptActivator,
RetailStaticAnimatingObjectScheduler staticAnimationScheduler,
WorldGenerationAvailabilityState worldAvailability,
GpuWorldState worldState,
LiveEntityRuntime liveEntities,
ProjectileController projectileController,
@ -942,6 +947,7 @@ internal sealed class LivePresentationCompositionPhase
entitySpawnAdapter,
entityScriptActivator,
staticAnimationScheduler,
worldAvailability,
worldState,
liveEntities,
projectileController,

View file

@ -321,6 +321,11 @@ internal sealed class SessionPlayerCompositionPhase
var spawnClaimClassifier = new DatSpawnClaimHydrationClassifier(
content.Dats,
d.DatLock);
var worldQuiescence = new WorldGenerationQuiescence(
live.WorldAvailability,
d.Selection,
live.WorldState,
content.Audio?.Engine);
var worldReveal = new WorldRevealCoordinator(
streaming.IsRenderNeighborhoodResident,
d.PhysicsEngine.IsSpawnCellReady,
@ -333,7 +338,8 @@ internal sealed class SessionPlayerCompositionPhase
radius),
live.DrawDispatcher.InvalidateCompositeWarmupReadiness,
spawnClaimClassifier.IsUnhydratable,
d.Log);
d.Log,
worldQuiescence);
Fault(SessionPlayerCompositionPoint.WorldRevealCreated);
return CompleteSessionPlayer(