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 forCopyResourceorCopyBufferRegioncommands 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.