Read write an image with the GL_ARB_fragment_shader_interlock extension

Viewed 74

I am testing whether the GL_ARB_fragment_shader_interlock extension can execute the critical section code of the same pixel position in the order of instance rendering. I used instanced rendering to draw five translucent planes (instances in order from farthest to nearer) and the result is the same as the fixed pipeline blending result (the blending result is random without this extension). But one problem is that there will be an extra line in the middle of each plane (not when using fixed pipeline blending). I found that the adjacent sides of the triangle generating the fragments twice. But rasterization should ensure that adjacent triangles do not have overlapping pixels. How to solve this please? I don't know where I went wrong, here is the code and result, please enlighten me!

The GLSL code:

#version 450 core
#extension GL_ARB_fragment_shader_interlock : require

//out vec4 Color_;

in vec4 v2f_Color;

layout(binding = 0, rgba16f) uniform image2D uColorTex;

void main()
{
    beginInvocationInterlockARB();

    vec4 color = imageLoad(uColorTex, ivec2(gl_FragCoord.xy));
    color = (1 - v2f_Color.a) * color + v2f_Color * v2f_Color.a;
    imageStore(uColorTex, ivec2(gl_FragCoord.xy), color);

    endInvocationInterlockARB();
    
    //Color_ = v2f_Color;
}

Tthe result using extension to read write an image manually: enter image description here

enter image description here

The result using fixed pipeline blending: enter image description here

1 Answers

I am a bit suspicious of the ivec2(gl_FragCoord.xy). This is doing a conversion from floating-point to an integer, and it could be the case that it gets rounded in different directions between the different triangles. This might explain not only the overlap, but why there's a missing top-left pixel in one of the squares.

Judging by the spec, ivec2(gl_FragCoord.xy) should be equivalent to ivec2(trunc(gl_FragCoord.xy)), which really ought to be consistent, but maybe the implementation is bad...

You might want to try:

  • ivec2(round(gl_FragCoord.xy))
  • ivec2(round(gl_FragCoord.xy + 0.5))
Related