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
32
src/AcDream.App/Rendering/FrameProfilerGpuMeasurement.cs
Normal file
32
src/AcDream.App/Rendering/FrameProfilerGpuMeasurement.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using AcDream.App.Diagnostics;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Production render-transaction measurement adapter. CPU frame boundaries
|
||||
/// remain owned by <see cref="FrameProfiler"/> while this adapter places the
|
||||
/// GPU query around only the GL-producing render phases.
|
||||
/// </summary>
|
||||
internal sealed class FrameProfilerGpuMeasurement : IRenderFrameGpuMeasurement
|
||||
{
|
||||
private readonly FrameProfiler _profiler;
|
||||
private readonly GL _gl;
|
||||
|
||||
public FrameProfilerGpuMeasurement(FrameProfiler profiler, GL gl)
|
||||
{
|
||||
_profiler = profiler ?? throw new ArgumentNullException(nameof(profiler));
|
||||
_gl = gl ?? throw new ArgumentNullException(nameof(gl));
|
||||
}
|
||||
|
||||
public void BeginFrame()
|
||||
{
|
||||
_profiler.FrameBoundary(_gl);
|
||||
_profiler.BeginGpuFrame();
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
{
|
||||
_profiler.EndGpuFrame();
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,18 @@ internal interface IRenderFrameResourcePhase
|
|||
void Prepare(RenderFrameInput input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Diagnostic GPU timer bracketing only render-resource, world, and private
|
||||
/// presentation submission. It deliberately excludes diagnostics, pacing,
|
||||
/// and the idle interval before the next render callback.
|
||||
/// </summary>
|
||||
internal interface IRenderFrameGpuMeasurement
|
||||
{
|
||||
void BeginFrame();
|
||||
|
||||
void EndFrame();
|
||||
}
|
||||
|
||||
internal interface IWorldSceneFramePhase
|
||||
{
|
||||
WorldRenderFrameOutcome Render(RenderFrameInput input);
|
||||
|
|
@ -117,6 +129,7 @@ internal sealed class NullRenderFrameFailureRecovery : IRenderFrameFailureRecove
|
|||
internal sealed class RenderFrameOrchestrator : IGameRenderFrameRoot
|
||||
{
|
||||
private readonly IRenderFrameLifetime _lifetime;
|
||||
private readonly IRenderFrameGpuMeasurement _gpuMeasurement;
|
||||
private readonly IRenderFrameResourcePhase _resources;
|
||||
private readonly IWorldSceneFramePhase _world;
|
||||
private readonly IPrivatePresentationFramePhase _presentation;
|
||||
|
|
@ -126,6 +139,7 @@ internal sealed class RenderFrameOrchestrator : IGameRenderFrameRoot
|
|||
|
||||
public RenderFrameOrchestrator(
|
||||
IRenderFrameLifetime lifetime,
|
||||
IRenderFrameGpuMeasurement gpuMeasurement,
|
||||
IRenderFrameResourcePhase resources,
|
||||
IWorldSceneFramePhase world,
|
||||
IPrivatePresentationFramePhase presentation,
|
||||
|
|
@ -134,6 +148,8 @@ internal sealed class RenderFrameOrchestrator : IGameRenderFrameRoot
|
|||
IRenderFrameFailureRecovery recovery)
|
||||
{
|
||||
_lifetime = lifetime ?? throw new ArgumentNullException(nameof(lifetime));
|
||||
_gpuMeasurement = gpuMeasurement
|
||||
?? throw new ArgumentNullException(nameof(gpuMeasurement));
|
||||
_resources = resources ?? throw new ArgumentNullException(nameof(resources));
|
||||
_world = world ?? throw new ArgumentNullException(nameof(world));
|
||||
_presentation = presentation ?? throw new ArgumentNullException(nameof(presentation));
|
||||
|
|
@ -149,10 +165,37 @@ internal sealed class RenderFrameOrchestrator : IGameRenderFrameRoot
|
|||
Exception? renderFailure = null;
|
||||
try
|
||||
{
|
||||
_resources.Prepare(input);
|
||||
WorldRenderFrameOutcome world = _world.Render(input);
|
||||
PrivatePresentationFrameOutcome presentation =
|
||||
_presentation.Render(input, world);
|
||||
WorldRenderFrameOutcome world;
|
||||
PrivatePresentationFrameOutcome presentation;
|
||||
Exception? measuredRenderFailure = null;
|
||||
_gpuMeasurement.BeginFrame();
|
||||
try
|
||||
{
|
||||
_resources.Prepare(input);
|
||||
world = _world.Render(input);
|
||||
presentation = _presentation.Render(input, world);
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
measuredRenderFailure = error;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
_gpuMeasurement.EndFrame();
|
||||
}
|
||||
catch (Exception measurementFailure)
|
||||
when (measuredRenderFailure is not null)
|
||||
{
|
||||
throw new AggregateException(
|
||||
"Rendering failed and its GPU measurement could not be closed.",
|
||||
measuredRenderFailure,
|
||||
measurementFailure);
|
||||
}
|
||||
}
|
||||
|
||||
var outcome = new RenderFrameOutcome(world, presentation);
|
||||
_diagnostics.Publish(input, outcome);
|
||||
_postDiagnostics.Process(input, outcome);
|
||||
|
|
|
|||
|
|
@ -93,9 +93,6 @@ internal sealed class RuntimeRenderFrameBeginResources : IRenderFrameBeginResour
|
|||
private readonly ClipFrame? _clip;
|
||||
private readonly TerrainModernRenderer? _terrain;
|
||||
private readonly SceneLightingUboBinding? _lighting;
|
||||
private readonly FrameProfiler _profiler;
|
||||
private readonly GL _gl;
|
||||
|
||||
public RuntimeRenderFrameBeginResources(
|
||||
TextureCache? textures,
|
||||
WbDrawDispatcher? dispatcher,
|
||||
|
|
@ -105,9 +102,7 @@ internal sealed class RuntimeRenderFrameBeginResources : IRenderFrameBeginResour
|
|||
TextRenderer? uiText,
|
||||
ClipFrame? clip,
|
||||
TerrainModernRenderer? terrain,
|
||||
SceneLightingUboBinding? lighting,
|
||||
FrameProfiler profiler,
|
||||
GL gl)
|
||||
SceneLightingUboBinding? lighting)
|
||||
{
|
||||
_textures = textures;
|
||||
_dispatcher = dispatcher;
|
||||
|
|
@ -118,8 +113,6 @@ internal sealed class RuntimeRenderFrameBeginResources : IRenderFrameBeginResour
|
|||
_clip = clip;
|
||||
_terrain = terrain;
|
||||
_lighting = lighting;
|
||||
_profiler = profiler ?? throw new ArgumentNullException(nameof(profiler));
|
||||
_gl = gl ?? throw new ArgumentNullException(nameof(gl));
|
||||
}
|
||||
|
||||
public void Begin(int gpuSlot)
|
||||
|
|
@ -134,7 +127,6 @@ internal sealed class RuntimeRenderFrameBeginResources : IRenderFrameBeginResour
|
|||
_clip?.BeginFrame(gpuSlot);
|
||||
_terrain?.BeginFrame(gpuSlot);
|
||||
_lighting?.BeginFrame(gpuSlot);
|
||||
_profiler.FrameBoundary(_gl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue