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

@@ -47,6 +47,19 @@ public:
// the result (so a confirmation shows once); otherwise returns an empty string.
[[nodiscard]] std::wstring take_screenshot_result();
// True once Present/ResizeBuffers reported DXGI_ERROR_DEVICE_REMOVED/RESET (a host-side TDR,
// driver reset, or GPU hang). The render loop is expected to stop and surface the error rather
// than spin forever on a dead device; full device re-creation is intentionally not attempted.
[[nodiscard]] bool device_lost() const
{
return device_lost_;
}
// The GetDeviceRemovedReason() HRESULT (or the originating error) when device_lost() is true.
[[nodiscard]] HRESULT device_lost_reason() const
{
return device_lost_reason_;
}
[[nodiscard]] HWND hwnd() const
{
return hwnd_;
@@ -68,6 +81,9 @@ private:
void release_render_target();
void handle_resize(UINT width, UINT height);
bool save_backbuffer_png(const std::wstring& path);
// If `hr` is DEVICE_REMOVED/RESET, capture the removed reason and set device_lost_; returns true
// when the device is now lost so the caller can bail out of whatever it was doing.
bool note_device_loss(HRESULT hr);
HWND hwnd_ = nullptr;
std::wstring pending_screenshot_; // set by request_screenshot, consumed in render_frame
@@ -75,6 +91,8 @@ private:
bool resize_pending_ = false;
UINT resize_width_ = 0;
UINT resize_height_ = 0;
bool device_lost_ = false;
HRESULT device_lost_reason_ = S_OK;
Microsoft::WRL::ComPtr<ID3D11Device> device_;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> context_;