【问题标题】:Random access to D3D11 buffer with R8G8B8A8_UNorm format in HLSL随机访问 HLSL 中 R8G8B8A8_UNorm 格式的 D3D11 缓冲区
【发布时间】:2014-10-31 01:27:56
【问题描述】:

我有一个包含几百万个元素的 D3D11 缓冲区,它应该以 R8G8B8A8_UNorm 格式保存数据。

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

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

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

【问题讨论】:

    标签: directx directx-11 hlsl


    【解决方案1】:

    由于有很多不同的陷阱,这有点棘手,但你应该能够做这样的事情。

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

    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,运行第二个 shader pass。

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

    【讨论】:

    • 非常感谢!它工作得很好:) 一个小的后续问题:我在没有指定任何“寄存器”的情况下编写了这个东西,但它仍然可以工作(注意我使用了效果框架)。指定它们有什么意义?
    • 如果不指定寄存器,它们只是在编译着色器时自动分配。显式指定它们只会让您更好地控制它们的去向,如果您在从 C++ 绑定数据时需要它,这很有用。对于 Effects 框架,它可能不那么重要,因为您可以按名称获取所有内容。如果没有 Effects 框架,您可以通过寄存器槽号在 C++ 中绑定内容(除非您使用着色器反射来模仿 Effects 框架)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    • 2022-01-13
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多