OpenGL中的2遍渲染系统正在使用MRT着色器,该着色器绑定(bind)到2个帧缓冲区纹理tex1和tex2。 MRT传递的目标是计算场景中的 overdraw ,并在聚集传递中将其渲染。我使用帧缓冲纹理来传递结果。

它也有一个工作的ssbo缓冲区,该缓冲区很大(并且使用固定的屏幕分辨率),并且链接需要花费很多时间,但是我可以使用它来做atomicAdds。我要完成的工作是用uiimage2D上的imageAtomicAdd操作代替它,就像mrt传递一样。

问题在于imageAtomicAdd的结果始终为零,我希望它像原子添加在那时那样上升。

#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收集到了..



..但坐标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的“核心”配置文件,因此我有点困惑,缺少所需的缓冲区可能是什么问题。难道是误认为imgCounter是帧缓冲区MRT设置的一部分吗?

最佳答案

该纹理不完整。

请参见,当您绑定(bind)纹理以用于图像加载/存储操作时,您不会同时绑定(bind)采样器。因此,所有这些glSamplerParameter调用对于纹理的完整性状态都是毫无意义的。

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

关于opengl - GLSL:我可以在同一着色器(通过)中组合MRT,ssbo和imageAtomic操作吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46788286/

10-13 06:30