How DirectX Handles Device Lost Events From TDR
When a graphics processing unit (GPU) stops responding, the Windows operating system uses Timeout Detection and Recovery (TDR) to reset the hardware and prevent a full system freeze. In response, the DirectX runtime invalidates the active virtual device, isolates the stalled graphics context, and signals the application that the hardware connection has been severed. This article explains how the DirectX runtime processes TDR events, how it translates low-level hardware resets into API-level error states, and how applications must respond to successfully recover.
The Trigger: Operating System TDR
The Windows Display Driver Model (WDDM) constantly monitors the GPU scheduler via a watchdog timer. If an individual draw call, compute shader, or internal command takes longer than the default threshold (typically two seconds) to execute, WDDM considers the GPU hung.
To resolve the hang without requiring a complete system reboot:
- The OS scheduler preempts or forcefully halts the non-responsive thread on the GPU.
- The display miniport driver resets the graphics hardware engine.
- The kernel reallocates physical video memory and marks existing contexts invalid.
- The kernel notifies the DirectX graphics kernel subsystem (Dxgkrnl), which informs the user-mode DirectX runtime.
How the DirectX Runtime Flags the Lost Device
Once notified of a reset, the DirectX runtime immediately transitions the software device representation into a "device removed" state. Because the underlying hardware state and virtual memory allocations were purged during the driver reset, the DirectX runtime disables further hardware communication to avoid memory corruption or undefined system states.
The runtime handles this invalidation through the following mechanisms:
- Command Dropping: Any command queues, immediate contexts, or deferred command lists that attempt to dispatch work to the GPU after a TDR will be intercepted by the runtime and discarded.
- Return Code Propagation: The next call to a
synchronization point—most commonly
IDXGISwapChain::Present(orPresent1)—fails and returns a failure code, typicallyDXGI_ERROR_DEVICE_REMOVEDorDXGI_ERROR_DEVICE_RESET. - Reason Isolation: The DirectX runtime provides the
specific cause of the failure via
GetDeviceRemovedReason(). During a TDR event, this method usually returns:DXGI_ERROR_DEVICE_HUNG: The GPU was reset because a command took too long to complete.DXGI_ERROR_DEVICE_RESET: The GPU was reset due to an invalid command or driver malfunction.
Behavior Differences Across DirectX Versions
DirectX 9
In legacy Direct3D 9, the runtime reported TDRs via the
D3DERR_DEVICELOST error code during Present or
TestCooperativeLevel. Direct3D 9 required applications to
release default-pool resources and call
IDirect3DDevice9::Reset once
TestCooperativeLevel returned
D3DERR_DEVICENOTRESET.
DirectX 11
In Direct3D 11, the runtime treats a TDR as non-recoverable on the
existing ID3D11Device instance. The runtime invalidates all
device-specific handles (such as textures, shaders, and buffer views).
Even if the physical GPU recovers within milliseconds, the
ID3D11Device context remains permanently dead.
DirectX 12
Because Direct3D 12 provides lower-level hardware abstraction, the
runtime immediately invalidates command queues
(ID3D12CommandQueue) and fences (ID3D12Fence).
Any CPU threads waiting on completion fences receive an error or unblock
immediately, preventing the application from hanging on a GPU execution
that will never finish. Calling
ID3D12Device::GetDeviceRemovedReason() reflects the TDR
state directly to the developer.
Required Recovery Steps for Applications
The DirectX runtime cannot automatically restore user assets or state following a TDR because GPU-side memory allocations are purged. To recover gracefully without crashing, an application must execute the following workflow:
- Detect the Error: Check the HRESULT of
Presentor command list submissions forDXGI_ERROR_DEVICE_REMOVEDorDXGI_ERROR_DEVICE_RESET. - Log the Cause: Call
GetDeviceRemovedReasonon the device interface to capture the diagnostic code for debugging. - Release Dependent Resources: Completely release all hardware-dependent objects, including textures, buffers, pipeline states, views, swap chains, and the DirectX device itself.
- Re-enumerate Adapters: Query the
IDXGIFactoryto re-enumerate the physical display adapters, ensuring the driver has completed its reset sequence and is ready to accept commands. - Recreate the Pipeline: Initialize a new DirectX device, rebuild swap chains, and reload all graphics assets and shader programs into video memory.