GLSL:我可以在同一个着色器(pass)中组合MRT,ssbo和imageAtomic操作吗?

时间:2017-10-17 10:46:05

标签: opengl glsl shader

OpenGL中的2遍渲染系统使用的MRT着色器绑定到2个帧缓冲纹理 tex1 tex2 。 mrt传递的目标是计算场景中的透支并在聚集传递中将其渲染出来。我使用framebuffer纹理传递结果。

它还有一个非常大的工作ssbo缓冲区(使用固定的屏幕分辨率)并且需要很长时间才能链接,但是我可以使用它来执行 atomicAdds 。我想要完成的是用 uiimage2D 上的 imageAtomicAdd 操作替换它,就像使用mrt pass一样。

问题是imageAtomicAdd的结果总是为零,我希望它会像atomicAdd那样上升。

#version 440 core

layout(early_fragment_tests) in;

// this works fine
layout (location = 0) out vec4 tex1;
layout (location = 1) out vec4 tex2;

// this works fine
layout(std430, binding = 3) buffer ssbo_data
{
        uint v[1024*768];
};

// this does not work at all.
uniform volatile layout(r32ui) uimage2D imgCounter;

out vec4 frag_colour;

void main () 
{       
    ivec2 coords = ivec2(gl_FragCoord.xy);
    uint addValue = 1u;

    uint countOverdraw1 = atomicAdd(v[coords.x + coords.y * 1024], 1u);
    uint countOverdraw2 = imageAtomicAdd(imgCounter, ivec2(0,0), 1u); 

    memoryBarrier();

    // supports 256 levels of overdraw..
    float overdrawDepth = 256.0;
    vec3 c1 = vec3(float(countOverdraw1+1)/overdrawDepth ,0,1);
    vec3 c2 = vec3(float(countOverdraw2+1)/overdrawDepth ,0,1);

    tex1 = vec4(c1,1);  
    tex2 = vec4(c2,1);  
    frag_colour = vec4(1,1,1,1);
}

khronos website on image atomic operations我收集到了......

  

对任何超出边界的纹素的原子操作   绑定的图像将返回0并且不执行任何操作。

..但坐标 ivec2(0,0)将完全在纹理大小的范围内(1024 x 768)。

可能纹理设置不正确?这就是我构建uiimage2D(从管道流拼凑在一起)的方式:

编辑:我根据Nicol Bolas的答案更新代码:设置纹理参数而不是采样器参数

char data[1024*768*4];
glGenTextures(1, &m_Handle);

m_Target = GL_TEXTURE_2D;

glActiveTexture(GL_TEXTURE0+6);
glBindTexture(m_Target,m_Handle);

// updated : a sampler object was bound to the texture, but is now removed

glTexParameteri(m_Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  // updated
glTexParameteri(m_Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  // updated
glTexParameteri(m_Target, GL_TEXTURE_WRAP_R, GL_REPEAT);       // updated
glTexParameteri(m_Target, GL_TEXTURE_WRAP_S, GL_REPEAT);       // updated
glTexParameteri(m_Target, GL_TEXTURE_WRAP_T, GL_REPEAT);       // updated
glTexImage2D(m_Target, 0, R32UI, 1024, 768, 0, GL_RED_INTEGER, GL_UNSIGNED_INT,  data);     

如果我通过gDEBugger GL运行它,我看到"此时纹理数据不可用"虽然'纹理4'纹理的参数被填入并且正确,没有任何纹理参数'和' 0级参数'显示(N / A)。在此时捕获调试器会引发一系列未出现在gDEBugger之外的问题。以下是前几个:

GL_INVALID_OPERATION error generated. The required buffer is missing.
GL_INVALID_ENUM error generated. <pname> requires feature(s) disabled in the current profile. 
GL_INVALID_OPERATION error generated. <index> exceeds the maximum number of supported texture units. 
GL_INVALID_ENUM error generated. or require feature(s) disabled in the current profile.  
GL_INVALID_OPERATION error generated. Can't mix integer and non-integer data
...

我明确强制要求GL 4.4或GL4.4&#39;核心&#39;配置文件,所以我有点困惑,可能是缺少所需的缓冲区的问题。难道它错误地将imgCounter视为帧缓冲区的MRT设置的一部分吗?

1 个答案:

答案 0 :(得分:4)

纹理不完整。

请参阅绑定纹理以用于图像加载/存储操作时,将采样器与其绑定。因此,所有这些glSamplerParameter调用对纹理的完整性状态都没有意义。

纹理不完整,因为过滤参数为GL_LINEAR,但纹理是无符号整数格式。在创建整数格式纹理时,您应始终将纹理参数设置为有效值。