Jump to content
  • Advertisement
Sign in to follow this  
Funkapotamus

VBO Size Questions

This topic is 4401 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My research tells me that it's best to keep a VBO under 6-8 megs. However, none of my findings are very current, so I have no way to know if this figure is accurate or not. Can someone confirm this? When considering size, assuming 6-8 megs is optimal, does this mean that each individual buffer should be less than 6-8 megs? Or does it mean total sum of all buffers? For example: 1) verts[] + colors[] + texCoords[] <= 6-8 megs Vs. 2) verts[] <= 6-8 megs, colors[] <= 6-8 megs, etc. Assuming I need to render 20,000 quads, would it be better to break things up into smaller chunks? How costly is it to switch pointers and bind different buffers? I ask because I'm optimizing a sprite engine. Currently, I don't discriminate between the "types" of sprites being sent to the engine, and they all get sent to one gigantic VBO. I'd like to break things up into multiple VBOs based on certain logic, and I'm just trying to plan out what's feasible.

Share this post


Link to post
Share on other sites
Advertisement
It's best to have one VBO for your vertex, color and texcoord

Make a struct like


struct MyVertexFormat
{
float x, y, z;
uint color;
float s, t;
}


The order of vertex, color and tex don't matter (I'm told)
Also, it's best that your struct is multiple of 32 bytes so make that


struct MyVertexFormat
{
float x, y, z;
uint color;
float s, t;
float padding[2];
}


I think 1 to 8 MB sounds good. nVidia says not too small and not too big.

Share this post


Link to post
Share on other sites
The size of the struct shouldn't have any effect over the size of the VBO on the card. Or am I misunderstanding the reason behind making the struct a certain size?

Actually though, I'm using Java so I can't use structs. I hope I wasn't confusing anyone with my "array math" example. To put it another way, I was wondering if the size is important due to data transfer or data storage.

For example, when I use glVertexPointer(), should the pointer be 6-8 megs? If so, this would imply that it's better to transfer 6-8 megs to the card at a time.

If the whole VBO must be 6-8 megs (glVertexPointer, glTexCoordPointer, etc), then it tells me that the card prefers storing VBOs in chunks of 6-8 megs.

Share this post


Link to post
Share on other sites
"The size of the struct shouldn't have any effect over the size of the VBO on the card. Or am I misunderstanding the reason behind making the struct a certain size?"

That's correct. When I said it should be multiples of 32 bytes, it's for memory alignment on ATI cards and the GPU accesses VRAM moer quickly. The information comes from ATI, in some pdf, distributed at GDC or some event.

"Actually though, I'm using Java so I can't use structs. I hope I wasn't confusing anyone with my "array math" example. To put it another way, I was wondering if the size is important due to data transfer or data storage."

I don't know about Java, but without struct, maybe you can use class. They are essentially the same thing on C++.
Both reasons can apply.
The size is important for memory management. There might not be enough VRAM so the VBO goes into AGP memory or RAM. If VBO is too big, the driver will not work too well.
If you are using streaming VBO, it might work better for the driver to push the smaller VBO to VRAM, instead of a 100 MB VBO

Memory management is really a driver thing. The GPU doesn't care how big the VBO is. The GPU prefers data that is local (xyz, color, s, t all close together)

Share this post


Link to post
Share on other sites
I thought I would just point out that you can only bind one buffer at a time, which means that you always need to consider position+normal+texture as a whole.

Share this post


Link to post
Share on other sites
Quote:
Original post by rick_appleton
I thought I would just point out that you can only bind one buffer at a time, which means that you always need to consider position+normal+texture as a whole.

That doesn't matter beacuse you can set the pointers before the draw call [smile].
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glNormalPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
glTexCoordPointer(...);
glDrawElements(...);

@OP: However, as everyone has pointed out, it's good practice interleave the data as you gain better cache behavior.

Share this post


Link to post
Share on other sites
Quote:
Original post by deavik
Quote:
Original post by rick_appleton
I thought I would just point out that you can only bind one buffer at a time, which means that you always need to consider position+normal+texture as a whole.

That doesn't matter beacuse you can set the pointers before the draw call [smile].
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glNormalPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
glTexCoordPointer(...);
glDrawElements(...);

@OP: However, as everyone has pointed out, it's good practice interleave the data as you gain better cache behavior.


I thought you could only use a single buffer, so I checked the specs. Turns out you are correct (emphasis mine)!

Quote:
specs
In the case of vertex arrays, this extension defines not merely one
binding for all attributes, but a separate binding for each
individual attribute. As a result, applications can source their
attributes from multiple buffers
. An application might, for example,
have a model with constant texture coordinates and variable geometry.
The texture coordinates might be retrieved from a buffer object with
the usage mode "STATIC_DRAW", indicating to the GL that the
application does not expect to update the contents of the buffer
frequently or even at all, while the vertices might be retrieved from
a buffer object with the usage mode "STREAM_DRAW", indicating that
the vertices will be updated on a regular basis.

Share this post


Link to post
Share on other sites

Perhaps the bit about 32 byte vertices was gleaned from this? http://www.ati.com/developer/gdc/PerformanceTuning.pdf

I wonder though, if I have only 4 floats to store per vertex is it really worth doubling the size of my buffer with padding? If I have only 1 is it worth 8x'ing the size?

Thanks, ~SPH

Share this post


Link to post
Share on other sites
I think I saw a slightly different slide. If 32bytes is a whole multiple of your vertex size (so vertex size = 16byte or 8 byte), then you are fine also.

Share this post


Link to post
Share on other sites
You would have to benchmark. Typically, people use texcoord (st) and normal (xyz) and vertex(xyz) and perhaps color (rgba) so it comes close to 32 or just over 32.
The slide says this is not good.

It's only worthwhile to make the change if your app will benifit and high end games need it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!