C++ struct as value in array, what about cross platform padding?

Started by
12 comments, last by Ectara 12 years ago
Certain functions, for example glBufferData takes a pointer to an array, for example with x, y, z, tex and so on. It's convenient to store these values in a statically typed struct, and I've seen several developers do this. But the problem is that a compiler can insert padding into a struct on an implementation basis. You could use pragma pack, but its compiler specific. How do you solve this in an efficient way?

I'm on my phone, so I apologize for any weirdness.
Advertisement
As I see it your two best options are likely:
1. Simply don't worry about padding until it actually has become a bottleneck. Use sizeof and let it be. Might be a waste of time to worry about it.
2. If you know it's a problem use pragma pack or whatever your current compiler requires and don't worry about compiling on some different compiler until you actually need it. Add ifdef for specific compilers when you do.

How do you solve this


Solve what exactly?
Solve what exactly?
That your struct layout might not match your idea GL vertex layout.
e.g. Given a vertex layout that has float x/y/z position, 8 bit tex-coords, and float RGB colour, we could write this structstruct Vertex {
float x, y, z;
unsigned char u, v;
// most compilers will insert padding here, e.g. "char _pad_[2];"
float r, g, b;
};
The problem is that because of the padding, our struct doesn't match the original description, so you can't give it to GL.

To solve this, either use pragma pack (it is fairly cross-platform, I use it often at work), or simply don't use structs like this ;)
The most applicable example for this that I considered was also vertex packing for OpenGL.
In my case I store everything in an LSUINT8 * array (LSUINT8 = unsigned char).
I can then enforce my own alignment conditions and be sure they are always the same alignment on every platform.

OpenGL is going to accept any stride you give it, so if you are aware that certain platforms like certain alignments on your data types, and would otherwise adjust your structures accordingly, you can handle this type of alignment manually with little effort, but guaranteed results.
If you don’t handle these, you are still guarantee that your code will work anyway, even if it is a little slower.
If it were to crash due to floats not being 4-byte aligned (hello armv7 without floating-point library calls), at least the crash is easily traceable to its actual source. Without crashing, you would be left with jumbled OpenGL ES 2 graphics and cranking up your puzzler.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid


[quote name='Rene Z' timestamp='1332245371' post='4923588']Solve what exactly?
That your struct layout might not match your idea GL vertex layout.
e.g. Given a vertex layout that has float x/y/z position, 8 bit tex-coords, and float RGB colour, we could write this structstruct Vertex {
float x, y, z;
unsigned char u, v;
// most compilers will insert padding here, e.g. "char _pad_[2];"
float r, g, b;
};
The problem is that because of the padding, our struct doesn't match the original description, so you can't give it to GL.

To solve this, either use pragma pack (it is fairly cross-platform, I use it often at work), or simply don't use structs like this ;)
[/quote]
For the record, unless padding is inserted in the middle of the doublets/triplets, the padding between the texture coordinate and the color is no problem for OpenGL. That structure is, in practice, perfectly fine.

For the record, unless padding is inserted in the middle of the doublets/triplets, the padding between the texture coordinate and the color is no problem for OpenGL. That structure is, in practice, perfectly fine.


How do you mean 'is no problem' for OpenGL? It doesn't know anything about your struct. Do you mean that you would use stride = sizeof(struct) and then offset according to what field you are interested in? Or something else? offsetof seems to be somewhat deprecated / frowned upon, and even so it might not be possible if the padding is in the wrong place?


OpenGL is going to accept any stride you give it, so if you are aware that certain platforms like certain alignments on your data types, and would otherwise adjust your structures accordingly, you can handle this type of alignment manually with little effort, but guaranteed results.


How do you mean, handle with little effort? How would you handle it?

Cheers :)

That your struct layout might not match your idea GL vertex layout.
e.g. Given a vertex layout that has float x/y/z position, 8 bit tex-coords, and float RGB colour, we could write this structstruct Vertex {
float x, y, z;
unsigned char u, v;
// most compilers will insert padding here, e.g. "char _pad_[2];"
float r, g, b;
};
The problem is that because of the padding, our struct doesn't match the original description, so you can't give it to GL.

To solve this, either use pragma pack (it is fairly cross-platform, I use it often at work), or simply don't use structs like this ;)


Couldn't you solve this by adjusting the stride when calling glVertexPointer, glTexCoord, etc. using offsetof?

[quote name='Brother Bob' timestamp='1332254622' post='4923630']
For the record, unless padding is inserted in the middle of the doublets/triplets, the padding between the texture coordinate and the color is no problem for OpenGL. That structure is, in practice, perfectly fine.


How do you mean 'is no problem' for OpenGL? It doesn't know anything about your struct. Do you mean that you would use stride = sizeof(struct) and then offset according to what field you are interested in? Or something else? offsetof seems to be somewhat deprecated / frowned upon, and even so it might not be possible if the padding is in the wrong place?
[/quote]
OpenGL doesn't know about your structure, but you know about it. No matter how much padding is inserted, the stride in an array of structures is always sizeof() the struct, and offsetof() can be used to get the offset. The stride and the offsets are all you need to properly use the structure in a vertex array.
struct Vertex {
float x, y, PADDING, z;
unsigned char u, v;
float r, g, b;
};


The above is unlikely, but theoretically possible. It's as possible as the compiler inserting a pad between the semantic data (i.e you can fix it with offsetof). If this happens it won't work whatever you do using offsetof?

This topic is closed to new replies.

Advertisement