Detect and surface host device loss instead of spinning silently

D3D11Window ignored the HRESULTs from Present, ResizeBuffers, and
CreateRenderTargetView, so a host-side TDR / driver reset / GPU hang left the
render loop presenting to a dead device forever with no error.

Now note_device_loss() inspects those HRESULTs; on DXGI_ERROR_DEVICE_REMOVED/RESET
it captures GetDeviceRemovedReason() and sets device_lost(). The main loop checks
it after render_frame, shows a MessageBox with the reason, and stops cleanly.

Per the agreed scope this is detect-surface-halt, not full device re-creation
(which would have to re-init ImGui + the capture pipeline) -- that's future work.
Not unit-testable (TDR isn't deterministically reproducible); fixed by inspection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 01:08:47 +02:00
parent 43d093405e
commit 8182389091
4 changed files with 56 additions and 6 deletions

View File

@@ -504,6 +504,20 @@ int run()
},
sync_interval);
// A host-side TDR / driver reset / GPU hang surfaces as a lost device on Present. We don't
// attempt to recreate the device (it would have to re-init ImGui + the capture pipeline);
// surface it and stop cleanly rather than spin forever rendering nothing.
if (window.device_lost())
{
wchar_t msg[320];
swprintf_s(msg,
L"The graphics device was lost (0x%08lX) -- a driver reset, GPU hang, or TDR on "
L"this PC.\n\nThe mirror can't continue; please restart CoopAllTheThings.",
static_cast<unsigned long>(window.device_lost_reason()));
MessageBoxW(window.hwnd(), msg, L"CoopAllTheThings -- graphics device lost", MB_ICONERROR | MB_OK);
break;
}
// render_frame saves a pending F10 screenshot just before Present; pick up the
// result here so next frame shows the confirmation toast (kept out of the shot).
if (std::wstring shot = window.take_screenshot_result(); !shot.empty())