[GLSL 420]imageStore store nothing

Hi!

I’m trying to set up a per pixel linked list algorithm, I want to sort my fragments by insertion, so, I’ve created tree images :

-The first one is just a counter which count the number of fragments drawn at the same position.
-The second one is a 2D array image which store the depth of every fragment.
-The las one is a 2D array image which store the color of every fragment.

So, the c++ code looks like this. (I draw a fullscreen quad first to clear the images)


// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <glew.h>
#include <vector>
// Include GLFW
#include <GLFW/glfw3.h>
GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){

    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    // Read the Vertex Shader code from the file
    std::string VertexShaderCode;
    std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
    if(VertexShaderStream.is_open())
    {
        std::string Line = "";
        while(getline(VertexShaderStream, Line))
            VertexShaderCode += "
" + Line;
        VertexShaderStream.close();
    }

    // Read the Fragment Shader code from the file
    std::string FragmentShaderCode;
    std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in);
    if(FragmentShaderStream.is_open()){
        std::string Line = "";
        while(getline(FragmentShaderStream, Line))
            FragmentShaderCode += "
" + Line;
        FragmentShaderStream.close();
    }

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    printf("Compiling shader : %s
", vertex_file_path);
    char const * VertexSourcePointer = VertexShaderCode.c_str();
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> VertexShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
    fprintf(stdout, "%s
", &VertexShaderErrorMessage[0]);

    // Compile Fragment Shader
    printf("Compiling shader : %s
", fragment_file_path);
    char const * FragmentSourcePointer = FragmentShaderCode.c_str();
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
    fprintf(stdout, "%s
", &FragmentShaderErrorMessage[0]);

    // Link the program
    fprintf(stdout, "Linking program
");
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
    fprintf(stdout, "%s
", &ProgramErrorMessage[0]);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    return ProgramID;
}
GLFWwindow* window;

int main( void )
{
	// Initialise GLFW
	if( !glfwInit() )
	{
		fprintf( stderr, "Failed to initialize GLFW
" );
		return -1;
	}

	glfwWindowHint(GLFW_SAMPLES, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	// Open a window and create its OpenGL context
	window = glfwCreateWindow( 1024, 768, "Tutorial 01", NULL, NULL);
	if( window == NULL ){
		fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.
" );
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) {
		fprintf(stderr, "Failed to initialize GLEW
");
		return -1;
	}
	GLuint abufferTexID, abufferCounterTexID, adepthbufferTexID;
	glGenTextures(1, &abufferTexID);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F, 1024, 768, 16, 0,  GL_RGBA, GL_FLOAT, 0);
    glBindImageTextureEXT(0, abufferTexID, 0, true, 0,  GL_READ_WRITE, GL_RGBA32F);
    glGenTextures(1, &abufferCounterTexID);
    glBindTexture(GL_TEXTURE_2D, abufferCounterTexID);

    // Set filter
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    //Texture creation
    //Uses GL_R32F instead of GL_R32I that is not working in R257.15
    glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1024, 768, 0,  GL_RED, GL_FLOAT, 0);
    glBindImageTextureEXT(1, abufferCounterTexID, 0, false, 0,  GL_READ_WRITE, GL_R32UI);
    glGenTextures(1, &adepthbufferTexID);
    glBindTexture(GL_TEXTURE_2D, adepthbufferTexID);

    // Set filter
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    //Texture creation
    //Uses GL_R32F instead of GL_R32I that is not working in R257.15
    glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R32F, 1024, 768, 16, 0,  GL_RED, GL_FLOAT, 0);
    glBindImageTextureEXT(1, adepthbufferTexID, 0, true, 0,  GL_READ_WRITE, GL_R32F);
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
    // An array of 3 vectors which represents 3 vertices
    static const GLfloat g_vertex_buffer_data2[] = {
       -1.0f, -1.f, 0.f,
       1.f, -1.f, 0.f,
       1.f, 1.f, 0.f,
       -1.f, 1.f, 0.f
    };
    static const GLfloat g_vertex_buffer_data[] = {
       -1.0f, -1.0f, 0.0f,
       1.0f, -1.0f, 0.0f,
       0.0f,  1.0f, 0.0f,
    };
    // This will identify our vertex buffer
    GLuint vertexbuffer, vertexbuffer2;

    // Generate 1 buffer, put the resulting identifier in vertexbuffer
    glGenBuffers(1, &vertexbuffer);

    // The following commands will talk about our 'vertexbuffer' buffer
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

    // Give our vertices to OpenGL.
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
    glGenBuffers(1, &vertexbuffer2);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data2), g_vertex_buffer_data2, GL_STATIC_DRAW);
    // Create and compile our GLSL program from the shaders
    GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", "SimpleFragmentShader.fragmentshader" );
    GLuint programID2 = LoadShaders("SimpleVertexShader.vertexshader","ClearABuffer.fragmentshader");
    GLuint abufferLocation = glGetUniformLocation(programID, "abufferImg");
    GLuint abufferCounterLocation = glGetUniformLocation(programID, "abufferCounterImg");
    GLuint adepthbufferLocation = glGetUniformLocation(programID, "adepthbufferImg");
    GLuint abufferLocation2 = glGetUniformLocation(programID2, "abufferImg");
    GLuint abufferCounterLocation2 = glGetUniformLocation(programID2, "abufferCounterImg");
    GLuint adepthbufferLocation2 = glGetUniformLocation(programID2, "adepthbufferImg");
	// Initialize GLEW


	// Ensure we can capture the escape key being pressed below
	glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

	// Dark blue background
	glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

	do{

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(
           0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
           3,                  // size
           GL_FLOAT,           // type
           GL_FALSE,           // normalized?
           0,                  // stride
           (void*)0            // array buffer offset
        );
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer2);
        glUseProgram(programID2);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        glMemoryBarrierEXT(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

        glUseProgram(programID);
        // Draw the triangle !
        glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
        glMemoryBarrierEXT(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT);
        glDisableVertexAttribArray(0);
		glfwSwapBuffers(window);
		glfwPollEvents();

	} // Check if the ESC key was pressed or the window was closed
	while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
		   glfwWindowShouldClose(window) == 0 );

	// Close OpenGL window and terminate GLFW
	glfwTerminate();

	return 0;
}

SimpleVertexShader.vertexshader :


#version 420 core
layout(location = 0) in vec3 vertexPosition_modelspace;
void main() {
	gl_Position.xyz = vertexPosition_modelspace;
        gl_Position.w = 1.0;
}

ClearABuffer.fragmentshader :


#version 420 core
#extension GL_EXT_shader_image_load_store : enable
uniform layout(size1x32) uimage2D abufferCounterImg;
uniform layout(size1x32) image2DArray adepthbufferImg;
uniform layout(size4x32) image2DArray abufferImg;
void main() {
	ivec2 coords = ivec2(gl_FragCoord.xy);
        imageStore(abufferCounterImg, coords, ivec4(0, 0, 0, 0));
	for (int i = 0; i < 16; i++) {
	     imageStore(adepthbufferImg, ivec3(coords, i), vec4(0, 0, 0, 0));
	     imageStore(abufferImg, ivec3(coords, i), vec4(0, 0, 0, 0));
	}
	discard;
}

and SimpleFragmentShader.fragmentshader :


#version 420 core
#extension GL_EXT_shader_image_load_store : enable
uniform layout(size1x32) uimage2D abufferCounterImg;
uniform layout(size1x32) image2DArray adepthbufferImg;
uniform layout(size4x32) image2DArray abufferImg;
out vec4 color;
vec4 backgroundColor = vec4(0, 0, 0, 1);
void main() {	
	ivec2 coords = ivec2 (gl_FragCoord.xy);
        float z = gl_FragCoord.z;
        int nbFrag = int(imageLoad(abufferCounterImg, coords).r);
        int fragPos = 0;        
        /*Check the fragment's position in the list by comparing the depth fragment's values.*/
        while (fragPos < nbFrag && z >= imageLoad(adepthbufferImg, ivec3(coords, fragPos)).r)
		fragPos++;
	int i = nbFrag;
        /*Move every fragment which are before the current one from one position back.*/
	while(i > fragPos) {
		float adepthbuffervalue = imageLoad(adepthbufferImg, ivec3(coords, i-1)).r;
		vec4 abuffervalue = imageLoad(abufferImg, ivec3(coords, i-1));
		imageStore(adepthbufferImg, ivec3(coords, i), vec4(adepthbuffervalue, 0, 0, 0));
		imageStore(abufferImg, ivec3(coords, i), abuffervalue);		
		i--;
	}	
        /*Insert the current fragment at the right place in the list.*/
	imageStore(adepthbufferImg, ivec3(coords, fragPos), vec4(z, 0, 0, 0)); 
    	imageStore(abufferImg, ivec3(coords, fragPos), vec4(1, 0, 0, 1));
        /*Increase the counter.*/
	nbFrag++;
	imageStore(abufferCounterImg, coords, ivec4(nbFrag, 0, 0, 0));
        /*Apply the alpha blending on the sorted list.*/
	vec4 finalColor = backgroundColor;
	for (i = 0; i < nbFrag; i++) {
            vec4 currentColor = imageLoad(abufferImg, ivec3(coords, i));
            finalColor = currentColor * currentColor.a + finalColor * (1 - currentColor.a);
	}
	color = finalColor;
}

The problem is that I’ve a black triangle draw on the screen so the color stored to the mage stay black, or it should be red.

Have I done something wrong ?

Thanks for your help.

I’ve printed all values of the 3D texture, and they aren’t modified, they are always keeping to 0.


 glBindTexture(GL_TEXTURE_2D, abufferTexID);
 glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA32F,GL_FLOAT,texValues);
 for (unsigned int i = 0; i < 1024 * 768 * 16*4; i++) {
      std::cout<<texValues[i]<<std::endl;
 }

Maybe a problem with the AMD driver …

I only have time for a brief glance at the code, but a couple of things stand out:

OpenGL 4.2 incorporates image load/store, so there’s no reason to use EXT_shader_image_load_store.

Also, you’re creating the texture as GL_R32F but binding it as GL_R32UI.

Again, GLSL 4.2 incorporates image load/store. But it doesn’t use the layout(size4x32) etc qualifiers, but e.g. layout(rgba32f) instead.

OpenGL 4.2 incorporates image load/store, so there’s no reason to use EXT_shader_image_load_store.

Ok I don’t need to declare this extension in the shader indeed.

Also, you’re creating the texture as GL_R32F but binding it as GL_R32UI.

Ok I’ve modified that.

Again, GLSL 4.2 incorporates image load/store. But it doesn’t use the layout(size4x32) etc qualifiers, but e.g. layout(rgba32f) instead.

I’ve changed that too :


#version 420 core
uniform layout(r32ui) uimage2D abufferCounterImg;
uniform layout(r32f) image2DArray adepthbufferImg;
uniform layout(rgba32f) image2DArray abufferImg;
out vec4 color;
vec4 backgroundColor = vec4(0, 0, 0, 1);
void main() {	
	ivec2 coords = ivec2 (gl_FragCoord.xy);
        float z = gl_FragCoord.z;
        int nbFrag = int(imageLoad(abufferCounterImg, coords).r);
        int fragPos = 0;        
        while (fragPos < nbFrag && z >= imageLoad(adepthbufferImg, ivec3(coords, fragPos)).r)
		fragPos++;
	int i = nbFrag;
	while(i > fragPos) {
		float adepthbuffervalue = imageLoad(adepthbufferImg, ivec3(coords, i-1)).r;
		vec4 abuffervalue = imageLoad(abufferImg, ivec3(coords, i-1));
		imageStore(adepthbufferImg, ivec3(coords, i), vec4(adepthbuffervalue, 0, 0, 0));
		imageStore(abufferImg, ivec3(coords, i), abuffervalue);		
		i--;
	}	
	imageStore(adepthbufferImg, ivec3(coords, fragPos), vec4(z, 0, 0, 0)); 
    	imageStore(abufferImg, ivec3(coords, fragPos), vec4(1, 0, 0, 1));
	nbFrag++;
	imageStore(abufferCounterImg, coords, ivec4(nbFrag, 0, 0, 0));
	vec4 finalColor = backgroundColor;
	for (i = 0; i < nbFrag; i++) {
            vec4 currentColor = imageLoad(abufferImg, ivec3(coords, i));
            finalColor = currentColor * currentColor.a + finalColor * (1 - currentColor.a);
	}	
	color = finalColor;
}

But it doesn’t solve the problem.

PS : I’ve added some calls to memoryBarrier() in the GLSL code but it doesn’t change anything …

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.