Updating SSBO Buffer size correctly

I’m currently using an SSBO to send matrix information to the GPU in order to use in the Vertex and Fragment shader to appy on the instaces being rendered by glDrawElementsInstanced.

My question is, what is the best way to reupdate the SSBO buffer size correctly?
I don’t think the question is detailed enough, so I’ll explain the scenario:

I have a central SSBO object which is used to render all sets of instanced of the application, and each time the buffer data is passsed on the SSBO, I check if the size is the same, if not, I reupdate the size and send the buffer, and so on, every glBufferData call I make. Let me add the scheme here:

Setup:

ssbo = glGenBuffers();
size = 20;
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, size, GL_STREAM_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo);

RenderFrame:

  1. Clear FBO
  2.  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
     if(bufferSize > size) {
     	this.size = bufferSize;
     	glBufferData(GL_SHADER_STORAGE_BUFFER, size, GL_STREAM_DRAW);
     }
     glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, buffer);
     glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    
  3. glDrawElementsInstanced(GL_TRIANGLES, indicesCount, GL_UNSIGNED_INT, 0, count);
    
  4. Repeat

My concern is, am I doing it right by calling glBufferData(GL_SHADER_STORAGE_BUFFER, size, GL_STREAM_DRAW); to update the buffer size?

And am I using the GL_STREAM_DRAW correctly or should it be GL_STATIC_DRAW?

I’ve read about it and tried to search regarding this matter, but I still get some confusion on what to use and why.

This is just for the sake of controlling each instance transformation (Pos, Dir, Scale, etc…)

Note: this code works fairly well on machines with good hardware cards, but has weird results on low-end ones

Don’t. If you can’t start with a big enough size for your needs (ie: if you’re going to resize it and sometimes you blow past the maximum capacity), it’s best to allocate a new buffer object when you overflow the size of the current one.

This way, you’ll be able to do things like use persistent mapping to upload data.

So basically, something like this:

if(NewBufferSize > CurrentBufferSize) {
	glBufferData(GL_SHADER_STORAGE_BUFFER, NewBufferSize, GL_STREAM_DRAW);
}
glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, buffer);

The issue here is that this technique requires knowing beforehand the size of the buffer in order to do an alternate writing each frame (if I read correctly), but my problem is that I can’t know beforehand the number of the instances that will be rendered at on point, in order to know at the starting point the full size of the buffer, so I was trying to write and expand it as it goes, but from what I can understand this is totally async which can lead to flickering results.

I was able to allocate a bigger buffer and this way works out perfectly. I thought that I should always keep it as packed as possible to prevent memory abuse.

Thanks for the concise info.

No, “allocate a new buffer object” would be:

GLuint newBuffer;
glCreateBuffer(1, &newBuffer);
glNamedBufferStorage(newBuffer, NewBufferSize, nullptr, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT);

But you know it at some point; otherwise, you wouldn’t be able to provide NewBufferSize. If that size is larger than the buffer object you have, make a new one that’s big enough.

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