Inertia's picture

Consistency

Here are some things I bumped into several times and which Imo should really be discussed before locking down the APIs. If these questions were addressed to Fiddler only, I would have used pm. Everyone is invited to voice suggestions|opinions.

1) CLS compliance. It's not ideal that some functions allow the use of uint, while some enforce the use of int.
Example: GL.GenList returns int, but GL.CallList() accepts both: int or uint
Although it will be more work, it would be nice if one could chose whether "compliance" (int) or "best fit" (uint) is desired regarding types. There's really no need to have both around, I believe everyone has a preference between those 2 types and is able to chose one of them.

2.a) reference vs. value. I believe this should be handled consistent throughout all GL helpers added to the API, not some passing by value and some by ref. Only talking about GL overloads here, no changes to the mathlib itself.

Maybe code explains this best:

// it's more cumbersome to write this (and it implies 2* Vector3 are created before GL receives it)
GL.Vertex3( new Vector3(1f, 2f, 3f) );
// might aswell write:
GL.Vertex3( 1f, 2f, 3f ); // which the Vector overload calls internally anyway
 
// in practice you usually created the Vector3 previously to calling GL.Vertex, and this call does not consume memory
GL.Vertex3( ref vec );

2.b) Afaik the primary reason why some commands pass by value is that you may call this: GL.Normal( Vector3.UnitY ); which is a problem with readonly&const when not passing by value. However this could be worked around by adding some private Unit-vectors for internal operation of the math library and allowing the user to pass UnitX etc. by reference. Obviously this could lead to UnitX etc. being modified by the user, so it might be viable to completely remove the public Unit* and Zero fields.

3) I'd really like to see some token named "Undefined", "Null" or "Invalid" in enums like BeginMode, TextureTarget or DrawElementsType (there's more, will make a list if it gets approved ;) ). Currently I do cast 0 to the enum and cast that back for Debug.Assert(). It would be much nicer if those enums had some token that obviously does not belong to GL and is not a valid parameter. i.e. NOT naming this token "Automatic" (the purpose of this is that you can use enums as fields/properties and initialize them to something you can easily distinguish from regular tokens)


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Inertia's picture

Come on guys, I'm not looking for allies to riot against the system here. Short statements of your preference would already be valuable feedback, even if it just states that you are perfectly happy with how things currently are.

Once the API is locked down opinions don't matter anymore.

objarni's picture

Regarding int/uint
[I'm a bit biased coming from a C# background.]
I prefer the uint versions since they state better what my intentions/mind model of the thing I'm passing in / getting out from a method is.

But then again I don't find it a big problem if only the int version stay around.

The problem is the bloat/inconsistency of the current API. So I would really prefer a decision to be made, no matter what it is ... :)

Regarding ref / non ref argument passing
I prefer non-ref versions. Just feels more .NET.

Regarding SomeEnum.Invalid
I don't have an opinion on this issue.

kanato's picture

1) I say, CLS compliance for the win. IIRC you're hardly ever going to have an int larger than 2^{31} to pass in, since things like GenTextures usually start counting from 1. I tend not to use unsigned values, because if I have a field which is only supposed to be positive but can have a negative value, I can use assertions that it is non-negative to catch bugs sometimes.

2.a) I don't really know, but I would think that for small structures, like Vector3, the difference between copying three 32-bit floats vs. one 32-bit (or 64-bit) pointer to a Vector3 structure is only going to matter if you're copying tens or hundreds of thousands of them in these function calls. It seems like the ref overload would only be useful if you were already doing something wrong, like using immediate mode. Even for larger structures, like Matrix4 I

2.b) Is there a reason things like Vector4.UnitX aren't set as readonly? I think using readonly and passing by value would be the better way to go.

3) I agree with you, having an Undefined or Invalid token in enums is a good idea.

Inertia's picture

should probably add my votes too:

1) int, because the way it is atm you usually end up using it anyways. Most likely a caching strategy is needed long before you reach the 10.000st generated handle.

2) ref, because trading extra memory for worse performance is a pretty bad deal. Most people want to do 'realtime' applications.

3) obviously: yes, please! :)

-------

Regarding immediate mode, I found no performance difference in wrapping a VertexArray into a DL in comparison to wrapping immediate mode calls into a DL. It would be interesting to see a memory dump of both DLs and see if there's actually any difference at all, after the display list compilation optimized the data.