Using D3D12_HEAP_TYPE_READBACK Strictly for CPU Reads

In DirectX 12, memory management is exposed directly to the developer, requiring precise allocation strategies to avoid catastrophic performance bottlenecks. D3D12_HEAP_TYPE_READBACK is a specialized heap type explicitly configured to facilitate the transfer of data from the GPU back to the CPU, such as for screenshots, compute shader analysis, or occlusion culling readbacks. Because of the underlying physical memory architecture, CPU cache behaviors, and bus bandwidth constraints, allocating resources in this heap for any purpose other than pulling data into the CPU will severely degrade rendering throughput and frame rates.

Hardware Architecture and Memory Placement

D3D12_HEAP_TYPE_READBACK is backed by system memory (RAM), not local video memory (VRAM). This heap is mapped with CPU cache-friendly attributes—specifically, CPU write-back memory. While this allows the CPU to read data through its L1, L2, and L3 caches at high speeds without incurring massive bus latency penalties, it places the data physically far from the GPU's memory controllers on discrete hardware.

High Cost of GPU Reads

The GPU accesses readback heaps across the PCI Express (PCIe) bus. While PCIe bandwidth is sufficient for asynchronous block copies, reading data from system RAM into GPU shaders introduces severe memory latency. If a shader attempts to read from a resource placed in a readback heap, the GPU execution units stall waiting for data across the PCIe interface. Consequently, the D3D12 runtime restricts readback buffers from supporting standard shader resource states (D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, etc.), allowing only states compatible with copy destinations (D3D12_RESOURCE_STATE_COPY_DEST).

Suboptimal for CPU Writes

Readback heaps are deliberately not designed for data passing from the CPU to the GPU. The CPU write-back caching policy requires cache line invalidations and coherency traffic when CPU writes occur. For uploading data to the GPU, D3D12_HEAP_TYPE_UPLOAD uses write-combining (WC) memory, which buffers sequential writes without polluting the CPU cache or triggering coherency checks. Writing to a readback heap from the CPU incurs unnecessary overhead and defeats the hardware optimizations baked into upload heaps.

Proper Resource Usage Pipeline

To maintain optimal throughput in DirectX 12, resources must follow distinct directional pipelines:

  • D3D12_HEAP_TYPE_DEFAULT: Stored in fast local VRAM. Used exclusively for GPU reads and writes (render targets, textures, vertex buffers, and UAVs).
  • D3D12_HEAP_TYPE_UPLOAD: Stored in system RAM with write-combined access. Used exclusively for CPU-to-GPU data transmission.
  • D3D12_HEAP_TYPE_READBACK: Stored in system RAM with CPU-cached access. Used strictly as a target for CopyResource or CopyBufferRegion commands to pull data from default heaps so the CPU can read the results.

Deviating from this pattern by attempting to perform general computation or CPU-driven uploads on a readback heap violates the architectural design of modern hardware interconnects, leading to PCIe bus saturation, pipeline stalls, and CPU cache thrashing.