PDA

View Full Version : Stuffing Elements into combined Vertex Array...



scratt
02-03-2009, 07:33 PM
Can someone confirm if I am breaking the rules here...

I modified my model loader so that it stuffs the data that would have gone into a GL_ELEMENT_ARRAY into part of a GL_VERTEX_ARRAY.

So in effect I have Vertices, Normals, TexCoords and then Elements all in one VBO.

It certainly works as the models draw fine. I keep the element array binding to 0, and simply use the correct offset into the vertex array when I call glDrawElements...

I suspect I am getting away with it because my elements are ints and that is the same size as floats, which is the format for the rest of the VBO.

Is this legal, or is this going to come back and bite me later?

Thanks for any feedback!

Jan
02-04-2009, 01:28 AM
The GPU really doesn't care, whether you have ints / floats or whatever at the end of an array, where it doesn't read it anyway. They do not need to be the same size, at all. You can for example but 3 byte colors into such an array and it will work, too (though horribly slow, because 3 bytes breaks any alignment).

The more interesting part is, that you use that array as an element array, and therefore bind it to index 0. I would suspect, that you are in a grey area here, because some drivers might simply expect, that in this case your index buffer is in main memory, not in a VBO and therefore most certainly on the GPU. This might lead some drivers to the idea to first copy that buffer into GPU memory for faster access. Whether this in turn might give you bad performance or even crashes, i don't know, but it is certainly an unnecessary risk to take.

The question is, how do you give it the correct offset ? glDrawElements expects a pointer, when bound to 0, but an offset, when bound to a VBO. If you simply give it the same offset as if ELEMENT_ARRAY was bound to a VBO it should not work, at all. However, you can't really give it a pointer, because you don't have one, unless you map it, but this pointer is not guaranteed to stay constant over time.

I would say this is indeed a very bad idea and i am wondering why you did that in the first place. What advantage do you get/expect from putting both data into the same array?

Jan.

scratt
02-04-2009, 02:07 AM
The GPU really doesn't care, whether you have ints / floats or whatever at the end of an array, where it doesn't read it anyway. They do not need to be the same size, at all. You can for example but 3 byte colors into such an array and it will work, too (though horribly slow, because 3 bytes breaks any alignment).

Actually thinking about that you are right.. The offset is a byte offset so the driver really doesn't care. And int, float, or 4 bytes, or whatever all get moved around the same way when you store the data as it's just a memcpy at the end of the day.


The more interesting part is, that you use that array as an element array, and therefore bind it to index 0. I would suspect, that you are in a grey area here, because some drivers might simply expect, that in this case your index buffer is in main memory, not in a VBO and therefore most certainly on the GPU. This might lead some drivers to the idea to first copy that buffer into GPU memory for faster access. Whether this in turn might give you bad performance or even crashes, i don't know, but it is certainly an unnecessary risk to take.

I think I may not have explained this very well.
Actually what I do is bind the vertex array as an element array also, using:

glBindBuffer(GL_ELEMENT_ARRAY, VertexBuffer);
That's what I explained badly when I meant I bind the element array to 0. Very confusing I know. My bad. Sorry.

I then have a table of offsets for vertices, normals, texcoords, and elements into that one VBO (which is bound twice) which are then updated with calls to glxxPointer functions.


I would say this is indeed a very bad idea and i am wondering why you did that in the first place. What advantage do you get/expect from putting both data into the same array?

In effect it's just one less VBO, but the same number of bindings....
So only a cosmetic advantage I guess!

Thinking about it it should be legal and makes sense: I guess my question should have been is it ok to have the same VBO bound to both Vertex and Element Arrays.

_NK47
02-04-2009, 02:36 AM
i must admit this is quite a cool idea in terms of just trying it out and be familiar with, though it never entered my mind. i would still use it as it was intentionally designed by the people for some reasons (no doubt they had some) and separate the buffers but all in all good thought/hack scratt. ;)

Jan
02-04-2009, 03:29 AM
Yeah, that "I keep the element array binding to 0" really confused me. Well, i would say that your approach _should_ work. Problem is, what should and what does work, is always a good question in OpenGL. I would not take the risk to have it break on some GPU / driver or get worse performance for whatever reason. Putting it into two buffers is easy to do and _should_ ;) always work as intended.

This whole thing reminds me of various situations, where i just implemented some canny new optimization, where i was not sure, whether it is 100% safe, only to have something break later and wonder whether it was my new optimization or something different. That can really drive you crazy!

Jan.

scratt
02-04-2009, 03:53 AM
He He. I learnt a new word yesterday. "Grue"

Apparently they are little beasties that lie in hiding in the dark to get you later.

I guess I might be feeding a baby Grue. ;)

I like the elegance of it, but will plaster the top of the header file with ***WARNINGS*** ;)

skynet
02-04-2009, 10:21 AM
Just to shed some light on this:

It is for sure possible to put vertexdata and indexdata into the same buffer object. Just be sure to bind the same VBO to _both_ GL_ARRAY_BUFFER_ARB and GL_ELEMENT_ARRAY_BUFFER_ARB.
I'm doing this for a long time now and it never gave problems.

Once, there was a time when GPUs couldn't handle indices in video memory. I think this regards to pre-GF3 cards. It was this time when it was said that it is a bad idea to put vertex and index data into the same buffer object, for obvious reasons.