Skip to content

Instantly share code, notes, and snippets.

@thelinked
Last active December 31, 2015 08:39
Show Gist options
  • Select an option

  • Save thelinked/7962215 to your computer and use it in GitHub Desktop.

Select an option

Save thelinked/7962215 to your computer and use it in GitHub Desktop.
One of the best ways I've found to stream instance data into vbos in OpenGL. Write data into a vbo and then orphan and remap it when it fills up. Is a bit like double buffering vbos except the details are handled at the driver level.
class StreamingBufferObject
{
public:
StreamingBufferObject() : vbohandle(0), cursor(0) {}
~StreamingBufferObject()
{
if (vbohandle != 0) glDeleteBuffers(1, &vbohandle);
}
template<typename T>
uint32_t stream(GLenum target, T *_start, int _elementCount)
{
uint32_t bytes = sizeof(T) *_elementCount;
uint32_t aligned = bytes + bytes % 64; //align memory
glBindBuffer(target, vbohandle);
//If theres not enough space left, orphan the buffer object and start writing to the beginning again
if (cursor + aligned > size)
{
assert(aligned < size);
glBufferData(target, size, NULL, GL_DYNAMIC_DRAW);
cursor = 0;
}
void* mapped = glMapBufferRange(target, cursor, aligned, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
memcpy(mapped, _start, bytes);
cursor += aligned;
glUnmapBuffer(target);
return cursor - aligned; //return the offset we used for glVertexAttribPointer call
}
void initialise(GLenum _target, int32_t _bytes);
public:
uint32_t vbohandle, cursor, size;
};
//I've found 1-4MB is a good size, depends on your use case
void StreamingBufferObject::initialise(GLenum _target, int32_t _bytes)
{
size = _bytes;
glGenBuffers(1, &vbohandle);
glBindBuffer(_target, vbohandle);
glBufferData(_target, size, NULL, GL_DYNAMIC_DRAW);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment