PDA

View Full Version : Updating dynamic vertex buffer (frequently)



SoulSharer
11-15-2012, 09:41 PM
Hello there.
I'm trying to replicate this strategy in OpenGL, but have no clear idea how.


//transfer transformed vertices to GPU (before drawing)
VertexPositionColorTexture *pData = NULL; //destination to copy vertices into

if (SUCCEEDED(m_VB->Lock( 0, 0, ( void** )&pData, m_vertexBufferPosition == 0 ? D3DLOCK_DISCARD : D3DLOCK_NOOVERWRITE )))
{
//move pointer to unused section of vertex buffer
pData += m_vertexBufferPosition * VERTICES_PER_SPRITE;

for (int i = 0; i < batchSize; i++)
{
sprites[i]->FillVertices(pData, i * VERTICES_PER_SPRITE);
}

m_VB->Unlock();
}

So far I've found glMapBuffer and glMapBufferRange (similar to lock operation in directx), but I'm not sure if I understand them right.
When I lock the buffer in DX with flag D3DLOCK_DISCARD I'm sure that if the data in a vertex buffer is currently being used - I will get a new chunk of memory (while GPU keeps using old memory for drawing behind the scenes), will the same happen with glMapBuffer? or should I do it myself? and if so how I should do it? Talking about D3DLOCK_NOOVERWRITE I see it as just mapping the buffer in the range it is not being used, so here glMapBufferRange might work perfectly for the situation.

What do you think?
How would you go about it?

Thanks for any help.

Dan Bartlett
11-16-2012, 03:02 AM
There's some info on this in the wiki (http://www.opengl.org/wiki/Buffer_Object_Streaming#Buffer_re-specification).
glBufferData with NULL as the last argument before mapping will work on all hardware that supports buffer objects, but the other ways are probably neater if you are targeting more recent hardware only.

SoulSharer
11-17-2012, 11:58 AM
Yeah thanks, thats what I was looking for.
Here's another document by Nvidia (in case someone will have the same question): http://coitweb.uncc.edu/~krs/courses/6127/lectures/Using-VBOS.pdf

l_hrabcak
11-21-2012, 06:58 AM
If you are updating the buffer frequently the most important parameter is the usage, in your case you should use GL_STREAM_DRAW. Alternative to D3DLOCK_DISCARD is GL_MAP_INVALIDATE_BUFFER_BIT but you can use it only in glMapBufferRange. Better way is to use multiple buffers with the flag GL_MAP_UNSYNCHRONIZED_BIT, usually four are enough because the driver GPU queue is usually 2-3 frames behind (use fences for syncing). This solution doesn't involve driver's memory management and will save some CPU time. You can use one big buffer too, with your own address management but don't forget the unsynchronized flag.

You can find more in free chapter from OpenGL Insights
http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-AsynchronousBufferTransfers.pdf