0

我正在使用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 个......非常感谢任何帮助!

谢谢!

4

0 回答 0