DirectX Programming Guide

Core Concepts: Resources

Resources

In DirectX, resources are the fundamental objects that store data used by the graphics pipeline. These include textures, vertex buffers, index buffers, constant buffers, and more. Understanding how to create, manage, and bind these resources is crucial for efficient rendering.

Types of Resources

DirectX defines several types of resources, each serving a specific purpose:

  • Textures: Two-dimensional or three-dimensional arrays of data, typically used for images, lighting information, or other visual data.
  • Buffers: Linear arrays of data. Common buffer types include:
    • Vertex Buffers: Store vertex data (position, color, texture coordinates, etc.).
    • Index Buffers: Store indices that reference vertices in a vertex buffer, allowing for efficient rendering of complex geometry.
    • Constant Buffers: Store data that is constant for a given draw call, such as transformation matrices, lighting parameters, or material properties.
    • Structured Buffers: Generic buffers that can be read from and written to by shaders.
  • Render Targets: Resources that can be written to by the graphics pipeline during rendering, typically used for the output of a frame.
  • Depth-Stencil Buffers: Used for depth testing and stencil operations to control visibility and rendering effects.

Resource Creation

Resources are typically created using methods on the ID3D12Device interface. The exact method depends on the type of resource, but common patterns involve specifying dimensions, format, memory usage, and initial data.

For example, creating a simple texture might involve:

// Example structure for texture creation (simplified) D3D12_RESOURCE_DESC textureDesc = {}; textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; textureDesc.Width = static_cast(width); textureDesc.Height = static_cast(height); textureDesc.DepthOrArraySize = 1; textureDesc.MipLevels = 1; textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; textureDesc.SampleDesc.Count = 1; textureDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE; D3D12_HEAP_PROPERTIES heapProps = {}; heapProps.Type = D3D12_HEAP_TYPE_DEFAULT; // Typically GPU-local memory for textures // Create the texture resource ComPtr<ID3D12Resource> textureResource; ThrowIfFailed(device->CreateCommittedResource( &heapProps, D3D12_HEAP_FLAG_NONE, &textureDesc, D3D12_RESOURCE_STATE_COPY_DEST, // Initial state nullptr, IID_PPV_ARGS(&textureResource) ));

Resource Binding

Before a resource can be used by the graphics pipeline, it must be bound to the appropriate pipeline state. This is typically done through the use of Descriptor Heaps and Root Signatures.

Descriptor heaps act as tables that hold descriptors, which are small handles pointing to GPU resources. When shaders need to access a resource (e.g., sample a texture or read from a constant buffer), they reference a descriptor in a descriptor heap. The root signature tells the pipeline which descriptor heaps to bind and how to use them.

Common Binding Slots:

  • Vertex Shader: Vertex buffers, constant buffers, SRV (Shader Resource View) for textures.
  • Pixel Shader: Textures (SRVs), constant buffers, UAV (Unordered Access View) for compute or read/write operations.

Resource States

DirectX 12 introduces the concept of resource states. Resources transition between different states (e.g., D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET) to indicate their intended use. Transitions are managed via Resource Barriers within command lists, ensuring that resources are in the correct state for the operations being performed.

// Example of a resource barrier for state transition D3D12_RESOURCE_BARRIER barrier = {}; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrier.Transition.pResource = textureResource.Get(); barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; commandList->ResourceBarrier(1, &barrier);

Memory Management

DirectX 12 provides more explicit control over memory. Resources are associated with heaps, which define their memory properties (e.g., GPU-only, CPU-visible). Developers must manage heap allocation and resource placement to optimize performance and avoid memory-related issues.