PDA

View Full Version : [GLSL 420]imageStore store nothing.



laurent7601
10-22-2015, 12:57 AM
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 += "\n" + 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 += "\n" + Line;
FragmentShaderStream.close();
}

GLint Result = GL_FALSE;
int InfoLogLength;

// Compile Vertex Shader
printf("Compiling shader : %s\n", 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\n", &VertexShaderErrorMessage[0]);

// Compile Fragment Shader
printf("Compiling shader : %s\n", 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\n", &FragmentShaderErrorMessage[0]);

// Link the program
fprintf(stdout, "Linking program\n");
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\n", &ProgramErrorMessage[0]);

glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);

return ProgramID;
}
GLFWwindow* window;

int main( void )
{
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
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.\n" );
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
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.

laurent7601
10-26-2015, 05:04 AM
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 ...

GClements
10-26-2015, 07:53 AM
I only have time for a brief glance at the code, but a couple of things stand out:





glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);



//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);


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.





#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;



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

laurent7601
10-27-2015, 05:31 AM
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 ...