我正在使用vvvv中的 directx11 计算着色器实现计数排序算法(用于 3D 空间中的粒子),图形编程环境(只有着色器以文本形式编写,其余(渲染器、缓冲区等)通过连接节点完成,因此更难在这里分享......)。
我已经成功地将我的空间划分为单元格,计算了每个单元格的粒子数量,并创建了单元格计数的前缀总和/包含扫描。在最后一步中,我首先将前缀和缓冲区复制到 RWStructuredBuffer 中,如下所示:
StructuredBuffer<uint> InputBuffer;
RWStructuredBuffer<uint> Prefix : PREFIXBUFFER;
[numthreads(1,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
if (tid.x >= elementCount)
return;
Prefix[tid.x] = InputBuffer[tid.x];
}
(请注意,上述步骤可能特定于我的环境,因为我没有看到任何其他选项可以使此缓冲区在以下着色器中可写)
然后,对于每个粒子的单元格,我正在查找前缀和缓冲区的值,将其用作相应粒子在输出缓冲区中的索引位置,然后将前缀和缓冲区增加 1:
StructuredBuffer<particleID> ParticleIDs;
RWStructuredBuffer<uint> Prefix : PREFIXBUFFER;
RWStructuredBuffer<particleID> ResultBuffer : RESULTBUFFER;
[numthreads(64,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
if (tid.x >= elementCount)
return;
particleID partID = ParticleIDs[tid.x];
uint oldval;
InterlockedAdd(Prefix[partID.cellID],1,oldval);
ResultBuffer[oldval] = partID;
}
我在这里使用的粒子结构看起来像这样并且是预先计算的:
struct particleID
{
uint pID; //particleID
uint cellID;
};
不幸的是,这不起作用。生成的缓冲区似乎具有正常的 cellID,但在使用固定粒子位置进行测试时,pID 会闪烁。
我真的没有原子函数的经验,但在几步之前,当计算每个细胞的粒子时,我正在做一件非常相似的事情:
首先,我将计数器重置为 0:
RWStructuredBuffer<uint> OutputBuffer : BACKBUFFER;
[numthreads(1,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
OutputBuffer[tid.x] = 0;
}
然后我这样数:
StructuredBuffer<particleID> ParticleIDs;
RWStructuredBuffer<uint> OutputBuffer : BACKBUFFER;
[numthreads(64,1,1)]
void CS(uint3 tid : SV_DispatchThreadID)
{
if (tid.x >= elementCount)
return;
uint oldval;
InterlockedAdd(OutputBuffer[ParticleIDs[tid.x].cellID],1,oldval);
}
这工作正常。我没有看到这里的区别,除了我使用 2 个我正在写入的缓冲区而不是 1 个......非常感谢任何帮助!
谢谢!