C++ directx-12-如何将commandlist与多个描述符堆一起使用?
目前通过微软的例子,可以注意到,每个commandlist只使用一个cbv_srv_uav堆(+可能在额外的采样器堆上) 每个CommandList可以使用多个堆吗 所以我设置了堆和范围C++ directx-12-如何将commandlist与多个描述符堆一起使用?,c++,heap,direct3d,descriptor,directx-12,C++,Heap,Direct3d,Descriptor,Directx 12,目前通过微软的例子,可以注意到,每个commandlist只使用一个cbv_srv_uav堆(+可能在额外的采样器堆上) 每个CommandList可以使用多个堆吗 所以我设置了堆和范围 this->mRSVHeap = new urd::DescriptorHeap( *this->mDevice, urd::DescriptorHeapType::CBV_SRV_UAV, 1, // shader visible 2); // space for
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)
然后我定义描述符表
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创建ShaderResourceView,在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)
现在是时候告诉commandlist引用这些堆了
ID3D12DescriptorHeap* ppHeaps[] = { this->mRSVHeap.Get(), this->mConstHeap.Get() };
this->mCommandList->GetRef()->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
在此之后,关闭commandlist总是抛出
ThrowIfFailed(this->mCommandList->Close());
下面是我如何告诉commandlist哪个表的哪个堆:
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错误:ID3D12CommandList::SetDescriptorHeaps:pDescriptorHeaps[1]设置了在pDescriptorHeaps数组中较早出现的描述符堆类型。一次只能设置任何给定描述符堆类型中的一种。[执行错误#554:设置_描述符_堆_无效]
D3D12错误:CCommandList::SetGraphicsRootDescriptorTable:命令列表上当前未设置CBV_SRV_UAV描述符堆,因此设置CBV_SRV_UAV句柄的根描述符表无效。[执行错误#708:设置_描述符_表_无效]
D3D12错误:CCommandList::SetGraphicsRootDescriptorTable:命令列表上当前未设置CBV_SRV_UAV描述符堆,因此设置CBV_SRV_UAV句柄的根描述符表无效。[执行错误#708:设置_描述符_表_无效]
D3D12错误:CCommandList::SetGraphicsRootDescriptorTable:命令列表上当前未设置CBV_SRV_UAV描述符堆,因此设置CBV_SRV_UAV句柄的根描述符表无效。[执行错误#708:设置_描述符_表_无效]
限制是每次只能设置每种类型(CBV/SRV/UAV和采样器)的一个堆。因此,一次只能设置两个描述符堆
但是,需要注意的是,描述符堆集在命令列表中可能会有所不同。您是否启用了调试层,以便为您所做的错误获得一个人类可读的错误?在示例中查找对“D3D12GetDebugInterface”的引用。是的,我使用调试输出更新了op。这似乎回答了我的问题!!一次只能设置任何给定描述符堆类型中的一种。!!一次只能设置任何给定堆中的一个,是的,但不能在整个命令列表中设置。您可以自由更改命令列表中的堆,但不能更改多个CBV/SRV/UAV堆(或采样器堆)在同一个电话中。感谢您的澄清。也许您应该发布答案并获得您应得的分数。不建议更改命令列表中的描述符堆,因为它可能会对某些硬件造成严重的性能损失。正确的方法是分配一个大堆,并根据需要将描述符从非着色器可见堆复制到它。