DirectX 12 Placed vs Committed Resources

DirectX 12 gives developers explicit control over GPU memory, replacing the automatic resource management found in older graphics APIs. This article provides a concise breakdown of two primary resource creation methods in DirectX 12: committed resources and placed resources. You will learn the mechanics behind each approach, how they interact with GPU memory heaps, their specific use cases, and how choosing the right method impacts runtime performance and memory efficiency.

The Foundation: GPU Memory Heaps

In DirectX 12, physical and virtual GPU memory is represented by heap objects (ID3D12Heap). A resource, such as a texture or a vertex buffer, is essentially a structured view over a range of bytes located within a heap. The fundamental difference between committed and placed resources lies in how closely the resource object is bound to its underlying memory allocation.

Committed Resources

A committed resource couples the resource metadata and its underlying heap allocation into a single unified operation using ID3D12Device::CreateCommittedResource.

When you allocate a committed resource, the DirectX 12 runtime and graphics driver simultaneously create an implicit heap large enough to contain the resource and bind the resource directly to it.

Characteristics of Committed Resources:

  • Simplicity: It requires the least amount of boilerplate code. You do not need to create or manage an explicit ID3D12Heap.
  • Isolated Lifetimes: The heap's lifetime is tied directly to the resource. Releasing the resource automatically frees the underlying memory.
  • Driver Optimization: Certain hardware and driver architectures can optimize dedicated allocations for specific, persistent assets, such as large render targets, swap chain buffers, or primary depth-stencil surfaces.
  • Inflexibility: Memory cannot be shared, overlapped, or repurposed for other resources. This can lead to increased memory consumption and fragmentation if overused for temporary or transient assets.

Placed Resources

A placed resource decouples the memory allocation from the resource object. To use placed resources, you first explicitly allocate an ID3D12Heap via ID3D12Device::CreateHeap. You then create individual resources within that heap at specific byte offsets using ID3D12Device::CreatePlacedResource.

Characteristics of Placed Resources:

  • Memory Aliasing: Multiple resources can occupy the same physical memory space within a heap at overlapping offsets. For example, a temporary render target used exclusively in a shadow pass can share memory with a post-processing buffer used later in the frame, dramatically lowering overall VRAM usage.
  • Manual Synchronization: Aliased resources require explicit synchronization. You must use resource aliasing barriers (D3D12_RESOURCE_BARRIER_TYPE_ALIASING) to inform the GPU driver when memory is transitioning from one resource view to another to avoid race conditions and cache corruption.
  • Strict Alignment Rules: Placed resources must strictly adhere to hardware alignment requirements (typically 64 KB for standard buffers and textures, or 4 MB for multi-sample anti-aliasing textures).
  • Efficiency: Creating and destroying placed resources is lightweight compared to committed resources because it does not involve OS-level memory allocations—only the creation of a resource descriptor over existing memory.

Key Differences Summary

Feature Committed Resources Placed Resources
Heap Creation Implicit (handled by driver) Explicit (ID3D12Device::CreateHeap)
API Method CreateCommittedResource CreatePlacedResource
Memory Aliasing Not supported Fully supported
Allocation Cost Slower (allocates OS/GPU memory) Fast (maps over existing heap)
Complexity Low High (requires barrier & offset management)

When to Use Each

Use committed resources for long-lived, high-priority assets that remain active throughout the application's lifecycle, such as back buffers, static environment geometry, UI buffers, and primary depth buffers.

Use placed resources for transient, frame-graph-driven workloads. They are best suited for scratch buffers, intermediate render passes, compute buffers, and dynamic asset streaming systems where memory reuse and strict limits on total VRAM consumption are critical.