feat(pipeline): MP0 - wire FrameProfiler into GameWindow + DebugPanel toggle
GameWindow gets one field (_frameProfiler), one FrameBoundary() call at
the top of OnRender, three stage scopes (Update in OnUpdate, Upload
around _wbMeshAdapter?.Tick(), ImGui around _imguiBootstrap.Render()),
and one Dispose() call in teardown before _dats?.Dispose() releases the
GpuFrameTimer query ring. No new feature bodies land in GameWindow.cs —
all profiler logic lives in AcDream.App.Diagnostics.
DebugVM.FrameProf mirrors RenderingDiagnostics.FrameProfEnabled so the
DebugPanel checkbox ("Frame profiler ([frame-prof])") toggles the 5s
report live. Note: the checkbox lives in
AcDream.UI.Abstractions/Panels/Debug/DebugPanel.cs (IPanelRenderer,
backend-agnostic) alongside the other Diagnostics-section checkboxes —
not in AcDream.UI.ImGui, which holds no panel-drawing code per Code
Structure Rule 3.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
73bb8777a9
commit
edbb1ffebd
3 changed files with 35 additions and 2 deletions
|
|
@ -122,6 +122,11 @@ public sealed class GameWindow : IDisposable
|
|||
private readonly long[] _applyLockWaitSamples = new long[256];
|
||||
private int _applyLockWaitSampleCursor;
|
||||
|
||||
// MP0 (2026-07-05): permanent frame profiler — one FrameBoundary call
|
||||
// per OnRender + three stage scopes. All logic lives in
|
||||
// AcDream.App.Diagnostics.FrameProfiler (structure rule 1).
|
||||
private readonly AcDream.App.Diagnostics.FrameProfiler _frameProfiler = new();
|
||||
|
||||
// Phase A.1: streaming fields replacing the one-shot _entities list.
|
||||
private AcDream.App.Streaming.LandblockStreamer? _streamer;
|
||||
private AcDream.App.Streaming.GpuWorldState _worldState = new();
|
||||
|
|
@ -7951,6 +7956,8 @@ public sealed class GameWindow : IDisposable
|
|||
|
||||
private void OnUpdate(double dt)
|
||||
{
|
||||
using var _updStage = _frameProfiler.BeginStage(AcDream.App.Diagnostics.FrameStage.Update);
|
||||
|
||||
// [FRAME-DIAG]: applies run later this frame inside _streamingController.Tick;
|
||||
// flush the PREVIOUS OnUpdate's accumulated apply cost here (a clean per-frame
|
||||
// boundary, independent of where in OnUpdate the applies landed) and reset.
|
||||
|
|
@ -8755,6 +8762,8 @@ public sealed class GameWindow : IDisposable
|
|||
|
||||
private void OnRender(double deltaSeconds)
|
||||
{
|
||||
_frameProfiler.FrameBoundary(_gl!);
|
||||
|
||||
// Phase G.1: set the clear color from the current sky's fog
|
||||
// tint so the horizon band continues naturally past the
|
||||
// rendered geometry. Fog blends to this color at max distance
|
||||
|
|
@ -8810,7 +8819,10 @@ public sealed class GameWindow : IDisposable
|
|||
// [FRAME-DIAG]: this OnRender drain is where staged GfxObj/entity meshes hit
|
||||
// the GPU (uncapped) — the H2 entity-upload suspect, separate from the apply.
|
||||
long fdE0 = _frameDiag ? System.Diagnostics.Stopwatch.GetTimestamp() : 0L;
|
||||
_wbMeshAdapter?.Tick();
|
||||
using (var _uplStage = _frameProfiler.BeginStage(AcDream.App.Diagnostics.FrameStage.Upload))
|
||||
{
|
||||
_wbMeshAdapter?.Tick();
|
||||
}
|
||||
if (_frameDiag)
|
||||
FrameDiagPush(_entityUploadSamples, ref _entityUploadSampleCursor,
|
||||
System.Diagnostics.Stopwatch.GetTimestamp() - fdE0);
|
||||
|
|
@ -9818,7 +9830,10 @@ public sealed class GameWindow : IDisposable
|
|||
// panels but still over the 3D scene. Cheap when no
|
||||
// selection — internal early-return on null guid.
|
||||
_targetIndicator?.Render();
|
||||
_imguiBootstrap.Render();
|
||||
using (var _imguiStage = _frameProfiler.BeginStage(AcDream.App.Diagnostics.FrameStage.ImGui))
|
||||
{
|
||||
_imguiBootstrap.Render();
|
||||
}
|
||||
}
|
||||
|
||||
// Update the window title with performance stats every ~0.5s.
|
||||
|
|
@ -14005,6 +14020,7 @@ public sealed class GameWindow : IDisposable
|
|||
_uiHost?.Dispose();
|
||||
_textRenderer?.Dispose();
|
||||
_debugFont?.Dispose();
|
||||
_frameProfiler.Dispose(); // MP0: releases the GpuFrameTimer query ring
|
||||
_dats?.Dispose();
|
||||
_input?.Dispose();
|
||||
_gl?.Dispose();
|
||||
|
|
|
|||
|
|
@ -254,6 +254,12 @@ public sealed class DebugPanel : IPanel
|
|||
if (r.Checkbox("Probe auto-walk (ACDREAM_PROBE_AUTOWALK)",
|
||||
ref probeAutoWalk)) _vm.ProbeAutoWalk = probeAutoWalk;
|
||||
|
||||
// MP0 (2026-07-05): permanent frame profiler toggle — not a
|
||||
// throwaway investigation probe, so it lives with the other
|
||||
// always-available diagnostics rather than a dated section.
|
||||
bool frameProf = _vm.FrameProf;
|
||||
if (r.Checkbox("Frame profiler ([frame-prof])", ref frameProf)) _vm.FrameProf = frameProf;
|
||||
|
||||
// ── Indoor rendering diagnostics (2026-05-19) ───────────────
|
||||
// Pinpoint where the EnvCell rendering chain breaks for
|
||||
// hypothesis-driven Phase 2 fix. Spec:
|
||||
|
|
|
|||
|
|
@ -291,6 +291,17 @@ public sealed class DebugVM
|
|||
set => PhysicsDiagnostics.ProbeAutoWalkEnabled = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runtime mirror of <c>RenderingDiagnostics.FrameProfEnabled</c>
|
||||
/// (env var <c>ACDREAM_FRAME_PROF</c>). Toggling here starts/stops the
|
||||
/// [frame-prof] 5-second report live — no relaunch required.
|
||||
/// </summary>
|
||||
public bool FrameProf
|
||||
{
|
||||
get => RenderingDiagnostics.FrameProfEnabled;
|
||||
set => RenderingDiagnostics.FrameProfEnabled = value;
|
||||
}
|
||||
|
||||
// ── Indoor rendering diagnostics (2026-05-19) ───────────────────
|
||||
// Mirror RenderingDiagnostics statics so DebugPanel checkbox toggles
|
||||
// take effect on the next render frame without relaunching.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue