Resource Heaps

[Some information relates to pre-released product which may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.]

A resource heap is a large, contiguous block of memory. It provides the backing storage for resources.

  • Heap types
  • Suballocation
    • Buffer alignment
  • Resources
    • Resource creation APIs
    • Resource size reflection
    • Mapping and unmapping
    • Copying
    • Sharing
  • Related topics

Heap types

Resource heaps can have a number of properties attached to them. The following lists some of the more common types of heap:

  • Upload Heaps: a heap for loading data from the CPU to the GPU, typically containing vertex, index or constant buffers, or textures and other resources.
  • Readback Heaps: a heap for loading data back from the GPU to the CPU. Typical data that would be collected by the GPU and downloaded to the CPU would be image data from a captured screen shot, and statistical and performance data such as counters and timings.
  • Default Heaps: a heap which supports all GPU operations. This resource heap is focused on containing data that is persistently required by the GPU, such as index and vertex data that may be required for many frames.

Refer to the D3D12_HEAP_TYPE enum.

Apps are required to explicitly manage resource lifetime in the heaps, as shown in Fence-Based Resource Management.

Suballocation

Heaps will often contain sub-allocated memory blocks, or "buffers". Buffers can be used orthogonally and concurrently from multiple parts of the graphics pipeline, and are very flexible. Common buffers are defined with the following API (or range of API) calls:

CopyResource operations are performed on the GPU and do not incur a significant CPU workload linearly dependent on the size of the data to copy.

Data typically associated with buffers and pitch-linear texture data operations are required to be aligned properly for use by the GPU. Both buffer and pitch-linear data may reside next to each other and even overlap. Pitch-linear requirements and restrictions are as follows:

  • Only a single 3D subresource, at a time, is required of pitch-linear/row-major copying.
  • Only a single 2D subresource, at a time, is required of pitch-linear/row-major sampling and rendering.
  • The base address/offset of pitch-linear texture data must be 512-byte aligned.
  • The width stride must be D3D12_TEXTURE_DATA_PITCH_ALIGNMENT byte aligned, for all texel element sizes. The width stride is 32-bit and can be much greater than the tightest stride that is correctly aligned for a particular texture width.
  • Arbitrary height, up to the D3D12 maximum, is supported orthogonally.
  • For volume textures, the depth stride is height * stride width.
  • Compressed render targets must be resolvable to enable the CPU to read and write the texels.

Buffer alignment

Buffer alignment restrictions have not changed from D3D11, notably:

  • 4 MB for multi-sample textures.
  • 64 KB for single-sample textures and buffers.
  • Linear subresource copying must be aligned to 512 bytes (with the row pitch aligned to D3D12_TEXTURE_DATA_PITCH_ALIGNMENT bytes).
  • Constant data reads must be a multiple of 256 bytes from the beginning of the heap (i.e. only from addresses that are 256-byte aligned).
  • Index data reads must be a multiple of the index data type size (i.e. only from addresses that are naturally aligned for the data).
  • ID3D12GraphicsCommandList::DrawInstanced and ID3D12GraphicsCommandList::DrawIndexedInstanced data must be from offsets that are multiples of 4 (i.e. only from addresses that are DWORD aligned).

Resources

Resources are the D3D concept which abstracts the usage of GPU physical memory. Resources require GPU virtual address space to access physical memory.

There are three types of resources with respect to virtual address creation and flexibility in D3D12:

  • Committed resources

    Committed resources are the most common idea of D3D resources over the generations. Creating such a resource allocates virtual address range, an implicit heap large enough to fit the whole resource, and commits the virtual address range to the physical memory encapsulated by the heap. The implicit heap properties must be passed to match functional parity with previous D3D versions.

  • Reserved resources

    Reserved resources are equivalent to D3D11 tiled resources. On their creation, only a virtual address range is allocated and not mapped to any heap. The application will map such resources to heaps later. The capabilities of such resources are currently unchanged over D3D11, as they can be mapped to a heap at a 64KB tile granularity with UpdateTileMappings.

  • Placed resources

    New for D3D12, applications may create heaps separate from resources. Afterward, the application may locate multiple resources within a single heap. This can be done without creating tiled or reserved resources, enabling the capabilities for all resource types able to be created directly by applications. Multiple resources may overlap, and the application must use the TiledResourceBarrier to re-use physical memory correctly.

