You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Compute Shader无法获取结果图像问题排查求助

问题排查:Compute Shader输出1D纹理无法读取数据

我正在用Compute Shader筛选符合条件的颜色列,想把结果输出到1D图像imgOutput做后续处理,但没法通过get_img获取任何数据。下面是我的代码实现,麻烦帮忙排查问题(注:第一个代码块里的texture已经提前生成):

C++ 代码实现

Shader spriteRowProgram, spriteColumnProgram;
unsigned int resultTexture = 0;
const std::string path = found::utils::Environment::GetRunPath();
const std::string sprite_row_path = path + "shaders/glfw_sprite_row.comp";
spriteRowProgram = Shader(sprite_row_path);
std::vector<GLfloat> get_img(qMax(TEX_WIDTH, TEX_HEIGHT) * 4);
glGenTextures(1, &resultTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_1D, resultTexture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, qMax(TEX_WIDTH, TEX_HEIGHT), 0, GL_RGBA, GL_FLOAT, get_img.data());

glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texture);

spriteRowProgram.use();
glUniform1i(1, 1);
glBindImageTexture(1, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F);
glUniform1i(0, 0);
glBindImageTexture(0, resultTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
glClear(GL_COLOR_BUFFER_BIT);

spriteRowProgram.setInt("input_width", TEX_WIDTH);
spriteRowProgram.setInt("input_height", TEX_HEIGHT);
glDispatchCompute(TEX_WIDTH, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

Compute Shader 代码实现

#version 430 core
layout (local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, location = 0, binding = 0) uniform writeonly image1D imgOutput;

// texture samplers
layout(rgba32f, location = 1, binding = 1) uniform readonly image2D inputImage;
uniform int input_width;
uniform int input_height;

void main()
{
    vec4 baseColor = imageLoad(inputImage, ivec2(0, 0));
    bool alpha = baseColor.w == 1;
    bool success = true;
    for (int i = 0; i <= input_height; ++i)
    {
        vec4 current = imageLoad(inputImage, ivec2(gl_GlobalInvocationID.x, i));
        if (alpha) {
            if (current.w > 0.99) continue;
            else {
                success = false;
                break;
            }
        } else {
            vec4 difference = baseColor - current;
            success = abs(difference.x) < 0.01 && abs(difference.y) < 0.01 && abs(difference.z) < 0.01;
            if (success) continue;
            else {
                break;
            }
        }
    }
    if (success) baseColor = ivec4(0.1, 0.1, 0.1, 0.1);
    else baseColor = ivec4(1.0, 1.0, 1.0, 1.0);
    imageStore(imgOutput, int(gl_GlobalInvocationID.x), baseColor);
}

问题排查与修复方案

  • 缺少GPU到CPU的数据读取步骤:你仅用get_img初始化了纹理,但Compute Shader执行后,没有将GPU上的resultTexture数据读回CPU。在glMemoryBarrier后添加以下代码:
    glBindTexture(GL_TEXTURE_1D, resultTexture);
    glGetTexImage(GL_TEXTURE_1D, 0, GL_RGBA, GL_FLOAT, get_img.data());
    
  • 1D纹理参数设置错误:1D纹理只有S轴,GL_TEXTURE_WRAP_T参数无效,删除该行:
    // glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
  • Shader中纹理访问越界:循环条件i <= input_height会访问超出图像范围的像素(图像y坐标范围是0到input_height-1),修改为:
    for (int i = 0; i < input_height; ++i)
    
  • 类型转换错误:将ivec4赋值给vec4会导致浮点数值被截断,改用vec4直接赋值:
    if (success) baseColor = vec4(0.1, 0.1, 0.1, 0.1);
    else baseColor = vec4(1.0, 1.0, 1.0, 1.0);
    
  • 冗余的Uniform设置:image类型的资源通过binding布局直接绑定,不需要用glUniform1i设置纹理单元,删除以下两行:
    // glUniform1i(1, 1);
    // glUniform1i(0, 0);
    
  • 内存屏障类型不匹配:写入图像纹理后,应使用GL_TEXTURE_FETCH_BARRIER_BIT确保数据可见性,修改内存屏障:
    glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
    

内容的提问来源于stack exchange,提问作者0ices

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 15:35:27