|
View previous topic :: View next topic
|
| Author |
Message |
jai
Joined: 10 Apr 2007 Posts: 247
|
| |
Posted: Wed Jan 27, 2010 5:49 pm Post subject: GL typedefs best practice? |
 |
|
Hi all, I have been a busy beaver porting over the very few worthwhile bits of MyFirstRenderingEngine® by Hasbro/me from Java to C++. I have looked at C++ many times and walked away in fear, lol. But working intensely on computer graphics the last few years ( even it was just in Java ) really taught me a lot about programming. Anyway, long blabber short, I was able to tackle C++ this time, and it actually made sense this go'round; but I have a best practices question about intrinsic types and typedefs provided by libraries like OpenGL. If this were just a technical question, I'd put it on another forum or something so as not to waste your time, but since this is a best practices question, I'd like to know how the gurus do it, and I'll just mimic that.
In looking through the GL documentation, it says that one can use intrinsic types like int and char * in place of GLchar *, and GLint, etc. Supposedly, if you doggedly stick to the GLtypes you are given a basic promise of platform independence. I read that different platforms may have slightly different data lengths, and that the GLtypes insulate one from that. But, if I'm sticking to intrinsic types, wouldn't that also be platform neutral? I can see where you'd want to use the type supplied by the library for something like Spaceship, or Matrix, but what are your policies for when a typedef can be substituted by the intrinsic basic type? Do you always use the libraries typedef, or the intrinsic, or does it depend on the library?
I am asking about this because for various reasons I need to render on Windows machines, but I develop on a Mac. I'm not asking about the whole of platform independent development as I know that could fill a book, and that would be lame to ask. I just wanted to ask about this one small aspect as I work on fundamental modules so I don't pull my hair out later.
Hopefully this question isn't too noobish and is games/graphics related enough. Thanks fellas. |
|
| Back to top |
|
 |
casey Site Admin
Joined: 18 Dec 2004 Posts: 1768 Location: Seattle
|
| |
Posted: Fri Jan 29, 2010 4:46 pm Post subject: |
 |
|
I am a little bit anal about these sorts of things, so I am always very specific about my types.
I use GL's typedefs for anything that has to go to GL, and similarly, if I'm interfacing with any other library, I try to always explicitly convert to their types when calling their code.
But more importantly, when writing general code, I use a layer of typedefs to insulate myself from platform size changes. My library of choice for this is Brian Hook's Posh, which I include and then typedef to my own syntax.
I typedef int32, int64, etc. and uint32, uint64, etc., things like that, so I can specify exactly the width of the variables. I then _also_ typedef int32x, int64x, uint32x, etc., which I make be the _most convenient_ type for the platform that can hold at least the named value. So, on a 32-bit machine, an int32x would be a 32-bit integer, but on a 64-bit machine, an int32x would be a 64-bit integer, whereas on both machines an int32 is a 32-bit integer.
Does that make sense?
Then my general rule for usage in the code is that the "x" types, like int32x, are used everywhere that doesn't persist, and then the non-x types are used everywhere that does. So in structs that get written to disk or sent over the network, where the exact packing is important because two different platforms may need to read the same data, it's all non-x's. Things like the iteration count in a for loop, x's.
It's not perfect, but it's the best system I've found given C's limitations.
- Casey |
|
| Back to top |
|
 |
Won
Joined: 21 Sep 2005 Posts: 506 Location: New York
|
| |
Posted: Fri Jan 29, 2010 7:18 pm Post subject: |
 |
|
So on a 64-bit machine, I guess you end up with:
| Code: | | typedef int64 int32x; |
But what benefit does that give? On x64, at least, you end up with larger instructions and higher-latency multiplies. I guess then, on x64 you could just do the obvious:
| Code: | | typedef int32 int32x; |
On the other hand, you generally already have a name for int32x:
I guess I'm curious as to what platform/type combinations does this make a significant difference? |
|
| Back to top |
|
 |
sean
Joined: 01 Feb 2005 Posts: 1392 Location: Kirkland WA
|
| |
Posted: Fri Jan 29, 2010 8:22 pm Post subject: |
 |
|
Yeah, I just use 'int' where casey would use 'int32x'.
However, some C comopilers for 64-bit platforms supposedly compile int as 32-bit for back-compatibility, even if 64-bit operations are actually faster (i.e. the 32-bit operations require extra masks/whatevers). In that case, the int32x type would win.
| Quote: | | On x64, at least, you end up with larger instructions and higher-latency multiplies. |
By the "on x64, at least" I think you reveal you know the answer! |
|
| Back to top |
|
 |
