How do I get the data out my std::vector and use it in OpenGL?

Started by
12 comments, last by Cornstalks 12 years ago

A structure with 3 floats could very well be padded out to four floats.

“Very well” is a bit optimistic. The very few cases in which this is possible are very exceptional and fully under your control. Anyone using __declspec() should know why this is being used, and, outside of that, #pragma pack defines the results of alignment and padding very clearly.

If you set packing to 1, neither the structure nor the members inside it will have any padding. Alignments are defined as min( packing, sizeof( TYPE ) ). Meaning that a packing of 8 still results in floating being aligned to 4-byte boundaries.

This is guaranteed behavior because it is important for certain operations that this pragma was specifically designed to address.

Giving newbies unnecessary concerns by saying it “very well” may be padded out is not a good idea. “It can be padded out (without your explicit request) on 64-bit target compiles under certain circumstances that most will never encounter, and even then it can be reliably handled,” might be a better way to put it.


L. Spiro


P.S.: When I refer to newbies I don’t mean anyone here including the topic poster; I was thinking about anyone stumbling onto this topic via Google search etc.

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

Advertisement
No, I think _you're_ building a straw man. This is exactly the point I'm trying to make, and nothing else other than the aforementioned. He's using no compiler pragmas or declaration specifications. The standard says it's implementation defined, and could pad it to a million bytes. I know there are pragma directives and declaration options that can be used. There's no point in casting aspersions on my intelligence based on how I word it. My point is, if you leave it to assumptions, then one day, it just might break and you'll have to rewrite. If a beginner realizes this works for _majority_ of the compile targets, then what stops them from having a structure containing single bytes, like

struct {
uint_8 r;
uint_8 g;
uint_8 b;
}Color;

and passing it to OpenGL, thinking they'll all fall one after another? The compiler should pad. And I appreciate the condescension, but there's no confusion. This "don't confuse the newbie" mentality will bite him. Sure, because there are three 4 byte floats on a 32bit system, it more than likely will not maybe possibly add padding that it could. We'd consider the compiler broken, because it is supposed to be optimal, but it simply could. I know this is just inviting people to nitpick, but if he has all of his code working, and has a decent engine, and decides to use SSE to speed up his transformations, he might choose to align to 16 bytes. This code will break if he uses the wrong stride, and assumes it is laid out like an array, and he must go back and fix all of it. I've read my compiler's documentation on it, and the language standard. Who hasn't? In this case, it has no reason to pad, but if it does, then it may, and I typically hope it would and plan for it. All I'm saying is not to make an assumption, that might not be true all of the time. It'll optimize in your best interest, but that might not always hold true. Since when is not making assumptions bad advice when the API acknowledges that this condition can happen and allows you to work around it, with 100% certainty that it will work?

And once again, the answers ignore the fact that in this case, it probably won't pad, but in my example above, it might. It doesn't have to, but it might. These arguments are taking one case to misconstrue my argument that this isn't always safe. Not just if he uses the same code on different targets or compilers, but if he makes a different structure with different members, and assumes they're tightly packed because someone told him one such case worked, so all of them must work.

Anyway, this witch hunt aside, what about my advice that if he is looking to use an array of floats, that he should use an array of floats, and if he is going to use the array of structures, then he should set up the call to use the stride like an array of structures, and not rely on an array and a structure to have the same representation? This sounds like a pretty solid argument to me, but the straw man of what a compiler will likely do is clouding the conversation. It's this kind of squabble that keeps me from posting here; few people read my posts in entirety, and they'll ignore my advice to start an argument. If he sets up the stride properly, or use an array of floats, he'll avoid the problem entirely. Right now, he's using a mix of the two, by not having the correct stride, and using structures. I'm not posting here for my benefit, I'm advising that he use the tools properly. Somehow, the correct answer ballooned into people trying to earn reputation by browbeating.

In addition:

The compiler will not align each member to 8 bytes. It will assume that because X&Y are 8 bytes, it should just pack them into a single 8byte chunk. If you set it to 16, the size of the struct is still 12 bytes, and X/Y/Z will still be continuous. The only (purely theoretical) problem would occur if your compiler offered a struct member alignment of 5 bytes (or something equally silly). In theory (only), that could lead to a structure size of 14. Since C++ compilers only offer power-of-2 alignments, it is impossible for bytes to be inserted between the variables.


... The compiler will likely not put padding between x, y, or z, but likely will put padding between z and the next x...


Once again, I get the feeling that you skimmed my post, and didn't read it in entirety. This has to be the definition of a straw man; you're criticizing me for believing things I explicitly said were unlikely. I essentially indicated that x, y, and z will have a 99% probability of being contiguous, aside from the edge cases outlined above. Then you ignored my point, and criticized me for a fictional argument that I was never making. On a 32bit system, although the compiler is allowed to, it most likely will not align each member to a value greater than four bytes. I am not arguing this, so I don't know to whom you are replying.
I wasn’t being condescending, but if that is what you appreciate-

My concerns were real. I don’t want to see some beginner getting too nervous about this topic based on your suggestion, particularly with the example you provided. As I mentioned, unrequested padding beyond 4 bytes is extremely rare across all compilers, and will only ever rear its head on 64-bit platforms, and even then it is still rare as most compilers still prefer to pad to 4 bytes for compatibility.

Your second example above is a more realistic case for padding, but can still be manually handled via #pragma pack.

You aren’t wrong. People should be aware of padding. But if it is worth mentioning padding, it is equally worth mentioning #pragma pack.


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='Ectara' timestamp='1334163867' post='4930306']
Might I also add that passing a pointer to a structure of float data and using it as a float array might have undefined results.


1. a C++ compiler that inserts padding in a struct containing nothing but floats is one that is horribly broken.
[/quote]
No it's not. Not according to the C++ standard, at least.

I don't get why people (particularly RobTheBloke) are so against the valid point that Ectara raised about padding. Yes, it's unlikely that the compiler will pad a structure of nothing but floats, but that doesn't change the fact that naively casting the structure to a pointer and using it like an array is undefined behavior (which is what the OP is doing).

Yes, padding can be controlled with compiler flags, but the OP isn't doing that right now, and until he does, he needs to worry about potential padding if he's going to write robust, valid C++ code.

No sense in starting a holy war about this. I think a lot of the disagreement here is caused by people just wording things poorly. Take a step back, all, and breathe. I think L. Spiro's last post has a nice summary of what the last 6 posts have been trying to say.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

This topic is closed to new replies.

Advertisement