Diag: add BT_SHOT backbuffer dump + correct/park the -net render glitch (task #53)

Scouted the "-net node render glitch". Two prior framings were wrong and are
corrected in the KB: it is NOT device contention (retracted earlier), and it is
NOT a from-load glitch -- the trigger is a RESPAWN (user correction). It's a
post-respawn render-rebuild fault on the MP path.

Could not reproduce in 9 automated 2-node loads + a forced death/respawn (all
clean). Debug uninit is a deterministic 0xCDCDCDCD, so the intermittency implies
a race -- and the task #52 respawn fixes (LoadMission re-entry, viewpoint relink,
death-latch) plausibly already closed it. Parked as WATCH; re-open if it recurs.

Tooling (general, off by default): BT_SHOT=<path> dumps a per-instance backbuffer
PNG from the world-render path (L4VIDEO.cpp) every 90 frames -- lets us capture a
specific node's frame without foregrounding the window. Used with
scratchpad/hunt53.sh (N-run divergence hunter) to verify a fix if the glitch
returns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-10 15:48:54 -05:00
co-authored by Claude Opus 4.8
parent 0bfb3d4ab3
commit 7b0b4f64ab
2 changed files with 52 additions and 13 deletions
+28
View File
@@ -7798,6 +7798,34 @@ void DPLRenderer::ExecuteImplementation(RendererComplexity, RendererOrigin::Inte
BTDrawTranslocationSpheres(mDevice, &viewTransform, (float)dT, mTargetRenderTime);
}
// DIAG (off by default): BT_SHOT=<path> dumps this instance's backbuffer (the rendered
// WORLD, before the 2D HUD overlay) to a PNG once ~180 frames in, for non-disruptive
// per-instance frame capture without foregrounding the window. Each instance sets its
// own path. Built for the -net render glitch (task #53) but general.
{
const char *shotPath = getenv("BT_SHOT");
if (shotPath)
{
static int s_btShotN = 0;
++s_btShotN;
// dump (overwriting) every 90 frames once past 90, so the file always holds a
// recent frame regardless of load timing / debug fps.
if (s_btShotN >= 90 && (s_btShotN % 90) == 0)
{
IDirect3DSurface9 *bb = 0;
if (SUCCEEDED(mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &bb)) && bb)
{
HRESULT hr = D3DXSaveSurfaceToFileA(shotPath, D3DXIFF_PNG, bb, 0, 0);
bb->Release();
DEBUG_STREAM << "[btshot] frame " << s_btShotN << " -> " << shotPath
<< " hr=0x" << std::hex << (unsigned)hr << std::dec << "\n" << std::flush;
}
else
DEBUG_STREAM << "[btshot] GetBackBuffer FAILED frame " << s_btShotN << "\n" << std::flush;
}
}
}
// The BT targeting reticle / weapon pips (2D screen space, cockpit view
// only -- the dpl2d layer; see game/reconstructed/dpl2d.cpp).
{