Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Contiguous memory, OpenGL, and how are you wrapping your vertices?

So, a critical requirement for OpenGL programming is that you store your vertices in a fashion that guarantees contiguous memory. I've read a couple decent books lately by professional graphics programmers, and both of them used a variation of the same idea: packaging vertices into a struct of 3 floats, x,y,z, and then packaging multiple vertices into either a c-style array or std::vector of these structs. And it works.

But I've seen it said time and again on this site that a struct does not guarantee memory contiguity. It has been said that if your struct contains all floats then they will probably be contiguous, but it is not guaranteed. The array and std::vector do guarantee it, but that's irrelevant if what you are putting into the array or vector is not contiguous.

For production code, I would expect that "probably" doesn't cut it. So despite the suggestion in these two books, which are clearly geared more for learning, I'd like to know what are some other good techniques for easily organizing vertex data in a way that guarantees contiguous memory, or, I'd accept the advice that I shouldn't worry about this, that probably should be good enough.

What are other common and good methods used in the graphics field?

like image 645
johnbakers Avatar asked Apr 12 '13 01:04

johnbakers


2 Answers

So, a critical requirement for OpenGL programming is that you store your vertices in a fashion that guarantees contiguous memory.

No not really. Contiguous memory saves space, but as long as the stride (distance in bytes) between attributes is the same between all elements, this thing will work.

What are other common and good methods used in the graphics field?

Simple, plain, flat arrays of primitive data types, like std::vector<float>, or std::vector<char> if you just want a hunk of memory in which you spread out the data manually contigously. You can wrap this is in a class nicely with getter and setter methods and iterator interfaces that abstract the the offset and stride calculations.

You can also use a struct if you can use compiler extensions to specify its memory layout. For example GCC's __attribute__((packed)) will make a tight struct of the elements without gaps between.

like image 88
datenwolf Avatar answered Oct 26 '22 09:10

datenwolf


OpenGL Mathematics Library, glm, has the guarantee that its vectors are contiguous and simple in memory, which I personally use to store vertices in:

std::vector<glm::vec3> positions;
std::vector<glm::vec2> texCoords;

It also has an utility to safely cast the addresses of its structures in OpenGL glXXXv functions.

If you want to have everything in one VBO, you would have to create some sort of compound struct, because I am afraid that std::tuple<glm::vec3, glm::vec2> is not up for the challenge, which is a bit sad.


As it seems, the glm behaviour is not backed by the standard, that might have changed with C++11 and alignas() though. However, you can hardly do better in terms of aligning structs, I guess, and the suggested static_assert should prevent you from shooting yourself in the foot.

like image 2
Bartek Banachewicz Avatar answered Oct 26 '22 08:10

Bartek Banachewicz