PDA

View Full Version : How To get VBO datas from the GPU?



Hellhound
02-01-2004, 06:10 AM
Hello,

i've implemented a VBO based application which renders all geometric datas via VBO. All works fine until now ...

Now i've to change some datas in the VBOs to realize GPU based billboards. The problem i've is how i get the datas back from the GPU?

I've tryed the glGetBufferSubDataARB but it fails (always get NULL)... Knows Anyone a solution?

Thx in advance,
Christian

zeckensack
02-01-2004, 07:23 AM
I've tryed the glGetBufferSubDataARB but it fails (always get NULL)... Knows Anyone a solution?Sounds fishy. Can you post that piece of code?

However, I don't think you should do it that way. You supplied the VBO contents in the first place, so you can easily keep a private copy of that data. This way you don't need to call GetBufferSubData at all. This is going to be more efficient, too.

Hellhound
02-01-2004, 07:33 AM
Sounds fishy. Can you post that piece of code?

Ok, here is the testcode fragment:



//Build and binding the VBO
glGenBuffersARB( 1, pMeshData->getVBONameID());
glBindBufferARB( GL_ARRAY_BUFFER_ARB, *pMeshData->getVBONameID());

glBufferDataARB(GL_ARRAY_BUFFER_ARB, pMeshData->getVertexCount()*3*
sizeof(float), pMeshData->getVertices(), GL_STATIC_DRAW_ARB );

// The same for texture
glGenBuffersARB( 1,pMeshData->getVBOTextureNameID());
glBindBufferARB( GL_ARRAY_BUFFER_ARB,*pMeshData->getVBOTextureNameID());

glBufferDataARB(GL_ARRAY_BUFFER_ARB, pMeshData->getVertexCount()*2*
sizeof(float), pMeshData->getTextureCoords(), GL_STATIC_DRAW_ARB);


// test to get the datas back from GPU

GLvoid* vboPointer = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB);

int vboSize=0;
glGetBufferParameterivARB(GL_ARRA_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &vboSize);

// Try to get subdata
glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, vboPointer, vboSize, vboData);

// clear memory
delete pMeshData->getVertices(); pMeshData->setVertices(NULL);
delete pMeshData->getTextureCoords(); pMeshData->setTextureCoords(NULL);



This is going to be more efficient, too.

By doing it in that whay i had to use glBindBuffer once again each frame to move the datas back in to the GPU? I've read something from NVIDIA that this is overhad
... for that reason i will manipulate the datas directly in the GPU memory ...

Enbar
02-01-2004, 09:07 AM
It's invalid to GetBufferSubData while the buffer is mapped. If you want to use GetBufferSubData don't map the buffer. Or map the buffer and use the pointer returned to read and manipulate the data directly.

That said both of these options can be very expensive since they require syncing the cpu and vpu so you can end up idling the hardware. It would be much better to keep a copy and maniulate that even if you need to do a few extra binds.

In gerneral remember that mapping requires idling of the hardware unless you make a bufferData call with null pointer.

Hellhound
02-01-2004, 09:26 AM
Originally posted by Enbar:
It's invalid to GetBufferSubData while the buffer is mapped. If you want to use GetBufferSubData don't map the buffer. Or map the buffer and use the pointer returned to read and manipulate the data directly.

I've tried to use GetBufferSubData without the mapped pointer but it will not work too. And how i can use the MapPointer? Its an void-Value without any data? How can i use it to get the vertices?

Ok, u're the 2nd one who tells me, that my way is inefficient and i should use a copy of my VBO. No problem, but how can i use it with an existing VBO? The only way i know is a new bind-operation wich is cheap ...

Have u got an example for one of these ways?

That said both of these options can be very expensive since they require syncing the cpu and vpu so you can end up idling the hardware. It would be much better to keep a copy and maniulate that even if you need to do a few extra binds.

In gerneral remember that mapping requires idling of the hardware unless you make a bufferData call with null pointer.



[This message has been edited by Hellhound (edited 02-01-2004).]

zeckensack
02-01-2004, 02:06 PM
Originally posted by Hellhound:


GLvoid* vboPointer = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB);

int vboSize=0;
glGetBufferParameterivARB(GL_ARRA_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &vboSize);

// Try to get subdata
glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, vboPointer, vboSize, vboData);
You're trying to Get while the buffer is mapped. Don't.
You're using vboPointer as the second argument to GetBufferSubData. This is supposed to be a byte offset into the vbo, i.e. the amount of bytes you want to skip, counting from the start of the VBO. If you want all data in the VBO, use 0.

What's vboData? You didn't include the declaration. This is supposed to be a pointer to system memory, which you must allocate. The GL implementation will copy the VBO contents to the memory region that is pointed to.

Suggestion:
float* vboData=(float*)malloc(vboSize);




// clear memory

delete pMeshData->getVertices();
delete pMeshData->getTextureCoords();This isn't related to your issue. But it is, most likely, wrong and will cause memory leaks. I take it you allocated these memory regions with new data_type[some_integer]. If you did, you need to use delete[] to deallocate them.

Eg

delete[] pMeshData->getVertices();


By doing it in that whay i had to use glBindBuffer once again each frame to move the datas back in to the GPU? I've read something from NVIDIA that this is overhad
... for that reason i will manipulate the datas directly in the GPU memory ...It doesn't matter either way. If you want to manipulate the data at all, you'll have to bind. MapBuffer will only work for the currently bound VBO, just like Buffer(Sub)Data.

zeckensack
02-01-2004, 02:17 PM
Originally posted by Hellhound:
Its an void-Value without any data? How can i use it to get the vertices?You need to get more familiar with your programming language.
The return type is a pointer to void. That doesn't mean that it points to nothing. What it means, is that you can't go and write


//won't compile
void* map_pointer=glMapBufferARB(<...> );
map_pointer[0]=1.0f;
Think about it as an unspecified type. You provided the data in the VBO, so you know what type it really is. Cast the pointer to that type.


//will compile
float* map_pointer=(float*)glMapBufferARB(<...> );
map_pointer[0]=1.0f;
map_pointer[1]=<...>;Or better yet


struct Position
{
float x,y,z;
};

Position* map_pointer=(Position*)glMapBufferARB(<...> );
map_pointer[0].x=1.0f;
map_pointer[0].y=...


Ok, u're the 2nd one who tells me, that my way is inefficient and i should use a copy of my VBO. No problem, but how can i use it with an existing VBO?Forget about the potential cost of the bind. You can't avoid it, no matter how hard you try.

You already have your data. pMeshData->getVertices() and pMeshData->getTextureCoords(). This is the same data that's in the VBOs, and it's a lot easier for you to access.

Hellhound
02-02-2004, 01:24 AM
All works fine now, thx 4 u're help ;o)