5

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?

genpfault
  • 51,148
  • 11
  • 85
  • 139
johnbakers
  • 24,158
  • 24
  • 130
  • 258
  • In addition to any other precautions you might take, throw this in your code: `static_assert(sizeof(vertex) == sizeof(float) * 3, "vertex not properly aligned");` -- If, upon any modification to your tool chain, your assumptions ever fail, you will be notified upon compilation. – Benjamin Lindley Apr 12 '13 at 01:24
  • It might not be guaranteed by the C++ standard but it might be specified by the ABI "standard" on a particular platform. Which means that once you've established it works on a platform it's not going to change unpredictably or it would break all compiled libraries. Basically the C++ standard isn't the only standard that applies, each platform has a standard for these things. Even if it's not a written, published standard its still not going to be easily broken. Of course you have to be sure that when porting to a platform your assumptions are correct, but after that I can't see it breaking. – jcoder Apr 12 '13 at 10:49

2 Answers2

5

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.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Interesting, thanks. Would you happen to know of any good examples or sample code that might feature a wrapper class such as you mention? – johnbakers Apr 12 '13 at 01:31
2

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.

Community
  • 1
  • 1
Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135