Use SSBO as VBO input for the next draw call
Asked Answered
M

1

5

I write some vertex data inside a shader to SSBO. Then I want to use the data written to the SSBO as VBOs. These will be used for the next draw call. How can this be done?

Here is, how I do it now, but it still segfaults:

int new_vertex_count = …;
int new_index_count = …;
int* new_indices = …;

GLuint ssbo[3];
glGenBuffers(3, ssbo);


glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER, new_vertex_count * 3 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo[1]);

glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo[2]);
glBufferData(GL_SHADER_STORAGE_BUFFER, new_vertex_count * 2 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo[2]);

glBindVertexArray(vao); //bind the original VAO
glPatchParameteri(GL_PATCH_VERTICES, 16);
glEnable(GL_RASTERIZER_DISCARD); //disable displaying
glDrawElements(GL_PATCHES, index_count, GL_UNSIGNED_INT, 0); //don't draw, just 
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); //sync writing
glFinish();
glDisable(GL_RASTERIZER_DISCARD); //reanable displaying for next draw call
glBindVertexArray(0); //unbind original VAO in order to use new VBOs


glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ssbo[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_count * sizeof(uint), indices, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, ssbo[1]); //bind SSBO as VBO, is this even possible?
//or should I use new VBOs and copy? How would I copy then?
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

glBindBuffer(GL_ARRAY_BUFFER, ssbo[2]);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);

glDrawElements(GL_PATCHES, new_index_count, new_indices, GL_UNSIGNED_INT, 0); //here the real drawing
Magee answered 18/7, 2017 at 18:26 Comment(0)
E
8

There is no such thing as an "SSBO" or a "VBO". There are only buffer objects. Storage blocks and vertex arrays are uses for buffer objects, but a particular buffer is not inherently linked to a particular use. There's nothing stopping you from writing to a buffer through a storage block, then reading from it in a rendering operation.

So long as you follow the rules of incoherent memory access for those writes, of course. Writes through a storage block are not available for reading operations unless you explicitly make them available. You would use glMemoryBarrier for this. And the way a memory barrier works is that the enumerator specifies the operations you want to be able to see the results of whatever was written.

You want the written data to be read as vertex attribute arrays. So you use:

glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT​);
Exhibit answered 18/7, 2017 at 19:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.