在HLSL中使用R8G8B8A8_UNorm格式随机访问D3D11缓冲区

时间:2014-10-28 14:46:10

标签: directx directx-11 hlsl

我有一个带有几百万个元素的D3D11缓冲区,它应该以{{1​​}}格式保存数据。

所需的行为如下:一个着色器计算R8G8B8A8_UNorm并以随机访问模式将其写入缓冲区。在下一个过程中,另一个着色器以随机访问模式读取数据并进一步处理它们。

我最好的猜测是使用vec4格式创建UnorderedAccessView。但是如何在HLSL中声明R8G8B8A8_UNorm,以及如何写入和读取它?是否有必要将其声明为RWBuffer<?>并手动执行从RWBuffer<uint>vec4的打包?

在OpenGL中,我会创建一个缓冲区和缓冲区纹理。然后,我可以在着色器中使用uint格式声明imageBuffer,使用rgba8imageLoad访问它,硬件会为我完成所有转换。这在D3D11中是否可行?

1 个答案:

答案 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。