14

以下 GLSL 计算着色器简单地复制inImageoutImage. 它源自更复杂的后处理过程。

在前几行中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]);
}
4

1 回答 1

25
于 2013-07-02T17:13:59.543 回答