OpenGL创建GL_R32UI格式纹理查询宽高返回0问题排查
问题原因及修复方案
核心错误点(导致纹理宽高查询为0)
- 整数纹理使用了不支持的过滤模式
GL_R32UI属于无符号整数内部格式,OpenGL规范明确规定整数纹理不支持GL_LINEAR过滤,仅支持GL_NEAREST,错误的过滤参数会导致纹理状态不完整,创建直接失败,因此查询宽高返回0。 - 纹理数据传输的格式参数不匹配
内部格式为整数类型时,glTexImage2D的第7个参数(外部基础格式)必须使用GL_RED_INTEGER而非GL_RED,GL_RED仅适用于归一化、浮点类纹理格式,类型不匹配也会导致纹理创建失败。
额外逻辑错误(不影响当前宽高查询,但会导致后续计算着色器执行异常)
- 图像单元绑定点不匹配
代码中glBindImageTexture将计数纹理绑定到了0号图像单元,但计算着色器中img_output的绑定点为1,img_input的绑定点为0,会导致输入输出纹理错位。 - 计算着色器工作组效率极低
local_size_x = 1, local_size_y = 1的配置会导致GPU并行性完全无法发挥,运行效率会低几个数量级。
修正后的计数纹理创建代码
num_bins = 256; GLuint* hist_data = new GLuint[num_bins * 3](); // 3对应RGB三个通道 glGenTextures(1, &tex_output); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex_output); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // 整数纹理必须使用NEAREST过滤 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // 外部格式改为GL_RED_INTEGER匹配整数内部格式 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, 256, 3, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, hist_data); // 绑定到1号图像单元匹配着色器绑定点 glBindImageTexture(1, tex_output, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); int width, height; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); cout << "width: " << width << " height: " << height << endl;
补充优化建议
将计算着色器的工作组配置修改为layout(local_size_x = 16, local_size_y = 16) in,调度时按输入纹理尺寸除以工作组大小计算调度组数,可大幅提升计算性能。
读取计数纹理前需要添加glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT)保证原子操作的结果对后续操作可见。
内容的提问来源于stack exchange,提问作者VlassisFo
相关产品推荐
相关产品推荐

