directx-12 - How to use commandlist with multiple descriptor heaps?
Asked Answered
M

1

7

Currently going through microsofts examples, it is noticable, that only one cbv_srv_uav heap is used per commandlist (+ maybe on additional sampler heap).

Is it possible to use multiple heaps per CommandList?

So i setup heap and ranges

this->mRSVHeap = new urd::DescriptorHeap(
    *this->mDevice,
    urd::DescriptorHeapType::CBV_SRV_UAV,
    1, // shader visible
    2); // space for 2 descriptors (2 textures)

this->mConstHeap = new urd::DescriptorHeap(
    *this->mDevice,
    urd::DescriptorHeapType::CBV_SRV_UAV,
    1, // shader visible
    1); // space for 1 descriptor

urd::DescriptorRange ranges[3];
ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0); // first and second descriptor in rsv heap (t0, t1)
ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); // first descriptor in cbv heap (b0)
ranges[2].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2); // same texture used as first range (again first descriptor in rsv, accessable by t2)

after that i define the descriptor tables

rootParam[0].InitDescTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_PIXEL);
rootParam[1].InitDescTable(1, &ranges[1], D3D12_SHADER_VISIBILITY_ALL);
rootParam[2].InitDescTable(1, &ranges[2], D3D12_SHADER_VISIBILITY_PIXEL);

So i create shaderResourceViews for texture 1 and 2 at cpu offset 0 and 1 in rsv heap and a constantbufferview for the constant buffer at cpu offset 0 in the cbv heap

like this:

D3D12_CPU_DESCRIPTOR_HANDLE handle = this->ConstHeap->GetCPUDescriptorHandleForHeapStart();
handle.ptr += index * SIZE_OF_ONE_DESCRIPTOR_CBV_SRV_UAV_TYPE;
CreateConstantBufferView(&desc, handle)

now its time to tell the commandlist to reference those heaps

ID3D12DescriptorHeap* ppHeaps[] = { this->mRSVHeap.Get(), this->mConstHeap.Get() };
this->mCommandList->GetRef()->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);

after this, closing the commandlist always throws.

ThrowIfFailed(this->mCommandList->Close());

Here is how i tell the commandlist which heap for which table:

this->mCommandList->GetRef()->SetGraphicsRootDescriptorTable(0, this->mRSVHeap->GetGPUHeapAddressAtOffset(0));
this->mCommandList->GetRef()->SetGraphicsRootDescriptorTable(1, this->mConstHeap->GetGPUHeapAddressAtOffset(0));
this->mCommandList->GetRef()->SetGraphicsRootDescriptorTable(2, this->mRSVHeap->GetGPUHeapAddressAtOffset(0));

It works fine if i describe all the objects into one single descriptor heap (like in the examples) and just use different offsets of that heap.

Debug Output:

D3D12 ERROR: ID3D12CommandList::SetDescriptorHeaps: pDescriptorHeaps[1] sets a descriptor heap type that appears earlier in the pDescriptorHeaps array. Only one of any given descriptor heap type can be set at a time. [ EXECUTION ERROR #554: SET_DESCRIPTOR_HEAP_INVALID] D3D12 ERROR: CCommandList::SetGraphicsRootDescriptorTable: No CBV_SRV_UAV descriptor heap is currently set on the command list so setting a root descriptor table of CBV_SRV_UAV handles is invalid. [ EXECUTION ERROR #708: SET_DESCRIPTOR_TABLE_INVALID] D3D12 ERROR: CCommandList::SetGraphicsRootDescriptorTable: No CBV_SRV_UAV descriptor heap is currently set on the command list so setting a root descriptor table of CBV_SRV_UAV handles is invalid. [ EXECUTION ERROR #708: SET_DESCRIPTOR_TABLE_INVALID] D3D12 ERROR: CCommandList::SetGraphicsRootDescriptorTable: No CBV_SRV_UAV descriptor heap is currently set on the command list so setting a root descriptor table of CBV_SRV_UAV handles is invalid. [ EXECUTION ERROR #708: SET_DESCRIPTOR_TABLE_INVALID]

Malina answered 20/8, 2015 at 9:12 Comment(5)
Have you enabled the debug layer so that you get a human readable error for what you've done wrong? Look for references to 'D3D12GetDebugInterface' in the samples.Gilgamesh
yes i did, updated op with debug output. So this seems to answer my question . !!Only one of any given descriptor heap type can be set at a time.!!Malina
Only one of any given heap can be set at one time, yes, but not throughout the command list. You're free to change the heaps within the command list, just not multiple CBV/SRV/UAV heaps (or sampler heaps) in the same call.Gilgamesh
thanks for the clarification.Malina
maybe you should post the answer and get your deserved points.Malina
G
11

The restriction is that only one heap of each type (CBV/SRV/UAV and Samplers) may be set at any one time. Thus only two descriptor heaps can ever be set at one time.

However, it's important to note that the descriptor heaps set may vary during a command list.

Gilgamesh answered 21/8, 2015 at 16:38 Comment(1)
It is not recommended to change the descriptor heaps inside a command list has it may have strong performance penalty on some hardware. The correct way is to allocate a large heap, and copy descriptors from non shader visible heap to it on demand.Quinsy

© 2022 - 2024 — McMap. All rights reserved.