6

目前通过微软的例子,值得注意的是,每个命令列表只使用一个 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)

之后我定义描述符表

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());

这是我如何告诉命令列表哪个表对应哪个堆:

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:SET_DESCRIPTOR_HEAP_INVALID] D3D12 错误:CCommandList::SetGraphicsRootDescriptorTable:当前在命令列表中未设置 CBV_SRV_UAV 描述符堆,因此设置 CBV_SRV_UAV 句柄的根描述符表无效。[执行错误#708:SET_DESCRIPTOR_TABLE_INVALID] D3D12 错误:CCommandList::SetGraphicsRootDescriptorTable:当前在命令列表上未设置 CBV_SRV_UAV 描述符堆,因此设置 CBV_SRV_UAV 句柄的根描述符表无效。[执行错误 #708:SET_DESCRIPTOR_TABLE_INVALID] D3D12 错误:CCommandList::SetGraphicsRootDescriptorTable: 当前在命令列表上没有设置 CBV_SRV_UAV 描述符堆,因此设置 CBV_SRV_UAV 句柄的根描述符表是无效的。[执行错误#708:SET_DESCRIPTOR_TABLE_INVALID]

4

1 回答 1

10

限制是在任何时候只能设置每种类型(CBV/SRV/UAV 和采样器)的一个堆。因此,一次只能设置两个描述符堆。

但是,重要的是要注意,描述符堆集在命令列表期间可能会有所不同。

于 2015-08-21T16:38:39.943 回答