¿Por qué la barrera sincroniza la memoria compartida cuando memoryBarrier no lo hace?

El siguiente compilador shader GLSL simplemente copiainImage aoutImage. Se deriva de un pase de post-procesamiento más complejo.

En las primeras líneas demain(), un solo hilo carga 64 píxeles de datos en la matriz compartida. Luego, después de la sincronización, cada uno de los 64 hilos escribe un píxel en la imagen de salida.

Dependiendo de cómo sincronizo, obtengo diferentes resultados. Originalmente pensémemoryBarrierShared() Sería la llamada correcta, pero produce el siguiente resultado:

que es el mismo resultado que no tener sincronización o usarmemoryBarrier() en lugar.

Si yo usobarrier(), Obtengo el siguiente resultado (deseado):

La franja tiene 32 píxeles de ancho, y si cambio el tamaño del grupo de trabajo a algo menor o igual a 32, obtengo los resultados correctos.

¿Que está pasando aqui? ¿Estoy malinterpretando el propósito dememoryBarrierShared()? Porque deberiabarrier() ¿trabajo?

#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]);
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta