计算着色器中的imageStore出现问题

rpppsulh  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(219)

我有一个问题,一个非常简单的计算着色器,只是复制一个纹理使用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));

我已经注意到:

  • 如果我写0它就全黑了
  • 如果我写255它就全是白色的
  • 但是如果我在中间写一些东西(比如100),它就不是灰色的,而是白色的

我也试过这样做,但也没有成功:

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

我做错了什么?我的最终目标是做一个前列腺处理过滤器,但我不能让它工作,所以我试图使它尽可能简单,但它不工作。
最小示例存储库:https://github.com/tuket/stackoverflow_image_store_problem

8iwquhpp

8iwquhpp1#

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

如果要使用 unnormalized unsigned integer图像,则必须在sahder中将其声明为uimage2Dimage2D仅适用于浮点数或正规化整数(范围[0,1])。

glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

这是一个错误的内存障碍。这个障碍是关于如何访问由着色器修改的资源,障碍之后,所以正确的是:
GL_TEXTURE_UPDATE_BARRIER_BIT
这在reference page中被解释为(强调我):
在屏障之后通过glTex(Sub)Image*glCopyTex(Sub)Image*glCompressedTex(Sub)Image***写入纹理以及通过glGetTexImage读取纹理将反映屏障之前着色器写入的数据。**此外,在屏障之后发出的这些命令中的纹理写入将不会执行,直到屏障之前启动的所有着色器写入完成。

相关问题