Error with multiple imageStore operations in compute shader

Hi, I am having an issue with a simple compute shader that calculates the average per column for two input textures. I’ve checked the values in Renderdoc, and they check out, but only when I do only one imageStore operation at the end and comment out the other. When both imageStore operations are there, then Renderdoc shows that the output textures now have the same values, which correspond to the last issued imageStore call. If I swap both calls, then the values in Renderdoc change for both textures and are only correct for the output texture that serves as input in the last imageStore call.

I have tried placing memory barriers in the GLSL code around the imageStore calls, but it does not make a difference, and if I understand it correctly, there should not be a reason why that should work in this situation with writing to two different textures in the same shader. I also cannot find something strange with the C++ code, so I was wondering if any of you know what I’m doing wrong?

The relevant C++ code is as follows:

shader.use();
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, textures[1]); //depthmap

glActiveTexture(GL_TEXTURE11);
glBindTexture(GL_TEXTURE_2D, textures[2]); //heatMap

glBindImageTexture(0, textures[9], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32F);
glBindImageTexture(1, textures[10], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R32F);
glDispatchCompute(DEPTH_WIDTH, 1, 1);
glMemoryBarrier(GL_ALL_BARRIER_BITS);

And the compute shader looks like this:

#version 450 core

uniform sampler2D heatMap;
uniform sampler2D depthMap;
uniform float invTextureWidth;
uniform int DEPTH_WIDTH;
uniform float airTemp;

layout(r32f) writeonly uniform image2D compHeatTexture;
layout(r32f) writeonly uniform image2D compDepthTexture;

layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;


// Write the average heat and depth to two different textures
void main()
{

    float depthWidthFloat = float(DEPTH_WIDTH);
    float x = float(gl_GlobalInvocationID.x) / depthWidthFloat; // the texture is a square


    float depthAverage = 0.0;
    float tempAverage = 0.0;
    float newHeatValue = 0.0;
    for (float y = 0.0; y < 1.0; y += invTextureWidth)
    {
        depthAverage += texture(depthMap, vec2(x, y)).r;

        float newHeatValue = texture(heatMap, vec2(x, y)).r;
        tempAverage += newHeatValue;
    }

    depthAverage /= depthWidthFloat;
    tempAverage /= depthWidthFloat;

    // compDepthTexture now has the same values as compHeatTexture when this is run, while that should not be the case
    // swapping both calls results in a compDepthTexture with the correct values and compHeatTexture with the same but wrong values
    imageStore(compDepthTexture, ivec2(gl_GlobalInvocationID.x, 0), vec4(depthAverage, 0, 0, 0));
    imageStore(compHeatTexture, ivec2(gl_GlobalInvocationID.x, 0), vec4(tempAverage, 0, 0, 0));
}

Are you setting the compHeatTexture and compDepthTexture uniforms correctly? Are the output textures distinct from the input textures?

1 Like

I forgot to add the image binding point in the uniforms, so I indeed made a mistake with setting up the compHeatTexture and compDepthTexture uniforms. When I changed it to

layout(binding = 1, r32f) writeonly uniform image2D compHeatTexture;
layout(binding = 0, r32f) writeonly uniform image2D compDepthTexture;

everything worked correctly, so thank you very much for your help GClements! :slight_smile: