test(runtime): add deterministic world gate artifacts

This commit is contained in:
Erik 2026-07-20 22:37:16 +02:00
parent db45b81f75
commit 354c2adc2e
11 changed files with 703 additions and 10 deletions

View file

@ -134,6 +134,8 @@ public sealed class GameWindow : IDisposable
// per OnRender + three stage scopes. All logic lives in
// AcDream.App.Diagnostics.FrameProfiler (structure rule 1).
private readonly AcDream.App.Diagnostics.FrameProfiler _frameProfiler = new();
private AcDream.App.Diagnostics.FrameScreenshotController? _frameScreenshots;
private AcDream.App.Diagnostics.WorldLifecycleAutomationController? _worldLifecycleAutomation;
private AcDream.App.Rendering.GpuFrameFlightController? _gpuFrameFlights;
private ResourceShutdownTransaction? _shutdown;
private readonly FramePacingController _framePacing = new();
@ -2275,6 +2277,24 @@ public sealed class GameWindow : IDisposable
ScreenSize: () => (_window.Size.X, _window.Size.Y));
void UiProbeLog(string message) => Console.WriteLine("[UI-PROBE] " + message);
if (_options.UiProbeEnabled
&& _options.AutomationArtifactDirectory is { } artifactDirectory)
{
_frameScreenshots = new AcDream.App.Diagnostics.FrameScreenshotController(
_gl!,
() => (_window!.Size.X, _window.Size.Y),
System.IO.Path.Combine(artifactDirectory, "screenshots"),
UiProbeLog);
_worldLifecycleAutomation =
new AcDream.App.Diagnostics.WorldLifecycleAutomationController(
() => _worldRevealTelemetry.Snapshot,
() => _worldRevealTelemetry.PortalMaterializationCount,
CaptureWorldLifecycleResourceSnapshot,
_frameScreenshots,
artifactDirectory,
UiProbeLog);
}
_retailUiRuntime = AcDream.App.UI.RetailUiRuntime.Mount(
new AcDream.App.UI.RetailUiRuntimeBindings(
Host: _uiHost,
@ -2426,7 +2446,8 @@ public sealed class GameWindow : IDisposable
UiProbeLog,
action => _inputDispatcher?.TryInvokeAutomationAction(action) == true,
(action, held) =>
_inputDispatcher?.TrySetAutomationActionHeld(action, held) == true)));
_inputDispatcher?.TrySetAutomationActionHeld(action, held) == true,
_worldLifecycleAutomation)));
}
@ -11226,6 +11247,11 @@ public sealed class GameWindow : IDisposable
}
}
// Explicit diagnostic captures are requested by the retained-UI
// automation tick above and executed only after every presentation
// layer has drawn into the back buffer on this render thread.
_frameScreenshots?.CapturePending();
// Update the window title with performance stats every ~0.5s.
_perfAccum += deltaSeconds;
_perfFrameCount++;
@ -11235,6 +11261,8 @@ public sealed class GameWindow : IDisposable
double fps = _perfFrameCount / _perfAccum;
int entityCount = _worldState.Entities.Count;
int animatedCount = _animatedEntities.Count;
_lastVisibleLandblocks = visibleLandblocks;
_lastTotalLandblocks = totalLandblocks;
// Keep the developer diagnostic title independent from retail's
// /framerate switch. That command owns the in-world SmartBox readout;
@ -11346,6 +11374,50 @@ public sealed class GameWindow : IDisposable
}
}
private AcDream.App.Diagnostics.WorldLifecycleResourceSnapshot
CaptureWorldLifecycleResourceSnapshot()
{
var meshManager = _wbMeshAdapter?.MeshManager;
var mesh = meshManager?.Diagnostics ?? default;
GCMemoryInfo memory = GC.GetGCMemoryInfo();
return new AcDream.App.Diagnostics.WorldLifecycleResourceSnapshot(
LoadedLandblocks: _worldState.LoadedLandblockIds.Count,
WorldEntities: _worldState.Entities.Count,
AnimatedEntities: _animatedEntities.Count,
VisibleLandblocks: _lastVisibleLandblocks,
TotalLandblocks: _lastTotalLandblocks,
LiveEntities: _liveEntities?.Count ?? 0,
MaterializedLiveEntities: _liveEntities?.MaterializedCount ?? 0,
PendingLiveTeardowns: _liveEntities?.PendingTeardownCount ?? 0,
PendingLandblockRetirements: _landblockRetirements?.PendingCount ?? 0,
ParticleEmitters: _particleSystem?.ActiveEmitterCount ?? 0,
Particles: _particleSystem?.ActiveParticleCount ?? 0,
ParticleBindings: _particleSink?.ActiveBindingCount ?? 0,
ParticleOwners: _particleSink?.TrackedOwnerCount ?? 0,
EffectOwners: _entityEffects?.ReadyOwnerCount ?? 0,
LightOwners: _liveEntityLights?.TrackedOwnerCount ?? 0,
ScriptOwners: _scriptRunner?.ActiveOwnerCount ?? 0,
ActiveScripts: _scriptRunner?.ActiveScriptCount ?? 0,
MeshRenderData: mesh.RenderData,
MeshAtlasArrays: mesh.AtlasArrays,
MeshEstimatedBytes: mesh.EstimatedBytes,
StagedMeshUploads: _wbMeshAdapter?.StagedUploadBacklog ?? 0,
StagedMeshBytes: _wbMeshAdapter?.StagedUploadBytes ?? 0,
TrackedGpuBytes: AcDream.App.Rendering.Wb.GpuMemoryTracker.AllocatedBytes,
TrackedGpuBuffers: AcDream.App.Rendering.Wb.GpuMemoryTracker.BufferCount,
TrackedGpuTextures: AcDream.App.Rendering.Wb.GpuMemoryTracker.TextureCount,
OwnedCompositeTextures: _textureCache?.OwnedBindlessTextureCount ?? 0,
CompositeTextureOwners: _textureCache?.TextureOwnerCount ?? 0,
ActiveParticleTextures: _textureCache?.ActiveParticleTextureCount ?? 0,
ParticleTextureOwners: _textureCache?.ParticleTextureOwnerCount ?? 0,
CompositeWarmupPending: _wbDrawDispatcher?.LastCompositeWarmupPendingCount ?? 0,
ManagedBytes: GC.GetTotalMemory(forceFullCollection: false),
ManagedCommittedBytes: memory.TotalCommittedBytes,
Fps: _lastFps,
FrameMilliseconds: _lastFrameMs,
LastFrameProfile: _frameProfiler.LastReport);
}
private bool RunRemoteTeleportHook(
uint serverGuid,
uint localEntityId,