Resource creation APIs

The following APIs reference resource creation. New to D3D12 is the ID3D12Resource interface.

Enums:

Structures:

Creation methods:

Resource creation is free-threaded. The initial resource state must be valid for the resource type, or E_INVALIDARG occurs.

Resource size reflection

Applications must use resource size reflection to understand how much room textures with unknown texture layouts require in heaps. Buffers are also supported, but mostly as a convenience.

Applications should be aware of major alignment discrepancies, to help pack resources more densely.

For example, a single-element array with a one-byte-buffer returns a Size of 64KB and an Alignment of 64KB, as buffers currently can only be 64KB aligned.

Also, a three element array with two single-texel 64KB aligned textures and a single-texel 4MB aligned texture reports differing sizes based on the order of the array. If the 4MB aligned textures is in the middle, the resulting Size is 12MB. Otherwise, the resulting Size is 8MB. The Alignment returned would always be 4MB, the super-set of all alignments in the resource array.

Reference the following APIs:

Mapping and unmapping

Map and Unmap can be called by multiple threads safely. Nested Map calls are supported and are ref-counted. The first call to Map allocates a CPU virtual address range for the resource. The last call to Unmap deallocates the CPU virtual address range. The CPU virtual address is commonly returned to the application; but manipulating the contents of textures with unknown layouts precludes the disclosure of the CPU virtual address.

Whenever data is passed between the CPU and GPU through resources in readback heaps, Map and Unmap must be used to support all systems D3D12 is supported on. Keeping the ranges as tight as possible maximizes efficiency on the systems that require ranges (refer to D3D12_RANGE).

The performance of debugging tools benefit not only from the accurate usage of ranges on all Map / Unmap calls, but also from applications unmapping resources when CPU modifications will no longer be made.

The D3D11 method of using Map (with the DISCARD parameter set) to rename resources is not supported in D3D12. Applications must implement resource renaming themselves. All Map calls are implicitly NO_OVERWRITE and multi-threaded. It is the application’s responsibility to ensure that any relevant GPU work contained in command lists is finished before the accessing data with the CPU. D3D12 calls to Map do not implicitly flush any command buffers, nor do they block waiting for the GPU to finish work. As a result, Map and Unmap may even be optimized out in some scenarios.

Copying

D3D12 methods enable applications to replace D3D11 UpdateSubresource, CopySubresourceRegion, and resource initial data. A single 3D subresource worth of row-major texture data may be located in buffer resources. CopyTextureRegion can copy that texture data from the buffer to a texture resource with an unknown texture layout, and vice versa. Applications should prefer this type of technique to populate frequently accessed GPU resources, by create large buffers in a UPLOAD heap while creating the frequently accessed GPU resource in a DEFAULT heap that has no CPU access. Such a technique efficiently supports discrete GPUs and their large amounts of CPU-inaccessible memory, without commonly impairing UMA architectures.

Note the following two constants:

const UINT D3D12_TEXTURE_DATA_PITCH_ALIGNMENT = 256;
const UINT D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT = 512;

The following methods will rearrange texture data between a row-major layout and an undefined resource layout. The operation is synchronous, as in the memory is copied by the time the function calls. So, the application should keep CPU scheduling in mind. The application can always break up the copying into smaller regions or schedule this operation in another task.

MSAA resources and depth-stencil resources with opaque resource layouts are not supported for the following CPU copy operations, and will cause a failure. Formats which don’t have a power-of-two element size are also not supported and will cause a failure. Out of memory return codes can occur.

Sharing

Sharing applies to multi-engine/multi-GPU architectures.

Both heaps and committed resources can be shared. Sharing a committed resource actually shares the implicit heap along with the committed resource description, such that a compatible resource description can be mapped to the heap from another device.

All methods are free-threaded and inherit the existing D3D11 semantics of the NT handle sharing design.

Note the DENY_TEXTURES and DENY_BUFFERS heap flags (see D3D12_HEAP_FLAGS) exist to prevent sharing, if necessary.

In this section

Topic Description

Using Resource Heaps

To best use resource heaps, an app should implement large buffers to store heaps and multiple types of resource including textures, index and vertex buffers, as well as other data.

 

ID3D12Heap

Memory Management