PDA

View Full Version : Move data with in the buffer



EmJayJay
08-26-2015, 06:41 AM
Is there a way to move data with in a a buffer? Say, I want to remove vertices from the buffer for example and I would like to move the rest of the data over the deleted part. Or do I have to refill the buffer from the start of the deleted vertices completly?

GClements
08-26-2015, 07:58 AM
Is there a way to move data with in a a buffer?
You can map the buffer then move the data with memmove/memcpy, std::copy, etc.

Or you can read it out with glGetBufferSubData() then write it back to the new location with glBufferSubData().

EmJayJay
08-26-2015, 08:11 AM
So there isn't a function which makes buffer[i] = buffer[j]?

So the only option is to read the movable data from the GPU to RAM and rewrite it back to the buffer at the specified location.
Unless you use OpenCL in conjuction or write compute shader.

Alfonse Reinheart
08-26-2015, 09:41 AM
You can copy one part of a buffer into another part (https://www.opengl.org/wiki/Buffer_Object#Copying), all on the GPU. Provided that the two regions don't overlap.

Generally speaking however, people don't really make such edits to live buffer objects. Instead, they upload data to a new buffer, pre-edited. This is primarily for streaming purposes (https://www.opengl.org/wiki/Buffer_Object_Streaming).

EmJayJay
08-26-2015, 10:11 AM
So,

glBindBuffer(GL_COPY_READ_BUFFER, sameBuffer); // Data to relocate
glBindBuffer(GL_COPY_WRITE_BUFFER, sameBuffer); // Target to write to
glCopyBufferSubData​(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, readDataFromOffset, w​riteDataToOffset, sizeOfDataToRelocate​);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);

And the data will be moved like this?


1, 2, 3, 4, 5, 6 >> 1, 4, 5, 6, 5, 6

GClements
08-26-2015, 11:02 AM
So,
And the data will be moved like this?
1, 2, 3, 4, 5, 6 >> 1, 4, 5, 6, 5, 6

In that case, the source and destination regions overlap, so glCopyBufferSubData() will generate a GL_INVALID_VALUE error.

If the amount of overlap is small, you could avoid the issue by splitting the copy operation into smaller operations which don't overlap. But if the shift (difference in offsets) is small, you may need to use many small copy operations, which is unlikely to be efficient.

And as Alfonse points out, the copy operation can't commence until the implementation has finished reading from the buffer (the implementation may block so long as there are pending reads for any part of the buffer, not just the part being modified).

Copying into a new buffer avoids both of these issues.

If the buffer is sufficiently large that creating a new buffer of the same size is problematic, you can create a new buffer which is large enough to hold the amount of data being moved. That avoids the first problem but not the second.

Ultimately, if the amount of data being moved is large, the only "good" solution is to find a way to avoid the move altogether (e.g. not requiring the data to be contiguous).