我有一个带有几百万个元素的D3D11缓冲区,它应该以{{1}}格式保存数据。
所需的行为如下:一个着色器计算R8G8B8A8_UNorm
并以随机访问模式将其写入缓冲区。在下一个过程中,另一个着色器以随机访问模式读取数据并进一步处理它们。
我最好的猜测是使用vec4
格式创建UnorderedAccessView
。但是如何在HLSL中声明R8G8B8A8_UNorm
,以及如何写入和读取它?是否有必要将其声明为RWBuffer<?>
并手动执行从RWBuffer<uint>
到vec4
的打包?
在OpenGL中,我会创建一个缓冲区和缓冲区纹理。然后,我可以在着色器中使用uint
格式声明imageBuffer
,使用rgba8
和imageLoad
访问它,硬件会为我完成所有转换。这在D3D11中是否可行?
答案 0 :(得分:3)
由于存在许多不同的问题,这有点棘手,但你应该可以做这样的事情。
在写入缓冲区的着色器中声明:
RWBuffer<float4> WriteBuf : register( u1 );
请注意,必须注册u1
而不是u0
。无序访问视图(UAV)必须从插槽1开始,因为u#
寄存器也用于渲染目标。
要写入缓冲区,请执行以下操作:
WriteBuf[0] = float4(0.5, 0.5, 0, 1);
请注意,您必须一次写入所有4个值。
在C ++代码中,您必须创建一个无序访问缓冲区,并将其绑定到UAV。您可以使用DXGI_FORMAT_R8G8B8A8_UNORM
格式。当您向其写入4个浮点数时,这些值将自动转换和打包。可以使用OMSetRenderTargetsAndUnorderedAccessViews
将无人机绑定到管道。
在着色器中,从缓冲区读取声明只读缓冲区:
Buffer<float4> ReadBuf : register( t0 );
请注意,此缓冲区使用t0
,因为它将被绑定为着色器资源视图(SRV)而非UAV。
要访问缓冲区,请使用以下内容:
float4 val = ReadBuf[0];
在C ++代码中,您可以将先前创建的相同缓冲区绑定到SRV而不是UAV。 SRV可以使用PSSetShaderResources
绑定到管道,也可以使用DXGI_FORMAT_R8G8B8A8_UNORM
创建。
您不能同时使用相同的缓冲区将SRV和UAV绑定到管道。因此,您必须首先绑定UAV并运行第一个着色器通道。然后取消绑定UAV,绑定SRV,并运行第二个着色器传递。
也可能有其他方法可以做到这一点。请注意,所有这些都需要着色器模型5。