【问题标题】:UAV counter indices used across multiple shaders?跨多个着色器使用的无人机计数器索引?
【发布时间】:2013-06-18 12:26:05
【问题描述】:

我一直在尝试实现一个基于计算着色器的粒子系统。

我有一个计算着色器,它使用带有 D3D11_BUFFER_UAV_FLAG_COUNTER 标志的 UAV 构建粒子的结构化缓冲区。

当我添加到这个缓冲区时,我会检查这个粒子是否有任何复杂的行为,我想过滤掉这些行为并在单独的计算着色器中执行。例如,如果粒子想要执行碰撞检测,我将其索引添加到另一个结构化缓冲区,也带有 D3D11_BUFFER_UAV_FLAG_COUNTER 标志。

然后我运行第二个计算着色器,它处理所有索引,并对这些粒子应用碰撞检测。

但是,在第二个计算着色器中,我估计大约 5% 的索引是错误的 - 它们属于不支持碰撞检测的其他粒子。

这是执行列表构建的计算着色器代码:

// append to destination buffer
uint dstIndex = g_dstParticles.IncrementCounter();
g_dstParticles[ dstIndex ] = particle;

// add to behaviour lists
if ( params.flags & EMITTER_FLAG_COLLISION )
{
    uint behaviourIndex = g_behaviourCollisionIndices.IncrementCounter();
    g_behaviourCollisionIndices[ behaviourIndex ] = dstIndex;
}

如果我将“添加到行为列表”位拆分为单独的计算着色器,并在构建粒子列表后运行它,则一切正常。但是我认为我不应该这样做 - 再次通过所有粒子会浪费带宽。

我怀疑IncrementCounter 实际上并不能保证将唯一索引返回到 UAV,并且正在进行一些巧妙的优化,这意味着索引仅在使用它的计算着色器内有效。因此我的尝试将其传递给第二个计算着色器是无效的。

谁能对这里发生的事情给出任何具体的答案?如果有办法让我将过滤保持在与我的核心更新相同的计算着色器中?

谢谢!

【问题讨论】:

    标签: graphics hlsl directx-11 compute-shader


    【解决方案1】:

    IncrementCounter 是一个原子操作,因此(尽管存在驱动程序/硬件错误)将向调用它的每个线程返回一个唯一值。

    您是否考虑过为此使用追加/使用缓冲区,因为这是它们的设计目的?第一遍只是将复杂的碰撞粒子附加到 AppendStructuredBuffer 中,第二遍从同一个缓冲区消耗,但使用 ConsumeStructuredBuffer 视图。第二次运行计算将需要使用 DispatchIndirect,因此您只需运行列表中所需数量的线程组(CPU 不会知道)。

    但通常的建议仍然适用,您是否尝试过 D3D11 调试层并在参考设备上运行它以确保它不是驱动程序问题?

    【讨论】:

    • 感谢您提供的信息 - 这几乎就是我的想法。我在其他 2 个图形供应商的硬件上测试了代码,发现它在这些硬件上运行良好,所以它一定是我正在测试的硬件/驱动程序有问题。我已经向他们提交了错误报告和重现案例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 1970-01-01
    • 2012-12-14
    • 2021-12-01
    相关资源
    最近更新 更多