OpenGL defines, very clearly, what the byte layout of a std140
interface block is. All you have to do on the C++ side is provide data in accord with that layout. If you can define a struct that your compiler will match with std140
, then you're fine. How do you do that?
You have to know the rules that your compiler uses to lay out types.
C++11 defines a concept called "standard layout types". If you follow certain rules, your types are standard layout. Now, this doesn't really mean much for knowing exactly how they are laid out in memory. The only things C++ tells you about standard layout types with regard to layout is that empty base classes are ignored (so long as it remains standard layout) and that the first NSDM will be at the very beginning of the class. That is, there will never be padding at the front.
The other thing the standard says is that NSDMs of the same access class will be allocated in order, with later ones having larger offsets than earlier ones. And since you're not allowed to have different NSDMs of different access classes in standard layout types, you can rely on them being laid out in the order specified.
But that's it, as far as the C++ standard is concerned. [class.mem]/13 states that implementations can add padding between members for various reasons.
Informally however, the rules of "standard layout types" give you a good guideline to know when such padding won't be added. Follow the rules of standard layout, and you can assume, for most systems, that your class's layout will be as tightly packed as the sizes and alignments of the types being used permit.
Do implementations have to play along? No. But there's really no reason to assume that they won't. And worst comes to worst, you can always check to see how implementations lay types out.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…