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