Следующий графический шейдер 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]);
}