MSDN Documentation

Overview

The DirectX Graphics resource management subsystem provides developers with a set of APIs to create, bind, and destroy GPU resources such as buffers, textures, and shaders. Proper management of these resources is essential for achieving high performance and minimizing GPU memory fragmentation.

FeatureDescription
Resource TypesBuffers, Textures, Samplers, Views
LifetimeExplicit creation & release, reference counting
Memory HeapsDefault, Upload, Readback, Custom
Debug LayerRuntime validation of resource usage

Resource Types

DirectX defines several core resource classes. Each class maps to a specific GPU object type.

  • ID3D12Resource – Base class for buffers and textures.
  • ID3D12DescriptorHeap – Stores descriptors for SRVs, UAVs, CBVs, etc.
  • ID3D12PipelineState – Encapsulates compiled shaders and state objects.

Resources are created with ID3D12Device::CreateCommittedResource or ID3D12Device::CreatePlacedResource, depending on whether they are allocated from a heap or placed within a pre‑allocated heap.

Lifetime Management

Resource lifetimes must be carefully coordinated with command queue execution. The typical pattern is:

  1. Create resource.
  2. Record commands that use the resource.
  3. Signal a fence after submitting the command list.
  4. Release the resource only after the fence is signaled.

Using the ComPtr smart pointer simplifies reference counting:

Microsoft::WRL::ComPtr<ID3D12Resource> vertexBuffer;
device->CreateCommittedResource(
    &heapProperties,
    D3D12_HEAP_FLAG_NONE,
    &resourceDesc,
    D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
    nullptr,
    IID_PPV_ARGS(&vertexBuffer));

Memory Pools & Heaps

Choosing the right heap type directly impacts performance:

  • Default Heap – GPU‑only memory; fast access for rendering.
  • Upload Heap – CPU‑visible, write‑combined; ideal for uploading dynamic data.
  • Readback Heap – CPU‑visible, cached; used for retrieving GPU results.

For large static assets, consider using a custom heap to reduce fragmentation and improve allocation speed.

Best Practices

  • Batch resource creation to minimize API overhead.
  • Reuse descriptors via descriptor heaps whenever possible.
  • Prefer TransitionResource barriers over implicit state changes.
  • Enable the DX12 Debug Layer during development to catch misuse.
  • Align resources to D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT for optimal placement.

Sample Code

The following example demonstrates creating a vertex buffer, uploading data, and issuing a draw call.

#include <d3d12.h>
#include <dxgi1_4.h>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;

struct Vertex { float x, y, z; float r, g, b, a; };

void CreateVertexBuffer(ID3D12Device* device, ID3D12GraphicsCommandList* cmdList)
{
    // Vertex data
    Vertex vertices[] = {
        { 0.0f,  0.5f, 0.0f, 1,0,0,1 },
        { 0.5f, -0.5f, 0.0f, 0,1,0,1 },
        {-0.5f, -0.5f, 0.0f, 0,0,1,1 },
    };
    const UINT vertexBufferSize = sizeof(vertices);

    // Create upload heap for the vertex data
    ComPtr<ID3D12Resource> vertexBufferUpload;
    D3D12_HEAP_PROPERTIES uploadHeapProps = {};
    uploadHeapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
    D3D12_RESOURCE_DESC bufferDesc = {};
    bufferDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
    bufferDesc.Width = vertexBufferSize;
    bufferDesc.Height = 1;
    bufferDesc.DepthOrArraySize = 1;
    bufferDesc.MipLevels = 1;
    bufferDesc.SampleDesc.Count = 1;
    bufferDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;

    device->CreateCommittedResource(
        &uploadHeapProps,
        D3D12_HEAP_FLAG_NONE,
        &bufferDesc,
        D3D12_RESOURCE_STATE_GENERIC_READ,
        nullptr,
        IID_PPV_ARGS(&vertexBufferUpload));

    // Copy data to the upload heap
    void* pVertexDataBegin;
    D3D12_RANGE readRange = {}; // We do not intend to read from this resource on the CPU.
    vertexBufferUpload->Map(0, &readRange, &pVertexDataBegin);
    memcpy(pVertexDataBegin, vertices, vertexBufferSize);
    vertexBufferUpload->Unmap(0, nullptr);

    // Create default heap (GPU‑only) buffer
    ComPtr<ID3D12Resource> vertexBufferGPU;
    D3D12_HEAP_PROPERTIES defaultHeapProps = {};
    defaultHeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
    device->CreateCommittedResource(
        &defaultHeapProps,
        D3D12_HEAP_FLAG_NONE,
        &bufferDesc,
        D3D12_RESOURCE_STATE_COPY_DEST,
        nullptr,
        IID_PPV_ARGS(&vertexBufferGPU));

    // Copy from upload heap to default heap
    cmdList->CopyBufferRegion(vertexBufferGPU.Get(), 0, vertexBufferUpload.Get(), 0, vertexBufferSize);

    // Transition to VERTEX_AND_CONSTANT_BUFFER state
    D3D12_RESOURCE_BARRIER barrier = {};
    barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
    barrier.Transition.pResource = vertexBufferGPU.Get();
    barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
    barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
    barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
    cmdList->ResourceBarrier(1, &barrier);

    // Create a vertex buffer view
    D3D12_VERTEX_BUFFER_VIEW vbView = {};
    vbView.BufferLocation = vertexBufferGPU->GetGPUVirtualAddress();
    vbView.SizeInBytes = vertexBufferSize;
    vbView.StrideInBytes = sizeof(Vertex);
    cmdList->IASetVertexBuffers(0, 1, &vbView);
}

Compile with /EHsc /std:c++17 and link against d3d12.lib and dxgi.lib.