Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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]

like image 621
Raphael Mayer Avatar asked Aug 20 '15 09:08

Raphael Mayer


1 Answers

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.

like image 188
Adam Miles Avatar answered Sep 23 '22 05:09

Adam Miles