2014-10-28 124 views
2

我有一个D3D11缓冲区,其中有几百万个元素,应该保存R8G8B8A8_UNorm格式的数据。在HLSL中随机访问R8G8B8A8_UNorm格式的D3D11缓冲区

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

我最好猜测的是创建UnorderedAccessView格式的R8G8B8A8_UNorm格式。但是,我如何在HLSL中声明RWBuffer<?>,以及如何写入和读取它?是否需要手动申报RWBuffer<uint>并从vec4uint进行包装?

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

回答

2

由于存在很多不同的问题,这有点棘手,但你应该可以做这样的事情。

在你的着色器写入缓冲区声明:

RWBuffer<float4> WriteBuf : register(u1); 

注意,它必然要登记u1而不是u0。无序访问视图(UAV)必须从插槽1开始,因为u#寄存器也用于渲染目标。

要写入缓冲区只是这样做:

WriteBuf[0] = float4(0.5, 0.5, 0, 1); 

请注意,您必须立即写所有4个值。

在您的C++代码中,您必须创建一个无序的访问缓冲区,并将其绑定到无人机。您可以使用DXGI_FORMAT_R8G8B8A8_UNORM格式。当你向它写入4个浮点数时,这些值将被自动转换和打包。无人机可以使用OMSetRenderTargetsAndUnorderedAccessViews绑定到管道。

在着色器从缓冲区中读取声明只读缓存:

Buffer<float4> ReadBuf : register(t0); 

注意,这个缓冲区使用t0,因为它必将为着色器资源视图(SRV),而不是无人机。

访问缓冲区使用类似:

float4 val = ReadBuf[0]; 

在你的C++代码,你可以绑定前面创建的SRV,而不是一个UAV相同的缓冲区。 SRV可以使用PSSetShaderResources绑定到管道,也可以使用DXGI_FORMAT_R8G8B8A8_UNORM创建。

无法同时使用相同的缓冲区同时绑定SRV和UAV。所以你必须先绑定无人机并运行你的第一个着色器通行证。然后解除绑定UAV,绑定SRV,并运行第二个着色器通道。

也有其他方法可以做到这一点。请注意,所有这些都需要着色器模型5。

+0

非常感谢!它完美的作品:) 一个小的后续问题:我没有指定任何“寄存器”编程的东西,它仍然工作(请注意,我使用了效果框架)。指定它们有什么意义? – chafner 2014-10-31 09:01:00

+1

如果不指定寄存器,则只在编译着色器时自动分配寄存器。明确指定它们只会让您更好地控制它们的位置,如果您在绑定来自C++的数据时需要它,这将非常有用。这对于Effects框架来说可能不那么重要,因为您可以通过名称来抓取所有内容。如果没有Effects框架,你可以通过寄存器槽号来在C++中绑定事物(除非你使用了着色器反射来模仿Effects框架)。 – megadan 2014-10-31 18:01:39