Hello!
I’m facing some problems with reading from SSBO.
For some reason the buffer assigned for SSBO is either empty (not filled in shader)
or not accessible (glMapBuffer
returns NULL
and err code 1282
).
I’ve already tried several approaches from different forums and books but the result is the same.
The best result that I could get is that sometimes it actually returns non-empty buffer with expected content but it occurs only once per program run and very unstably.
Could your please explain why this happens and where I’m wrong?
Also some advises on how to achieve stable behavior are appreciated!
Application code:
....
// Buffer initialization and bindings
GLuint imageBuffer;
//std::vector<glm::vec3> image;
std::vector<float> image;
image.resize(width*height*3);
cv::Mat img = cv::Mat(height, width, CV_32FC3);
glCreateBuffers(1, &imageBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, imageBuffer);
glNamedBufferStorage(imageBuffer, // Name of the buffer
//width*height*sizeof(glm::vec3), // Storage size in bytes
width*height*sizeof(float)*3, // Storage size in bytes
img.data,//&image[0], // initial data
GL_MAP_WRITE_BIT | GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT ); // Allow map for writing
glBufferData(GL_SHADER_STORAGE_BUFFER, /*width*height*sizeof(glm::vec3)*/width*height*sizeof(float)*3, /*&image[0]*/img.data, GL_DYNAMIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2/*see fragment shader binding*/, imageBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
......
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT); // missed previously call to memory barrier
do{
glBindBuffer(GL_SHADER_STORAGE_BUFFER, imageBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2/*see fragment shader binding*/, imageBuffer);
/* here goes rendering and other bindings*/
....
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );
std::this_thread::sleep_for(std::chrono::milliseconds(10));
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
//here we gona read the SSBO content
glFinish();
//void * ptr = glMapNamedBuffer(imageBuffer, GL_READ_WRITE);//GL_READ_ONLY);
void * ptr = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_WRITE);//GL_READ_ONLY);
/*void * ptr = glMapBufferRange( GL_SHADER_STORAGE_BUFFER,
0,
width*height*sizeof(float)*3,
GL_READ_ONLY);*/
if(ptr != NULL)
{
// Sometime in the first iteration of the cycle the program manage to get here but the buffer is sometimes empty, sometimes filled
// Copy our data into it...
memcpy(img.data, ptr, width*height*sizeof(float)*3);
// Tell OpenGL that we're done with the pointer
glUnmapNamedBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
cv::imshow("Suzane",img);
std::cout<<"Image read"<<std::endl;
cv::waitKey();
}
else{
// the program always end up here.
std::cout<<"glMapNamedBuffer return NULL"<<std::endl;
checkGLError(""); // prints MyApp: glError 1282
}
glUnmapNamedBuffer(GL_SHADER_STORAGE_BUFFER);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
}
...
// much later
void checkGLError(std::string op) {
int error;
while ((error = glGetError()) != GL_NO_ERROR) {
std::cout<<"MyApp"<< op << ": glError " << error<<std::endl;
}
}
Fragment shader code:
#version 430 core
// Interpolated values from the vertex shaders
in vec2 UV;
in vec3 Position_worldspace;
in vec3 Normal_cameraspace;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;
in vec3 colorIn;
layout(origin_upper_left) in vec4 gl_FragCoord ;
// Ouput data
out vec3 color;
uniform int imageBufferID;
uniform int imageWidth;
uniform int imageHeight;
layout(std430, binding = 2) buffer imageLayout
{
//vec3 image[];
float image[];
} SharedBuffer;
void main(){
//----------------------------------------------------------------
vec4 xy = gl_FragCoord;
highp int x = int(xy.x);
highp int y = int(xy.y);
int stride = imageWidth*3;
int maxOffset = imageWidth*imageHeight*3;
int offset = int(3*x + y*stride);
if(offset>=maxOffset) offset= maxOffset-1;
int ind = offset;
SharedBuffer.image[offset] = colorIn.x;
SharedBuffer.image[offset+1] = colorIn.y;
SharedBuffer.image[offset+2] = colorIn.z;
//--------------------------------------------------------------
color = colorIn;
}