directx-12 - 如何使用具有多个描述符堆的命令列表?
directx-12 - How to use commandlist with multiple descriptor heaps?
目前正在浏览微软示例,值得注意的是,每个命令列表仅使用一个 cbv_srv_uav 堆(+ 可能在额外的采样器堆上)。
是否可以为每个 CommandList 使用多个堆?
所以我设置了堆和范围
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)
之后我定义描述符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);
所以我在 rsv 堆中的 cpu 偏移量 0 和 1 处为纹理 1 和 2 创建 shaderResourceViews,并在 cbv 堆中的 cpu 偏移量 0 处为常量缓冲区创建一个 constantbufferview
像这样:
D3D12_CPU_DESCRIPTOR_HANDLE handle = this->ConstHeap->GetCPUDescriptorHandleForHeapStart();
handle.ptr += index * SIZE_OF_ONE_DESCRIPTOR_CBV_SRV_UAV_TYPE;
CreateConstantBufferView(&desc, handle)
现在是告诉命令列表引用这些堆的时候了
ID3D12DescriptorHeap* ppHeaps[] = { this->mRSVHeap.Get(), this->mConstHeap.Get() };
this->mCommandList->GetRef()->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
在此之后,关闭命令列表总是会抛出异常。
ThrowIfFailed(this->mCommandList->Close());
这是我如何告诉命令列表哪个堆用于哪个 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));
如果我将所有对象描述到一个描述符堆中(就像在示例中那样)并且只使用该堆的不同偏移量,它就可以正常工作。
调试输出:
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]
限制是每次只能设置一个堆(CBV/SRV/UAV 和采样器)。因此一次只能设置两个描述符堆。
但是,请务必注意描述符堆集在命令列表期间可能会有所不同。
目前正在浏览微软示例,值得注意的是,每个命令列表仅使用一个 cbv_srv_uav 堆(+ 可能在额外的采样器堆上)。
是否可以为每个 CommandList 使用多个堆?
所以我设置了堆和范围
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)
之后我定义描述符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);
所以我在 rsv 堆中的 cpu 偏移量 0 和 1 处为纹理 1 和 2 创建 shaderResourceViews,并在 cbv 堆中的 cpu 偏移量 0 处为常量缓冲区创建一个 constantbufferview
像这样:
D3D12_CPU_DESCRIPTOR_HANDLE handle = this->ConstHeap->GetCPUDescriptorHandleForHeapStart();
handle.ptr += index * SIZE_OF_ONE_DESCRIPTOR_CBV_SRV_UAV_TYPE;
CreateConstantBufferView(&desc, handle)
现在是告诉命令列表引用这些堆的时候了
ID3D12DescriptorHeap* ppHeaps[] = { this->mRSVHeap.Get(), this->mConstHeap.Get() };
this->mCommandList->GetRef()->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
在此之后,关闭命令列表总是会抛出异常。
ThrowIfFailed(this->mCommandList->Close());
这是我如何告诉命令列表哪个堆用于哪个 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));
如果我将所有对象描述到一个描述符堆中(就像在示例中那样)并且只使用该堆的不同偏移量,它就可以正常工作。
调试输出:
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]
限制是每次只能设置一个堆(CBV/SRV/UAV 和采样器)。因此一次只能设置两个描述符堆。
但是,请务必注意描述符堆集在命令列表期间可能会有所不同。