casey Site Admin
Joined: 18 Dec 2004 Posts: 1768 Location: Seattle
|
| |
Posted: Sun Jan 31, 2010 7:40 pm Post subject: |
 |
|
Well, the idea is that you have control over all this, right. It's the same reason I don't generally use "unsigned char" to refer to an 8-bit type. Because _maybe_ somebody breaks that at some point.
So while I _could_ use "int" and hope it always works, why not use int32x and then know that if I come across some messed-up platform (probably distributed by Sony, but I don't want to place blame ), I am insulated and can select the appropriate compiler type manually?
Using "int" just seems like bad policy to me. Not to mention the fact that it will screw you already if you do something like compile for 16-bit ARM and were using it for iterators over arrays larger than 65535 elements.
- Casey |
|
| Back to top |
|
 |
sean
Joined: 01 Feb 2005 Posts: 1392 Location: Kirkland WA
|
| |
Posted: Sun Jan 31, 2010 8:43 pm Post subject: |
 |
|
I did say the "int32x" would win in that case. (And obviously it wins porting back to 16-bit platforms, but hey, guess what I absolutely don't care about! The compilers for 16-bit platforms better provide 32-bit pointers and 32-bit ints or we're fucked anyway.)
One thing is that this involves an unrealistic assumption that you know how big your arrays are going to be.
Whether you use int or int32x, when you port to a 64-bit platform and then use the code to iterate over the bytes of a 10GB movie, you're fucked anyway. (Maybe you should use a type "int_array_index" which you can define appropriately for each app?)
That's sort of a worst case, but I think it shows the problem is a little slipperier than it seems.
(Although this amounts to: yes, use GLuint as variables when interacting with OpenGL, and use GLuint to persistently store your GL texture handles unless you really have to stick them in something else to be portable between OpenGL and D3D or something, and just know what you're getting yourself into if you don't use GLuint.) |
|
| Back to top |
|
 |
ryg
Joined: 31 May 2007 Posts: 276 Location: Kirkland, WA
|
| |
Posted: Sun Jan 31, 2010 10:31 pm Post subject: |
 |
|
| casey wrote: | | Well, the idea is that you have control over all this, right. It's the same reason I don't generally use "unsigned char" to refer to an 8-bit type. Because _maybe_ somebody breaks that at some point. |
I think some old Cray machines used to have sizeof(char) == sizeof(basically all integer types) == sizeof(double) == 1, since they couldn't address memory in smaller units than a double.
I don't think that kind of stuff is likely to ever come back again, though. Nowadays, even for SPUs which can only address (and access) memory in quadword units compilers have an 8-bit character type (which requires some gymnastics to load from and especially store to memory) and byte-based addressing conventions. If even Sony is willing to adhere to established conventions that far, the war is pretty much over.
| casey wrote: | | Not to mention the fact that it will screw you already if you do something like compile for 16-bit ARM and were using it for iterators over arrays larger than 65535 elements. |
Is there any 16-bit ARM? There's Thumb which is a 16-bit instruction encoding, but the data path is still full 32 bits.
| sean wrote: | One thing is that this involves an unrealistic assumption that you know how big your arrays are going to be.
Whether you use int or int32x, when you port to a 64-bit platform and then use the code to iterate over the bytes of a 10GB movie, you're fucked anyway. (Maybe you should use a type "int_array_index" which you can define appropriately for each app?) |
That type already exists, in standard C89 and C++, and it's called size_t.
Another thing to note is that if your compiler supports C99 (and by now that basically means "if your compiler isn't VC++") there's stdint.h which has all the typedefs mentioned in this thread, with somewhat different names. They're more verbose than I'd prefer ("uint_least64_t" and "int_fast32_t" are rubbish for something that you intend to use frequently), but other than that it's fine. |
|
| Back to top |
|
 |
jai
Joined: 10 Apr 2007 Posts: 247
|
| |
Posted: Mon Feb 01, 2010 3:28 am Post subject: |
 |
|
Cool. I think I get the idea. Creating a typedef 'layer' does a few of things for me: 1) allows me to create an adapter layer to types found in other software libraries or platforms, 2) allows me to specify exactly what I mean by unsigned 32-bit integer (as opposed to int, which could mean diff. things), and 3) using typedef means the compiler will do type checking.
And, full circle, now I see why the GL guys are creating the typedefs in the first place. They're doing exactly what Casey is doing. They're insulating the GL interface from platform specifics. To gain this benefit, you need to use their types. But Casey is creating one further insulating layer, so that he doesn't have to spend a bunch of time writing boilerplate code everytime he's doing something cross platform, or even across libraries.
You guys probably just saved me many hours. I'm not anywhere near setting up the PC side of rendering, but using this technique, I can make that transition down the road much less painful. Thanks again! |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|