计算着色器中的 imageStore 问题

Problem with imageStore in compute shader

我有一个非常简单的计算着色器的问题,它只是使用 imageStore 复制纹理。

#define KS 16 // kernel size
layout (local_size_x = KS, local_size_y = KS) in;

layout(location = 0) uniform sampler2D u_inputTex;
layout(location = 1) uniform writeonly image2D u_outImg;

void main()
{
    const ivec2 gid = ivec2(gl_WorkGroupID.xy);
    const ivec2 tid = ivec2(gl_LocalInvocationID.xy);
    const ivec2 pixelPos = ivec2(KS) * gid + tid;

    imageStore(u_outImg, pixelPos,
        uvec4(255.0 * texelFetch(u_inputTex, pixelPos, 0).rgb, 255u));
}

在 C++ 方面,我有这个:

int w, h;
u32 inTex = -1;
{
    int nc;
    auto img = stbi_load("imgs/Windmill_NOAA.png", &w, &h, &nc, 3);
        
    if (img) {
        glGenTextures(1, &inTex);
        glBindTexture(GL_TEXTURE_2D, inTex);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        stbi_image_free(img);
    }
    else
        printf("Error loading img\n");
}

u32 outTex;
{
    glGenTextures(1, &outTex);
    glBindTexture(GL_TEXTURE_2D, outTex);
    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, w, h);
}

u32 compProg = easyCreateComputeShaderProg("compute", shader_srcs::computeSrc);
glUseProgram(compProg);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, inTex);
glBindImageTexture(0, outTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI);
glUniform1i(0, 0);
glUniform1i(1, 0);

glDispatchCompute((w+15)/16, (h+15)/16, 1);

glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); // make sure the output image has been written
    
u8* img = new u8[w * h * 4];
glBindTexture(GL_TEXTURE_2D, outTex);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, img);
stbi_write_png("imgs/out.png", w, h, 1, img, w*4);
delete[] img;

输入图像如下所示:

但这是我在输出图像中得到的:

我进一步简化了着色器:我不从输入纹理读取,而是写入一个固定值:

    imageStore(u_outImg, pixelPos,
        //uvec4(255.0 * texelFetch(u_inputTex, pixelPos, 0).rgb, 255u));
        uvec4(1u));

我注意到:

我也这样试过,但也没用:

    imageStore(u_outImg, pixelPos,
        vec4(texelFetch(u_inputTex, pixelPos, 0).rgb, 255u));

我做错了什么?我的最终目标是制作一个 prostprocessing 过滤器,但我无法让它工作,所以我试图让它尽可能简单,但它不起作用。

最小示例回购:https://github.com/tuket/Whosebug_image_store_problem

glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, w, h);

如果要使用非规范化无符号整数图像,必须在sahder中将其声明为uimage2Dimage2D 仅适用于 floating-point 或规范化整数(范围 [0,1])。

glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

那是错误的记忆障碍。屏障是关于你将如何访问你的着色器修改的资源在屏障之后,所以正确的是:

GL_TEXTURE_UPDATE_BARRIER_BIT

reference page 中解释为(强调我的):

Writes to a texture via glTex(Sub)Image*, glCopyTex(Sub)Image*, glCompressedTex(Sub)Image*, and reads via glGetTexImage after the barrier will reflect data written by shaders prior to the barrier. Additionally, texture writes from these commands issued after the barrier will not execute until all shader writes initiated prior to the barrier complete.