Binding

This will drain you sanity

Descriptors

A descriptor is a block of GPU-specific data that describe an object to the GPU. They where called “resource views” in past DirectX version and the name view still show up in many places in the API.

The driver to not track the creation of descriptors and there can be multiple descriptors that describe the same object.

Non-Heap Descriptors

These descriptors are not placed in any heap. They are created by simply filling in a structure with the information and then used directly as a argument to functions on a commandlist.

IBV - Index Buffer View - D3D12_INDEX_BUFFER_VIEW

A descriptor to a index buffer that contain the GPU address of the index buffer, the size in bytes and the format. It can then be used directly in a call to ID3D12GraphicsCommandList::IASetIndexBuffer.

VBV - Vertex Buffer View - D3D12_VERTEX_BUFFER_VIEW

A descriptor to a vertex buffer that contain the GPU address of the buffer, the size in bytes and the stride in bytes. It can then be used directly in a call to ID3D12GraphicsCommandList::IASetVertexBuffers.

SOV - Stream Output View - D3D12_STREAM_OUTPUT_DESC

Used to write out the vertex data from the vertex-shader or geometry-shader stage.

Heap Descriptors

These descriptors need to be placed inside a descriptor heap of that support the type of the descriptor. They are created by filling in a structure and then calling a function on the device.

RTV - Render Target View - D3D12_RENDER_TARGET_VIEW_DESC / ID3D12Device::CreateRenderTargetView

Describes the render target.

DSV - Depth Stencil View - D3D12_DEPTH_STENCIL_VIEW_DESC / ID3D12Device::CreateDepthStencilView

Descripe a depth and stencil buffer.

Sampler - D3D12_SAMPLER_DESC / ID3D12Device::CreateSampler

A sampler contains the information needed to sample data from a texture. The two common settings to care about is the Filter and the Address mode that resolve texture coordinates outside the 0 to 1 range. It is common that the same sampler settings is used many times in a application so another options is to use static samplers. They can be setup when a PSO is created and do not need to be put into heaps and managed later. The limit for number of unique static samplers is 2032 so if one use more some need to be put in heaps.

SRV - Shader Resource View - D3D12_SHADER_RESOURCE_VIEW_DESC / ID3D12Device::CreateShaderResourceView

A descriptor to a buffer or texture resource. A common usage is for 2D textures. The Create functions also takes the resource pointer as an argument.

CBV - Constant Buffer View - D3D12_CONSTANT_BUFFER_VIEW_DESC / ID3D12Device::CreateConstantBufferView

UAV - Unordered Access View - D3D12_UNORDERED_ACCESS_VIEW_DESC / ID3D12Device::CreateUnorderedAccessView

Descriptor Heaps

A descriptor heap is a chunk of memory where descriptors are stored. To create a heap fill in a D3D12_DESCRIPTOR_HEAP_DESC and then create it with ID3D12Device::CreateDescriptorHeap(). In the _DESC structure you select how many descriptor it should have room for and what type it is. There are four types of heaps; one for RTV, one for DSV, one for Samplers and one for CBV, SRV and UAV.

Descriptor handle

Descriptors in heaps are accessed by using descriptor handles. Each descriptor has two handles depending on if it should be used by the CPU (D3D12_CPU_DESCRIPTOR_HANDLE) or the GPU (D3D12_GPU_DESCRIPTOR_HANDLE). To get the handle of a descriptor x in a heap first get a handle to the first descriptor in the heap with ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart or ID3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart. Then you need to offset the handle by x * the size of the descriptor type. The size of the descriptor type is hardware dependent so get it with ID3D12Device::GetDescriptorHandleIncrementSize() .

Shader Visible Descriptor Heaps

The shader visible heaps are ones that can be accessed through descriptor tables by shaders. To create it as shader visible set it flags in the _DESC structure when creating it. When created as shader visible there might be a hardware size limit on the heap size.

    • D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV

    • D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER

Non Shader Visible Descriptor Heaps

These type of heaps are not used from shaders so they have no size limite when created. The shader visible heaps can also be created as non shader visible and then there will be no size limit for them. Such a heap can be used to stage (prepare descriptors to be used later) and then one can copy them over to the shader visible heap.

    • D3D12_DESCRIPTOR_HEAP_TYPE_RTV

    • D3D12_DESCRIPTOR_HEAP_TYPE_DSV

Filling a heap

When a heap have been created one needs to fill it with real descriptors as they all start out the life as undefined. There are two possible ways to do this, to generate descriptors or to copy existing ones.

Generate

On the ID3D12Device there are functions to create discriptors in heaps, see above in this document. They take a D3D12_CPU_DESCRIPTOR_HANDLE to the descriptor in the heap. It can be created in a shader-visible heaps and non-shader-visible ones.

Copy

With ID3D12Device::CopyDescriptors() and ID3D12Device::CopyDescriptorsSimple() it is possible to copy from one descriptor heap to another. The source heap must be non-shader-visible. The destination can have any visibility.

Using the heap

So set what heaps to use on a command list call ID3D12GraphicsCommandList::SetDescriptorHeaps( ). The heaps need to be shader visible and max one TYPE_CBV_SRV_UAV and one TYPE_SAMPLER heap can be used at the same time. Switching to a new heap can be a expensive operation.