perf(diag): complete trustworthy Slice A capture tooling
Correct whole-frame GPU timestamps so they bracket only the accepted render transaction and associate delayed query results with the owning CPU frame. Add route-wide frame-history summaries, fixed-camera screenshot comparison, process counters, contention traces, a pinned Arwic workload, and credential-safe launch disclosure. The reference hardware/display contract now keeps local and RDP populations separate and defines the screenshot and re-baseline rules needed by later prepared-content gates. Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
parent
bf7ec12f68
commit
3ee8ec537a
23 changed files with 1639 additions and 170 deletions
|
|
@ -182,8 +182,10 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
"screenshotCaptured);");
|
||||
AssertAppearsInOrder(
|
||||
orchestrator,
|
||||
"WorldRenderFrameOutcome world = _world.Render(input);",
|
||||
"_gpuMeasurement.BeginFrame();",
|
||||
"world = _world.Render(input);",
|
||||
"_presentation.Render(input, world);",
|
||||
"_gpuMeasurement.EndFrame();",
|
||||
"new RenderFrameOutcome(world, presentation);",
|
||||
"_diagnostics.Publish(input, outcome);");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ public sealed class RenderFrameOrchestratorTests
|
|||
|
||||
Assert.Equal(
|
||||
[
|
||||
"gpu-begin", "resources", "world", "presentation",
|
||||
"gpu-begin", "measure-begin", "resources", "world", "presentation",
|
||||
"measure-end",
|
||||
"diagnostics", "post-diagnostics", "gpu-end",
|
||||
],
|
||||
calls);
|
||||
|
|
@ -118,7 +119,8 @@ public sealed class RenderFrameOrchestratorTests
|
|||
Assert.Same(expected, actual);
|
||||
Assert.Equal(
|
||||
[
|
||||
"gpu-begin", "resources", "world", "presentation",
|
||||
"gpu-begin", "measure-begin", "resources", "world", "presentation",
|
||||
"measure-end",
|
||||
"diagnostics", "post-diagnostics", "gpu-end",
|
||||
],
|
||||
calls);
|
||||
|
|
@ -177,7 +179,10 @@ public sealed class RenderFrameOrchestratorTests
|
|||
Assert.Same(renderFailure, actual.InnerExceptions[0]);
|
||||
Assert.Same(recoveryFailure, actual.InnerExceptions[1]);
|
||||
Assert.Equal(
|
||||
["gpu-begin", "resources", "world", "recovery-abort", "gpu-end"],
|
||||
[
|
||||
"gpu-begin", "measure-begin", "resources", "world",
|
||||
"measure-end", "recovery-abort", "gpu-end",
|
||||
],
|
||||
calls);
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +210,8 @@ public sealed class RenderFrameOrchestratorTests
|
|||
Assert.Same(closeFailure, actual.InnerExceptions[2]);
|
||||
Assert.Equal(
|
||||
[
|
||||
"gpu-begin", "resources", "world", "presentation",
|
||||
"gpu-begin", "measure-begin", "resources", "world", "presentation",
|
||||
"measure-end",
|
||||
"recovery-abort", "gpu-end",
|
||||
],
|
||||
calls);
|
||||
|
|
@ -217,19 +223,21 @@ public sealed class RenderFrameOrchestratorTests
|
|||
var phases = new RecordingPhases([]);
|
||||
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
null!, phases, phases, phases, phases, phases, phases));
|
||||
null!, phases, phases, phases, phases, phases, phases, phases));
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
phases, null!, phases, phases, phases, phases, phases));
|
||||
phases, null!, phases, phases, phases, phases, phases, phases));
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
phases, phases, null!, phases, phases, phases, phases));
|
||||
phases, phases, null!, phases, phases, phases, phases, phases));
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
phases, phases, phases, null!, phases, phases, phases));
|
||||
phases, phases, phases, null!, phases, phases, phases, phases));
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
phases, phases, phases, phases, null!, phases, phases));
|
||||
phases, phases, phases, phases, null!, phases, phases, phases));
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
phases, phases, phases, phases, phases, null!, phases));
|
||||
phases, phases, phases, phases, phases, null!, phases, phases));
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
phases, phases, phases, phases, phases, phases, null!));
|
||||
phases, phases, phases, phases, phases, phases, null!, phases));
|
||||
Assert.Throws<ArgumentNullException>(() => new RenderFrameOrchestrator(
|
||||
phases, phases, phases, phases, phases, phases, phases, null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -238,6 +246,7 @@ public sealed class RenderFrameOrchestratorTests
|
|||
Type[] expectedFieldTypes =
|
||||
[
|
||||
typeof(IRenderFrameLifetime),
|
||||
typeof(IRenderFrameGpuMeasurement),
|
||||
typeof(IRenderFrameResourcePhase),
|
||||
typeof(IWorldSceneFramePhase),
|
||||
typeof(IPrivatePresentationFramePhase),
|
||||
|
|
@ -308,22 +317,33 @@ public sealed class RenderFrameOrchestratorTests
|
|||
|
||||
private static string[] ExpectedFailureCalls(string failurePoint) => failurePoint switch
|
||||
{
|
||||
"resources" => ["gpu-begin", "resources", "recovery-abort", "gpu-end"],
|
||||
"world" => ["gpu-begin", "resources", "world", "recovery-abort", "gpu-end"],
|
||||
"resources" =>
|
||||
[
|
||||
"gpu-begin", "measure-begin", "resources", "measure-end",
|
||||
"recovery-abort", "gpu-end",
|
||||
],
|
||||
"world" =>
|
||||
[
|
||||
"gpu-begin", "measure-begin", "resources", "world", "measure-end",
|
||||
"recovery-abort", "gpu-end",
|
||||
],
|
||||
"presentation" =>
|
||||
[
|
||||
"gpu-begin", "resources", "world", "presentation",
|
||||
"gpu-begin", "measure-begin", "resources", "world", "presentation",
|
||||
"measure-end",
|
||||
"recovery-abort", "gpu-end",
|
||||
],
|
||||
"diagnostics" =>
|
||||
[
|
||||
"gpu-begin", "resources", "world", "presentation", "diagnostics",
|
||||
"gpu-begin", "measure-begin", "resources", "world", "presentation",
|
||||
"measure-end", "diagnostics",
|
||||
"recovery-abort", "gpu-end",
|
||||
],
|
||||
"post-diagnostics" =>
|
||||
[
|
||||
"gpu-begin", "resources", "world", "presentation", "diagnostics",
|
||||
"post-diagnostics", "recovery-abort", "gpu-end",
|
||||
"gpu-begin", "measure-begin", "resources", "world", "presentation",
|
||||
"measure-end", "diagnostics", "post-diagnostics",
|
||||
"recovery-abort", "gpu-end",
|
||||
],
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(failurePoint)),
|
||||
};
|
||||
|
|
@ -348,10 +368,11 @@ public sealed class RenderFrameOrchestratorTests
|
|||
}
|
||||
|
||||
private static RenderFrameOrchestrator Create(RecordingPhases phases) =>
|
||||
new(phases, phases, phases, phases, phases, phases, phases);
|
||||
new(phases, phases, phases, phases, phases, phases, phases, phases);
|
||||
|
||||
private sealed class RecordingPhases :
|
||||
IRenderFrameLifetime,
|
||||
IRenderFrameGpuMeasurement,
|
||||
IRenderFrameResourcePhase,
|
||||
IWorldSceneFramePhase,
|
||||
IPrivatePresentationFramePhase,
|
||||
|
|
@ -376,15 +397,19 @@ public sealed class RenderFrameOrchestratorTests
|
|||
public WorldRenderFrameOutcome ObservedWorld { get; private set; }
|
||||
public RenderFrameOutcome ObservedOutcome { get; private set; }
|
||||
|
||||
public void BeginFrame() => Record("gpu-begin");
|
||||
void IRenderFrameLifetime.BeginFrame() => Record("gpu-begin");
|
||||
|
||||
public void EndFrame()
|
||||
void IRenderFrameLifetime.EndFrame()
|
||||
{
|
||||
_calls.Add("gpu-end");
|
||||
if (CloseFailure is not null)
|
||||
throw CloseFailure;
|
||||
}
|
||||
|
||||
void IRenderFrameGpuMeasurement.BeginFrame() => Record("measure-begin");
|
||||
|
||||
void IRenderFrameGpuMeasurement.EndFrame() => _calls.Add("measure-end");
|
||||
|
||||
public void AbortFrame()
|
||||
{
|
||||
_calls.Add("recovery-abort");
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public sealed class RenderFrameRecoveryIntegrationTests
|
|||
new Screenshots());
|
||||
var orchestrator = new RenderFrameOrchestrator(
|
||||
gpu,
|
||||
new GpuMeasurement(),
|
||||
preparation,
|
||||
new World(failure),
|
||||
presentation,
|
||||
|
|
@ -87,6 +88,17 @@ public sealed class RenderFrameRecoveryIntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
private sealed class GpuMeasurement : IRenderFrameGpuMeasurement
|
||||
{
|
||||
public void BeginFrame()
|
||||
{
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class DevTools(FailureSwitch failure) : IDevToolsFrameLifecycle
|
||||
{
|
||||
public bool IsOpen { get; private set; }
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ public sealed class RenderFrameResourceControllerTests
|
|||
"_uiText?.BeginFrame(gpuSlot);",
|
||||
"_clip?.BeginFrame(gpuSlot);",
|
||||
"_terrain?.BeginFrame(gpuSlot);",
|
||||
"_lighting?.BeginFrame(gpuSlot);",
|
||||
"_profiler.FrameBoundary(_gl);");
|
||||
"_lighting?.BeginFrame(gpuSlot);");
|
||||
Assert.DoesNotContain("_profiler.FrameBoundary(", source);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue