Writing to an image using imageStore in OpenGL

2.5k views Asked by At

Currently I am trying to write to an image using imageStore in OpenGL. However, using renderdock as my debugger, I find only a black texture after running my program.

I create and bind the image to write to as follows:

glGenTextures(1, &textureID);
glBindTexture(target, textureID);
glObjectLabel(GL_TEXTURE, textureID, -1, "\"3D Texture\"");
glTexStorage3D(target, 1, GL_RGBA8, width, height, depth);

glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

Then I load the texture to a program by doing:

glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA8);
GLuint location = glGetUniformLocation(programID, uniform);
glUniform1i(location,0);

And finally I render by calling glDrawArrays().

My fragment shader looks like:

#version 440

out vec3 f_pos;
out vec3 f_norm;
out vec2 f_uv;

layout(RGBA8) uniform image3D volumeMap;

void main()
{
    imageStore(volumeMap, ivec3(0,0,0),
        vec4(0,1,1,0));
}

So my expectation is to find a cyan pixel on the upper left corner of the first layer. However that pixel is black.

I have successfully loaded and read from samplers using the texture() call.

I am not sure if I am missing steps or if the way I am doing stuff is wrong.

EDIT:

I modified my code to not rely on RenderDoc to check for the color.

So I render things as follows

Final Fragment Shader:

#version 440

out vec4 fragment_color;

layout(binding=3, RGBA8) uniform image3D vMap;

void main()
{
    fragment_color = imageLoad(vMap, ivec3(0,0,0));
}

C++

glUseProgram(Program1);
/*load texture as above*/
draw();
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

glUseProgram(Program2);
/*load texture as above*/
draw();

draw simply sets up the geometry buffers and then calls glDrawArrays().

The result is a black mesh where I expect a cyan mesh

1

There are 1 answers

1
Nicol Bolas On BEST ANSWER

Image load/store operations operate under the rules of incoherent memory access. This means that writes to them are not visible to later reads unless you explicitly do something to make them visible. Usually, this is a call to glMemoryBarrier.

Always remember that glMemoryBarrier specifies how you intend to access the written value, not how you wrote to it. In this case, the mechanism is the same either way: GL_SHADER_IMAGE_ACCESS_BARRIER_BIT. This command must be placed after the command that writes the data, and before the one that reads it.

Also, I cannot say whether this shader has undefined behavior or not. You have multiple invocations that are all writing to the same memory location. But in your case, they are writing the same value. It is not clear from the description in the specification whether this is genuine UB or whether it is fine. It would certainly be UB if the invocations were writing different data, but I don't know if some exception exists for them writing the same data.

I would be very hesitant about doing this, however.