How DX12 DRED Identifies Page Faults vs Engine Hangs

DirectX 12 Device Removed Extended Data (DRED) provides post-mortem diagnostics to determine the exact cause of GPU crashes, which typically manifest as Device Removed or Timeout Detection and Recovery (TDR) events. DRED differentiates between an engine hang and a GPU page fault by isolating the hardware mechanism that triggered the device removal: it uses execution timeline markers (AutoBreadcrumbs) to detect stalled commands that cause engine hangs, and it matches faulting virtual addresses against an allocation database to pinpoint GPU page faults.

The DRED Architecture Overview

When a DirectX 12 device is removed, the runtime queries the driver and the GPU's memory management unit (MMU) through the ID3D12DeviceRemovedExtendedData interface. DRED gathers crash telemetry into two primary data structures:

  • AutoBreadcrumbs (D3D12_DRED_AUTO_BREADCRUMBS_OUTPUT): Tracks the progress of command execution.
  • Page Fault Allocations (D3D12_DRED_PAGE_FAULT_OUTPUT): Tracks active and recently freed resource memory allocations.

The presence, state, and contents of these outputs reveal whether the device removal stemmed from an infinite execution loop/deadlock (engine hang) or an invalid memory access (page fault).

How DRED Identifies an Engine Hang

An engine hang occurs when the GPU becomes unresponsive because a shader enters an infinite loop, a synchronization primitive causes a deadlock, or the workload exceeds the operating system's TDR timeout period (typically two seconds).

DRED identifies an engine hang using AutoBreadcrumbs:

  1. Command Insertion: While recording command lists, the DRED runtime injects lightweight write commands before and after every draw call, dispatch, copy, and barrier. These commands write sequential counter values into an internal GPU-visible memory buffer.
  2. Execution Tracking: As the GPU hardware processes each command, it writes completion markers back to the buffer.
  3. Post-TDR Analysis: When the OS triggers a TDR due to a non-responsive engine, DRED reads the AutoBreadcrumbs buffer from system memory.
  4. Hang Confirmation: If no memory fault was signaled by the GPU MMU, DRED inspects the breadcrumb nodes. An engine hang is identified when an execution node shows that a command was started by the GPU but never finished. DRED reports the exact command list, the specific draw or dispatch index, and the shader pipeline state where execution stalled.

How DRED Identifies a GPU Page Fault

A GPU page fault occurs when the GPU executes a memory operation targeting an invalid, unmapped, or unauthorized Virtual Address (VA). This commonly happens during use-after-free scenarios, buffer overflows, or when accessing uncommitted tiled resources.

DRED identifies a page fault through the GPU MMU and allocation tracking:

  1. Hardware Trap: When the GPU MMU encounters an access violation, it triggers a hardware trap that halts the device and logs the specific 64-bit faulting Virtual Address.
  2. VA Capture: The display driver passes this faulting address directly to DRED via the PageFaultVA field of D3D12_DRED_PAGE_FAULT_OUTPUT.
  3. Allocation Correlation: DRED maintains two internal allocation lists:
    • Active Allocations: Currently allocated and bound resources (textures, buffers, heaps).
    • Recent Freed Allocations: A ring buffer of recently deleted resources (tombstones).
  4. Root-Cause Mapping: DRED compares the PageFaultVA against the ranges of these allocation lists:
    • If the address matches a recently freed resource, DRED classifies the crash as a use-after-free error and outputs the resource name and allocation history.
    • If the address falls immediately outside an active resource's bounds, DRED flags it as an out-of-bounds access / buffer overrun.
    • If the address does not match any known resource, DRED indicates an access to completely unmapped or wild memory.

Key Differences in Output

Developers can query ID3D12DeviceRemovedExtendedData::GetAutoBreadcrumbsOutput and ID3D12DeviceRemovedExtendedData::GetPageFaultAllocationOutput to programmatically evaluate the crash:

  • In an Engine Hang: PageFaultVA is set to 0 (or nullptr), indicating no MMU violation occurred. The breadcrumb list contains active command nodes where the completion count is lower than the start count.
  • In a Page Fault: PageFaultVA contains a non-zero address. While the breadcrumbs will also show an incomplete command (the command that executed the faulting memory access), the non-zero page fault output takes precedence, definitively marking the crash as a memory violation rather than an algorithmic hang.