Por que barreira sincroniza a memória compartilhada quando o memoryBarrier não faz?

O seguinte sombreador de computação GLSL simplesmente copiainImage paraoutImage. É derivado de um passe de pós-processamento mais complexo.

Nas primeiras várias linhas demain(), um único thread carrega 64 pixels de dados no array compartilhado. Em seguida, após a sincronização, cada um dos 64 segmentos grava um pixel na imagem de saída.

Dependendo de como sincronizo, obtenho resultados diferentes. Eu originalmente penseimemoryBarrierShared() seria a chamada correta, mas produz o seguinte resultado:

que é o mesmo resultado de não ter sincronização ou usarmemoryBarrier() em vez de.

Se eu usarbarrier(), Recebo o seguinte resultado (desejado):

A distribuição tem 32 pixels de largura e, se eu alterar o tamanho do grupo de trabalho para algo menor ou igual a 32, obtenho resultados corretos.

Oque esta acontecendo aqui? Eu estou entendendo errado o propósito dememoryBarrierShared()? Porque deveriabarrier() trabalhos?

#version 430

#define SIZE 64

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

layout(rgba32f) uniform readonly  image2D inImage;
uniform writeonly image2D outImage;

shared vec4 shared_data[SIZE];

void main() {
    ivec2 base = ivec2(gl_WorkGroupID.xy * gl_WorkGroupSize.xy);
    ivec2 my_index = base + ivec2(gl_LocalInvocationID.x,0);

    if (gl_LocalInvocationID.x == 0) {
        for (int i = 0; i < SIZE; i++) {
            shared_data[i] = imageLoad(inImage, base + ivec2(i,0));
        }
    }

    // with no synchronization:   stripes
    // memoryBarrier();        // stripes
    // memoryBarrierShared();  // stripes
    // barrier();              // works

    imageStore(outImage, my_index, shared_data[gl_LocalInvocationID.x]);
}

questionAnswers(1)

yourAnswerToTheQuestion