-
Notifications
You must be signed in to change notification settings - Fork 411
DescriptorHeap
DirectXTK |
---|
In order to render with resources like textures, DirectX 12 uses a descriptor to provide the meta-data required. This helper provides a simple manager for the GPU memory heap of resource descriptors.
See also DescriptorPile
Related tutorial: Sprites and textures
#include "DescriptorHeap.h"
The client application maintains a list of identifiers for indices for each resource, such as:
enum Descriptors
{
WindowsLogo,
CourierFont,
ControllerFont,
GamerPic,
Count
};
Then creates the heap to hold them:
resourceDescriptors = std::make_unique<DescriptorHeap>(device,
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
Descriptors::Count);
Since this is the most common usage case (CBV/SRV/UAV heap with shader visibility), there's a simplified constructor version:
resourceDescriptors = std::make_unique<DescriptorHeap>(device, Descriptors::Count);
You can then use this to create shader resource view as a resource descriptor with the CPU handle:
D3D12_SHADER_RESOURCE_VIEW_DESC desc = {};
...
device->CreateShaderResourceView(tex, &desc,
resourceDescriptors->GetCpuHandle(Descriptors::WindowsLogo));
Then to reference the SRV for rendering, you get the GPU handle using the same index identifier:
effect->SetTexture(resourceDescriptors->GetGpuHandle(Descriptors::WindowsLogo));
Strongly typed enums (a.k.a.
enum class
) are not recommended here as this requires adding astatic_cast<int>
when using the enum as a parameter toGetCpuHandle
orGetGpuHandle
.
There are two alternative ways to construct a DescriptorHeap. The first takes ownership of an existing heap:
DescriptorHeap(ID3D12DescriptorHeap* pExistingHeap);
The second takes a D3D12_DESCRIPTOR_HEAP_DESC description:
DescriptorHeap(ID3D12Device* device, const D3D12_DESCRIPTOR_HEAP_DESC* pDesc);
There are four types of descriptor heaps in DirectX 12:
-
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
- A heap of constant buffer views, shader resource reviews, and/or unordered-access views. -
D3D12_DESCRIPTOR_HEAP_TYPE_RTV
- A heap of render target views. -
D3D12_DESCRIPTOR_HEAP_TYPE_DSV
- A heap of depth/stencil views. -
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER
- A heap of (non-static) samplers.
To render, the descriptor heap must be made active on the current command list:
ID3D12DescriptorHeap* heaps[] = { resourceDescriptors->Heap() };
commandList->SetDescriptorHeaps(static_cast<UINT>(std::size(heaps)), heaps);
References to elements on the heap are made using the client identifiers:
// Returns a D3D12_GPU_DESCRIPTOR_HANDLE
resourceDescriptors->GetGpuHandle(Descriptors::WindowsLogo)
// Returns a D3D12_CPU_DESCRIPTOR_HANDLE
resourceDescriptors->GetCpuHandle(Descriptors::WindowsLogo)
To provide flexibility, setting the proper descriptor heaps to render with via
SetDescriptorHeaps
is left to the caller.
DescriptorHeap can also be used for creating Render Target View Descriptors or Depth/Stencil View Descriptors:
enum RTDescriptors
{
SceneRT,
Blur1RT,
Blur2RT,
RTCount
};
renderDescriptors = std::make_unique<DescriptorHeap>(device,
D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
RTDescriptors::RTCount);
device->CreateRenderTargetView(sceneTex.Get(),
nullptr,
renderDescriptors->GetCpuHandle(RTDescriptors::SceneRT));
depthDescriptors = std::make_unique<DescriptorHeap>(device,
D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
1);
device->CreateDepthStencilView(depthStencil.Get(),
nullptr,
depthDescriptors->GetCPUDescriptorHandleForHeapStart());
auto rtvDescriptor = renderDescriptors->GetCpuHandle(RTDescriptors::SceneRT);
auto dsvDescriptor = depthDescriptors->GetCPUDescriptorHandleForHeapStart();
commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor);
Texture samplers can be statically defined within the DirectX 12 root signature, or provided on a descriptor heap. You can use DescriptorHeap
to create your own sampler descriptor heap, but you can also make use of CommonStates which provides common combinations of sampler state. When used in conjunction with DescriptorHeap
for the texture descriptors, the built-in effects expect drawing with the following heap settings:
ID3D12DescriptorHeap* heaps[] = { resourceDescriptors->Heap(), states->Heap() };
commandList->SetDescriptorHeaps(static_cast<UINT>(std::size(heaps)), heaps);
For a custom sampler heap:
samplerDescriptors = std::make_unique<DescriptorHeap>(device,
D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
32);
You can create as many heaps as you wish in your application, but remember that you can have only a single CBV/SRV/UAV descriptor heap and a single sampler descriptor heap active at a given time.
In addition to operations that utilize the CPU or GPU handle to a descriptor, the WriteDescriptors method can be used to write data directly into a descriptor or range of descriptors, typically copying from a existing set of descriptors.
D3D12_GPU_DESCRIPTOR_HANDLE WriteDescriptors(ID3D12Device* device,
uint32_t offsetIntoHeap, uint32_t totalDescriptorCount,
const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts,
const uint32_t* pDescriptorRangeSizes,
uint32_t descriptorRangeCount);
D3D12_GPU_DESCRIPTOR_HANDLE WriteDescriptors(ID3D12Device* device,
uint32_t offsetIntoHeap, const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptorRangeStarts,
const uint32_t* pDescriptorRangeSizes, uint32_t descriptorRangeCount);
D3D12_GPU_DESCRIPTOR_HANDLE WriteDescriptors(ID3D12Device* device,
uint32_t offsetIntoHeap,
const D3D12_CPU_DESCRIPTOR_HANDLE* pDescriptors,
uint32_t descriptorCount);
In addition to the methods above, a descriptor heap has the following properties:
- GetFirstGpuHandle: Returns the first GPU handle in the heap
- GetFirstCpuHandle: Returns the first CPU handle in the heap
- GetGpuHandle: Returns a GPU handle given an index.
- GetCpuHandle: Returns a CPU handle given an index.
- Count: Returns the capacity of the heap.
- Flags: Returns the flags used to create the heap.
- Type: Returns the heap type.
- Increment: Returns the increment needed for computing handles.
- Heap: Returns a pointer to the underlying DirectX 12 heap object.
Creation of resources is fully asynchronous, so you can create many heaps at the same time.
All content and source code for this package are subject to the terms of the MIT License.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
- Universal Windows Platform apps
- Windows desktop apps
- Windows 11
- Windows 10
- Xbox One
- Xbox Series X|S
- x86
- x64
- ARM64
- Visual Studio 2022
- Visual Studio 2019 (16.11)
- clang/LLVM v12 - v18
- MinGW 12.2, 13.2
- CMake 3.20