fix(rendering): bound portal resource lifetime
Separate logical ownership, render publication, and GPU retirement across live entities, landblocks, particles, textures, mesh arenas, portal/UI teardown, and per-frame scratch storage. Add bounded DAT/texture caches, upload budgets, three-frame fence retirement, exact-incarnation appearance reconciliation, frame pacing, and extensive lifetime conformance coverage.\n\nThe seven-destination connected route now cuts peak working/private memory roughly in half, returns Caul to 125-153 FPS locally, and produces no WER or AMD reset.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
3971997689
commit
749e8ceeb1
225 changed files with 29107 additions and 3914 deletions
|
|
@ -727,6 +727,7 @@ public sealed class EntityEffectControllerTests
|
|||
WorldEntity entity = fixture.ReadyLive();
|
||||
fixture.Controller.HandleDirect(new PlayPhysicsScript(Guid, DirectDid));
|
||||
entity.SetPosition(new Vector3(10, 20, 30));
|
||||
fixture.Controller.MarkLiveOwnerPoseDirty(Guid);
|
||||
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
fixture.Runner.Tick(1.0);
|
||||
|
|
@ -734,6 +735,84 @@ public sealed class EntityEffectControllerTests
|
|||
Assert.Equal(new Vector3(10, 20, 30), Assert.Single(fixture.Sink.Calls).Position);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PoseRefreshWorkset_VisitsOnlyDirtyOwnerAcrossDenseReadySet()
|
||||
{
|
||||
const int ownerCount = 2_000;
|
||||
var fixture = new Fixture();
|
||||
WorldEntity? changedEntity = null;
|
||||
uint changedGuid = 0;
|
||||
for (int i = 0; i < ownerCount; i++)
|
||||
{
|
||||
uint guid = 0x71000000u + (uint)i;
|
||||
WorldEntity entity = fixture.ReadyLive(guid);
|
||||
if (i == 777)
|
||||
{
|
||||
changedGuid = guid;
|
||||
changedEntity = entity;
|
||||
}
|
||||
}
|
||||
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
Assert.Equal(0, fixture.Controller.LastPoseRefreshOwnerVisitCount);
|
||||
|
||||
changedEntity!.SetPosition(new Vector3(7, 8, 9));
|
||||
fixture.Controller.MarkLiveOwnerPoseDirty(changedGuid);
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
Assert.Equal(1, fixture.Controller.LastPoseRefreshOwnerVisitCount);
|
||||
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
Assert.Equal(0, fixture.Controller.LastPoseRefreshOwnerVisitCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PoseRefreshWorkset_RetainsCallbackMutationForNextPass()
|
||||
{
|
||||
const uint firstGuid = 0x72000001u;
|
||||
const uint secondGuid = 0x72000002u;
|
||||
var fixture = new Fixture();
|
||||
WorldEntity first = fixture.ReadyLive(firstGuid);
|
||||
WorldEntity second = fixture.ReadyLive(secondGuid);
|
||||
fixture.Poses.Publish(first, Array.Empty<Matrix4x4>());
|
||||
fixture.Poses.Publish(second, Array.Empty<Matrix4x4>());
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
first.SetPosition(new Vector3(10, 0, 0));
|
||||
|
||||
bool callbackRan = false;
|
||||
fixture.Poses.EffectPoseChanged += localId =>
|
||||
{
|
||||
if (localId != first.Id || callbackRan)
|
||||
return;
|
||||
callbackRan = true;
|
||||
fixture.Controller.MarkLiveOwnerPoseDirty(secondGuid);
|
||||
};
|
||||
fixture.Controller.MarkLiveOwnerPoseDirty(firstGuid);
|
||||
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
Assert.Equal(1, fixture.Controller.LastPoseRefreshOwnerVisitCount);
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
Assert.Equal(1, fixture.Controller.LastPoseRefreshOwnerVisitCount);
|
||||
Assert.True(callbackRan);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PoseRefreshWorkset_RejectsDeletedIncarnationAfterGuidReuse()
|
||||
{
|
||||
var fixture = new Fixture();
|
||||
fixture.ReadyLive(Guid, generation: 1);
|
||||
fixture.Controller.MarkLiveOwnerPoseDirty(Guid);
|
||||
Assert.True(fixture.Runtime.UnregisterLiveEntity(
|
||||
new DeleteObject.Parsed(Guid, 1),
|
||||
isLocalPlayer: false));
|
||||
|
||||
WorldEntity replacement = fixture.ReadyLive(Guid, generation: 2);
|
||||
replacement.SetPosition(new Vector3(20, 30, 40));
|
||||
fixture.Controller.MarkLiveOwnerPoseDirty(Guid);
|
||||
fixture.Controller.RefreshLiveOwnerPoses();
|
||||
|
||||
Assert.Equal(1, fixture.Controller.LastPoseRefreshOwnerVisitCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClearNetworkStatePreservesDatStaticProfiles()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -154,6 +154,31 @@ public sealed class EntityEffectPoseRegistryTests
|
|||
Assert.Equal(0xA9B4000Bu, cellId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChangeNotifications_SuppressEquivalentStaticPublishes()
|
||||
{
|
||||
var poses = new EntityEffectPoseRegistry();
|
||||
WorldEntity entity = Entity(13u, new Vector3(1, 2, 3));
|
||||
var changed = new List<uint>();
|
||||
poses.EffectPoseChanged += changed.Add;
|
||||
Matrix4x4 part = Matrix4x4.CreateTranslation(0, 0, 1);
|
||||
|
||||
poses.Publish(entity, new[] { part });
|
||||
poses.Publish(entity, new[] { part });
|
||||
Assert.True(poses.UpdateRoot(entity));
|
||||
Assert.Equal(new[] { 13u }, changed);
|
||||
|
||||
entity.SetPosition(new Vector3(4, 5, 6));
|
||||
Assert.True(poses.UpdateRoot(entity));
|
||||
Assert.Equal(new[] { 13u, 13u }, changed);
|
||||
|
||||
poses.Publish(entity, new[] { Matrix4x4.CreateTranslation(0, 0, 2) });
|
||||
Assert.Equal(new[] { 13u, 13u, 13u }, changed);
|
||||
|
||||
Assert.True(poses.Remove(entity.Id));
|
||||
Assert.Equal(new[] { 13u, 13u, 13u, 13u }, changed);
|
||||
}
|
||||
|
||||
private static WorldEntity Entity(uint id, Vector3 position) => new()
|
||||
{
|
||||
Id = id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue