feat(render): Phase A8 — full GL state probe + pool diagnostics (apparatus)

Defense-in-depth apparatus per the 2026-05-27 handoff's option-1 recommendation.
The audit-found pool aliasing bug (prior commit) is the primary fix; this probe
is the safety net for any unidentified residual issue when the visual gate runs.

EmitDrawOrderProbe now logs the full GL state at each step boundary of
RenderInsideOutAcdream — stencil test/func/ref/mask/op, depth func/mask, cull
face/mode, blend src/dst, color writemask, current VAO, current program. An
operator can read the log offline and compare line-by-line against WB's
expected state at VisibilityManager.cs:73-239. Any divergence pinpoints the
bug's GL-state shape; matching state confirms the issue is elsewhere
(instance data, mesh upload, etc.).

EmitEnvCellProbe now logs pool diagnostics — total pool size + snapshot's
PostPreparePoolIndex high-water mark. A spike in poolTotal across stationary-
camera frames, or a divergence between poolHwm and cell-count, signals
pool-management regression. The fix-the-bug-first principle keeps this probe
dormant by default; enable via ACDREAM_PROBE_VIS=1 only when investigating.

Heavy (~10 GL queries per step × 5-10 steps per frame), but gated.

86/86 App tests still pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-27 19:11:00 +02:00
parent 9559726960
commit 375f9a7b9b
2 changed files with 74 additions and 5 deletions

View file

@ -88,6 +88,21 @@ public sealed unsafe class EnvCellRenderer : IDisposable
public struct LastFrameStats { public int CellsRendered; public int TrianglesDrawn; }
private LastFrameStats _lastFrameStats;
/// <summary>
/// Diagnostic accessor for the [envcells] probe (Phase A8 apparatus 2026-05-28).
/// Returns (pool-list count total, snapshot's PostPreparePoolIndex high-water).
/// A divergence between expected and actual values would indicate a pool-
/// management regression — exactly the bug class the 2026-05-28 audit caught.
/// </summary>
public (int PoolTotal, int SnapshotPoolHwm) GetPoolDiagnostics()
{
int poolTotal;
lock (_listPool) poolTotal = _listPool.Count;
int hwm;
lock (_renderLock) hwm = _activeSnapshot.PostPreparePoolIndex;
return (poolTotal, hwm);
}
// ---------------------------------------------------------------------------
// Constructor + Initialize
// ---------------------------------------------------------------------------