我有一个包含几百万个元素的 D3D11 缓冲区,该缓冲区应该保存 R8G8B8A8_UNorm
中的数据。格式。
所需的行为如下:一个着色器计算 vec4
并以随机访问模式将其写入缓冲区。在下一个 channel 中,另一个着色器以随机访问模式读取数据并进一步处理它们。
我最好的猜测是创建一个 UnorderedAccessView
与 R8G8B8A8_UNorm
格式。但我如何声明 RWBuffer<?>
在 HLSL 中,如何写入和读取?是否有必要声明为RWBuffer<uint>
并从 vec4
进行包装至uint
手动?
在 OpenGL 中,我将创建一个缓冲区和一个缓冲区纹理。然后我可以声明 imageBuffer
与 rgba8
在着色器中格式化,通过 imageLoad
访问它和imageStore
,硬件为我完成所有转换。这在 D3D11 中可能吗?
最佳答案
由于有很多不同的问题,这有点棘手,但你应该能够做这样的事情。
在写入缓冲区的着色器中声明:
RWBuffer<float4> WriteBuf : register( u1 );
请注意,它必须注册 u1
而不是 u0
。无序访问 View (UAV) 必须从插槽 1 开始,因为 u#
寄存器也用于渲染目标。
要写入缓冲区,只需执行以下操作:
WriteBuf[0] = float4(0.5, 0.5, 0, 1);
请注意,您必须一次写入所有 4 个值。
在您的 C++ 代码中,您必须创建一个无序访问缓冲区,并将其绑定(bind)到无人机。您可以使用DXGI_FORMAT_R8G8B8A8_UNORM
格式。当您向其中写入 4 个 float 时,这些值将自动转换并打包。可以使用 OMSetRenderTargetsAndUnorderedAccessViews 将无人机绑定(bind)到管道。
在从缓冲区读取的着色器中声明一个只读缓冲区:
Buffer<float4> ReadBuf : register( t0 );
请注意,此缓冲区使用 t0
,因为它将绑定(bind)为着色器资源 View (SRV) 而不是 UAV。
要访问缓冲区,请使用以下内容:
float4 val = ReadBuf[0];
在您的 C++ 代码中,您可以将之前创建的相同缓冲区绑定(bind)到 SRV 而不是 UAV。 SRV 可以使用 PSSetShaderResources
绑定(bind)到管道,也可以使用 DXGI_FORMAT_R8G8B8A8_UNORM
创建。
您不能同时将使用相同缓冲区的 SRV 和 UAV 绑定(bind)到管道。因此,您必须首先绑定(bind)无人机并运行第一个着色器 channel 。然后解除无人机的绑定(bind),绑定(bind)SRV,并运行第二个着色器 channel 。
可能还有其他方法可以做到这一点。请注意,所有这些都需要着色器模型 5。
关于directx - 在 HLSL 中随机访问 R8G8B8A8_UNorm 格式的 D3D11 缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26611274/