结构化缓冲区资源
以下示例展示了如何通过HLSL来定义结构化缓冲区
struct Data
{
float3 v1;
float3 v2;
};
StructuredBuffer<Data> gInputA : register(t0);
StructuredBuffer<Data> glnputB : register(t1);
RWStructuredBuffer<Data> gOutput : register(u0);
结构化缓冲区是一种由相同类型元素所构成的简单缓冲区——其本质上是一种数组。正如我们所看到的,该元素类型可以是用户以HLSL定义的结构体。
我们可以把为顶点缓冲区与索引缓冲区创建SRV的方法同样用于创建结构化缓冲区的SRV。除了“必 须指定D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS 标志“这一条之外,将结构化缓冲区用作UAV也与之前的操作基本一致。设置此标志的目的是用于把资源转换为D3D12_RESOURCE_ STATE_UNORDERED_ACCESS 状态。
struct Data
{
XMFLOAT3 vl;
XMFLOAT2 v2;
};
//生成一些数据来填充SRV缓冲区
std::vector<Data> dataA(NumDataElements);
std::vector<Data> dataB(NumDataElements);
for(int i = 0; i < NumDataElements; ++i)
{
dataA[i].v1=XMFLOAT3 (i,i,i);
dataA[i].v2=XMFLOAT2 (i,0);
dataB[i].v1=XMFLOAT3 (-i,i,0.0f);
dataB[i].v2=XMFLOAT2 (0,-i);
}
UINT64 byteSize = dataA.size()*sizeof(Data);
//创建若干缓冲区用作SRV
mlnputBufferA = d3dUtil::CreateDefaultBuffer(
md3dDevice.Get(),
mCommandList.Get(),
dataA.data(),
byteSize,
mlnputUploadBufferA);
mlnputBufferB = d3dUtil::CreateDefaultBuffer(
md3dDevice.Get(),
mCommandList.Get(),
dataB.data(),
byteSize,
mlnputUploadBufferB);
//创建用作UAV的缓冲区
ThrowlfFailed(md3dDevice->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3DI2_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(byteSize,
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS),
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
IID_PPV_ARGS(&mOutputBuffer)));
结构化缓冲区可以像纹理那样与流水线相绑定。我们为它们创建SRV或UAV的描述符,再将这些 描述符作为参数传入需要获取描述符表的根参数。或者,我们还能定义以根描述符为参数的根签名,由此便可以将资源的虚拟地址作为根参数直接进行传递,而无须涉及描述符堆(这种方式仅限于创建缓冲 区资源的SRV或UAV,并不适用于纹理)。考虑下列的根签名描述:
//根参数可以是描述符表、根描述符或根常量
CD3DX12_ROOT_PARAMETER slotRootParameter[3];
//性能优化小提示:按变更频率由高到低的顺序来填充根参数
slotRootParameter[0].InitAsShaderResourceView(0);
slotRootParameter[1].InitAsShaderResourceView(1);
slotRootParameter[2].InitAsUnorderedAccessView(0);
//根签名由一系列根参数所构成
CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(3, slotRootParameter,0, nullptr,
D3D12_ROOT_SIGNATURE_FLAG_NONE);
接下来,我们就能绑定所创建的缓冲区以供分派调用使用:
mCommanciList->SetComputeRootSignature (mRootSignature . Get ());
mCommandList->SetComputeRootShaderReSourceView(0,mlnputBufferA->GetGPUVirtualAddress());
mCommandList->SetComputeRootShaderReSourceView(1, mlnputBufferB->GetGPUVirtualAddress());
mCommandList->SetComputeRootUnorderedAccessView(2,mOutputBuffer->GetGPUVirtualAddress());
mCommandList->Dispatch(1, 1, 1);