Почему барьер синхронизирует разделяемую память, а memoryBarrier - нет?

Следующий GLSL вычислительный шейдер просто копируетinImage вoutImage, Он получен из более сложного этапа последующей обработки.

В первых нескольких строчкахmain()один поток загружает 64 пикселя данных в общий массив. Затем после синхронизации каждый из 64 потоков записывает один пиксель в выходное изображение.

В зависимости от того, как я синхронизируюсь, я получаю разные результаты. Я изначально думалmemoryBarrierShared() будет правильным вызовом, но он даст следующий результат:

что является тем же результатом, что отсутствие синхронизации или использованиеmemoryBarrier() вместо.

Если я используюbarrier()Я получаю следующий (желаемый) результат:

Ширина чередования составляет 32 пикселя, и если я изменю размер рабочей группы на значение, меньшее или равное 32, я получу правильные результаты.

Что тут происходит? Я неправильно понимаю цельmemoryBarrierShared()? Почему следуетbarrier() работай?

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

Ответы на вопрос(1)

Ваш ответ на вопрос