0

I have a GLSL fragment shader that should render pixels into a texture, and blend the value at each pixel with the one that has been in the texture before.

Instead of using GL blending operations, it needs to have as variables in the shader, both the existing value at that pixel that is in the texture (dst), and the new value that should be blended on top of it (src).

I have a fragment shader that is like this:

#version 460 core

layout(location=0) in float src;

layout(binding=0, r32f) uniform image2D valuesImage;
layout(location=0) out vec4 outputValue;

void main() {
    ivec2 pixelCoord = ivec2(gl_FragCoord.xy);
    float dst = imageLoad(valuesImage, pixelCoord).r;
    float result = f(dst, src); // do some blending operation
    outValue = vec4(result, 0.0, 0.0, 0.0);
}

And it is called like:

// bind texture to framebuffer
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, &drawBuffers);

// also bind texture to image
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);

//....

for each frame {
    glDrawArrays(GL_TRIANGLES, 0, numVertices);

    glTextureBarrier();
}

According to https://www.khronos.org/opengl/wiki/Memory_Model "Framebuffer objects", reading from the image that is being rendered into would not work (such reads are incoherent).

However later it says (bottom of "Texture barrier") that since the ARB_texture_barrier extension, it would work, when there is only a single image read operation from the same pixel that is being rendered into (through the framebuffer), and it is followed by a texture barrier call.

Is this correct that it would be well-defined when used as in this example? Also, would it still work, if GL_BLEND options is used on top of this, when OpenGL renders outValue into the texture?

7
  • I'm not sure if I understand you correctly: You are still not allowed to read and write from the same draw call. What texture barriers allow you to do is that when drawCall1 renders something and drawCall2 reads the same texels, a texture barrier guarantees that all changes from drawCall1 are visible to drawCall2. Commented Jun 4, 2024 at 11:00
  • ARB_texture_barrier seems to say that this is allowed (reading image and rendering to framebuffer, within the same draw call): Specifically, the values of rendered fragments are undefined if any shader stage fetches texels and the same texels are written via fragment shader outputs, even if the reads and writes are not in the same Draw call, unless any of the following exceptions apply: ... There is only a single read and write of each texel, and the read is in the fragment shader invocation that writes the same texel (e.g. using "texelFetch2D(sampler, ivec2(gl_FragCoord.xy), 0);"). Commented Jun 4, 2024 at 11:22
  • Also OpenGL wiki says: 1. Render an object that reads from image, blends in the shader, and writes to image. 2. Call glTextureBarrier, if the next object overlaps with the first. Commented Jun 4, 2024 at 11:23
  • Ah, now I understand what you mean: Yes, as long as you can guarantee that each draw call reads each texel only once and stores it only once (so basically no overdraw), this should work. Commented Jun 4, 2024 at 11:35
  • If there are two textures (both bound to a framebuffer attachment, and both bound to GLSL images), can the fragment shader also do the same for both? (Read from valuesImage1 and write to outputValue1, and then read from valuesImage2 and write to outputValue2) Commented Jun 4, 2024 at 11:45

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.