what does exactly the function barrier do in GLSL?

52 views Asked by At

I am reading a small github project, within which there is a compute shader code to organize an index buffer of indirect draw call as follows,

layout(local_size_x=1024, local_size_y=1, local_size_z=1) in;

/* some stuffs */

void main()
{
    uint id = gl_GlobalInvocationID.x; //for grass blade

    if(id == 0)
    {
        atomicExchange(indirect[0], 0);
    }

    barrier();
    
    if(id < 10240)
    {
        /* do some stuffs like
        if(culled)
        {
            return;
        }
        */
    
        uint index = atomicAdd(indirect[0], 1);
        ind[index] = id;
    }
}

with a dispatch call as follows,

glDispatchCompute(11, 1, 1);

I am confused because as I learned from OpenGL Refpage,

For any given static instance of barrier in a compute shader, all invocations within a single work group must enter it before any are allowed to continue beyond it.

the barrier function only synchronize all invocations within a single work group, which, if I understand it correctly, says here only the 1024 * 1 * 1 invocations will synchronize with each other.

Since we dispatch 11 work groups here, there are 11 synchronizations within each group, though the order of executions between these 11 work groups is undefined.

Now assume that the invocation with id == 2048 run so fast that it executes

uint index = atomicAdd(indirect[0], 1);

before the invocation with id == 0 have executed

atomicExchange(indirect[0], 0);

( Again if I understand it correctly, this could happen because they are not in the same work group. So the barrier function cannot synchronize them.)

then the invocation with id == 2048 may reach an uninitialized value of indirect[0] ; Or even indirect[0] == 0 at the very first time, there will be a confliction ind[0] == 2048 and ind[0] == i != 2048 where i is the id of a certain invocation which is the first invocation to execute

uint index = atomicAdd(indirect[0], 1);

after

atomicExchange(indirect[0], 0);atomicExchange(indirect[0], 0);

has been executed.

I was wondering where did I go wrong.

Did I misunderstand the function barrier ? Maybe it synchronize globally all invocations with a dispatch?

Or Did I misunderstand the concept of work group?

0

There are 0 answers