如何在计算着色器中对SSBO使用原子操作

时间:2017-12-05 20:17:06

标签: opengl glsl gpu-atomics

示例代码

这是一个简单的计算着色器来说明我的问题

layout(local_size_x = 64) in;

// Persistent LIFO structure with a count of elements
layout(std430, binding = 0) restrict buffer SMyBuffer
{
    int count;
    float data[];
} MyBuffer;

bool AddDataElement(uint i);
float ComputeDataElement(uint i);

void main()
{
    for (uint i = gl_GlobalInvocationID.x; i < some_end_condition; i += gl_WorkGroupSize.x)
    {
        if (AddDataElement(i))
        {
            // We want to store this data piece in the next available free space
            uint dataIndex = atomicAdd(MyBuffer.count, 1);
            // [1] memoryBarrierBuffer() ?
            MyBuffer.data[dataIndex] = ComputeDataElement(i);
        }
    }
}

说明

SMyBuffer是一堆元素(data[]),其元素的当前数量为count。当满足某个条件时,计算着色器会自动递增计数。此操作返回先前的索引,该索引用于索引data[]以存储新元素。这保证了没有两个着色器调用会覆盖彼此的元素。

另一个计算着色器最终会从此堆栈中弹出值并使用它们。当然,在两个计算着色器调度之间需要glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)

问题

所有这一切都运行良好,但我想知道我是否只是幸运时间,我想验证我对API的使用。

那么,还需要确保存储在SSBO中的计数器有效吗(参见1)?我期待atomicAdd()处理内存同步,因为否则它没有意义。什么是原子操作的意义,其效果只在单个线程中可见?

关于记忆障碍,OpenGL wiki states

  

请注意,原子计数器在功能上与原子图像/缓冲区变量操作不同。后者仍然需要连贯的限定词,障碍等。

这让我想知道是否有一些我没有正确理解的东西,实际上需要memoryBarrierBuffer()。但是如果是这样的话,那么在其中一个线程进入后续atomicAdd()之前阻止两个线程执行memoryBarrierBuffer()是什么?

此外,答案是否会改变glDispatchCompute()是否调度单个工作组?

0 个答案:

没有答案