Why SDL_TextureID? (Potential performance loss on looking up

Can’t agree more. I would even rewrite my app again if SDL_Texture /SDL_TextureID compatibility could not be somehow achieved.

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. I’m open to changing that though, if people
think the raw access is worth it…On Mon, Jan 18, 2010 at 7:27 AM, hardcoder wrote:

Can’t agree more. I would even rewrite my app again if SDL_Texture
/SDL_TextureID compatibility could not be somehow achieved.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


-Sam Lantinga, Founder and President, Galaxy Gameworks LLC

In fact this same concerns apply to SDL_Window* vs SDL_WindowID, although this is rather not concerned sensitive when drawing the scene.

Sam Lantinga wrote:

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. I’m open to changing that though, if people
think the raw access is worth it…

This is not a good reason IMHO. To make application correct, code has not to use invalid (released) IDs either. Additionally, for C programmers it is natural thing to pass a struct ptr to a bunch of functions operating on it and for C++ers it is natural to wrap them with classes.

Pointer based API would be faster, more natural and consistent. Has my vote :slight_smile:

[…]

Sam Lantinga wrote:

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. I’m open to changing that though, if people
think the raw access is worth it…

This is not a good reason IMHO. To make application correct, code has not
to use invalid (released) IDs either. Additionally, for C programmers it
is natural thing to pass a struct ptr to a bunch of functions operating on
it and for C++ers it is natural to wrap them with classes.

Pointer based API would be faster, more natural and consistent. Has my vote
:slight_smile:

+1

A “safe” API might seem nice at first, but rather than preventing bugs, it can
actually make them harder to find, and thus more likely to be left in the
final release. It might seem nicer that a runtime error is ignored instead of
causing a segfault, but even that is partially an illusion. Maybe not a big
deal in games, but applications dealing with important data are perhaps
better off segfaulting instead of continuing with a broken state,
potentially corrupting data without the user noticing until it’s too late…

In the development phase, a “safe” API might even prevent detection of some
bugs, unless you have full and correct error handling everywhere. (You can’t
really “forget” to check for segfaults on most platforms these days. :slight_smile:

If you want it safe (for rapid development, fault tolerant applications and
the like), you need to switch to a safer language - and then it doesn’t
matter if the underlying APIs are using pointers or IDs, as the language
binding should ensure correct handling of objects.On Tuesday 19 January 2010, at 15.28.04, “hardcoder” wrote:


//David Olofson - Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://olofson.net http://kobodeluxe.com http://audiality.org |
| http://eel.olofson.net http://zeespace.net http://reologica.se |
’---------------------------------------------------------------------’

Pointer based API would be faster, more natural and consistent. Has my
vote
:slight_smile:

+1

I agree too, I thought the ID was the result of a direct mapping to
directx/opengl texture ids, but if this is not the case I see no reason to
keep a double lookup for every texture access, and pass through function
calls when a macro or a direct access to the struct should be enough. Now
SDL 1.3 is still in a state where such a change is possible without too
problems :)–
Bye,
Gabry

[…]

Sam Lantinga wrote:

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. I’m open to changing that though, if people
think the raw access is worth it…

This is not a good reason IMHO. To make application correct, code has not
to use invalid (released) IDs either. Additionally, for C programmers it
is natural thing to pass a struct ptr to a bunch of functions operating on
it and for C++ers it is natural to wrap them with classes.

Pointer based API would be faster, more natural and consistent. Has my vote
:slight_smile:

+1

A “safe” API might seem nice at first, but rather than preventing bugs, it can
actually make them harder to find, and thus more likely to be left in the
final release. It might seem nicer that a runtime error is ignored instead of
causing a segfault, but even that is partially an illusion. Maybe not a big
deal in games, but applications dealing with important data are perhaps
better off segfaulting instead of continuing with a broken state,
potentially corrupting data without the user noticing until it’s too late…

In the development phase, a “safe” API might even prevent detection of some
bugs, unless you have full and correct error handling everywhere. (You can’t
really “forget” to check for segfaults on most platforms these days. :slight_smile:

Agreed. Any abstraction that you can’t get beneath is evil. We’d be better off
converting this to a struct pointer instead of an opaque handle, both for
performance and for debuggability.>----- Original Message ----

From: David Olofson
Subject: Re: [SDL] Why SDL_TextureID? (Potential performance loss on looking up
On Tuesday 19 January 2010, at 15.28.04, “hardcoder” wrote:

[…]

Sam Lantinga wrote:

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. ?I’m open to changing that though, if people
think the raw access is worth it…

This is not a good reason IMHO. To make application correct, code has not
?to use invalid (released) IDs either. Additionally, for C programmers it
?is natural thing to pass a struct ptr to a bunch of functions operating on
?it and for C++ers it is natural to wrap them with classes.

Pointer based API would be faster, more natural and consistent. Has my vote
?:slight_smile:

+1

A “safe” API might seem nice at first, but rather than preventing bugs, it can
actually make them harder to find, and thus more likely to be left in the
final release. It might seem nicer that a runtime error is ignored instead of
causing a segfault, but even that is partially an illusion. Maybe not a big
deal in games, but applications dealing with important data are perhaps
better off segfaulting instead of continuing with a broken state,
potentially corrupting data without the user noticing until it’s too late…

In the development phase, a “safe” API might even prevent detection of some
bugs, unless you have full and correct error handling everywhere. (You can’t
really “forget” to check for segfaults on most platforms these days. :slight_smile:

Agreed. ?Any abstraction that you can’t get beneath is evil. ?We’d be better off
converting this to a struct pointer instead of an opaque handle, both for
performance and for debuggability.

There is one real good reason for doing it the way Sam has it, API
stability. If you give a programmer a pointer he will deference it.
That is especially true when the pointer is part of an API whose
source code is completely public and you can just look it up. That
means that if Sam needs to change the contents of the struct then he
is breaking the API. The contents of that struct may be different on
each platform. Over time tt may turn out that some fields need to go
away and new fields need to be added. That has certainly happened over
the life of SDL.

Giving the programmer an anonymous ID is a warning that he can not
assume anything about the object referenced by the ID. A pointer…
Well, a pointer makes the contents of that structure and everything it
references fair game for the programmer to inspect, change, and use as
he likes. And, it causes problems with memory allocation. If you give
a programmer a pointer, the API can no longer dispose of what it
points to. The memory has to stay around until the programmer frees it
and you have to trust the programmer not to free it while the API is
still using it and to let the API know when he freed it.

Those are both good enough reasons to only give the programmer IDs.

The argument that you have to pay for a look up is not a very strong
argument. The usual way to allocate IDs is to just give the index of
an empty slot in a vector of pointers. When done that way the worst
case is a range test and an add of an integer to a constant pointer
and then fetch the real pointer. That is not heavy lifting. If you can
turn off error checking then you can get rid of the range check.

I would prefer to see SDL use anonymous IDs when ever it possibly can.

Bob PendletonOn Tue, Jan 19, 2010 at 11:56 AM, Mason Wheeler wrote:

----- Original Message ----
From: David Olofson
Subject: Re: [SDL] Why SDL_TextureID? (Potential performance loss on looking up
On Tuesday 19 January 2010, at 15.28.04, “hardcoder” wrote:


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


±----------------------------------------------------------

There is one real good reason for doing it the way Sam has it, API
stability. If you give a programmer a pointer he will deference it.

Make it a void *, then, and have SDL cast it to a real struct pointer
internally. Make sure the struct declaration is not in any public
header. If someone wants to dereference the pointer directly after that,
they get what they deserve when it breaks.

I don’t see a lot of sense in having to maintain an internal table, and
reallocate it as items come and go, deal with gaps in the table when
we’re done with items in the middle, etc.

Giving applications an index into a table isn’t safe, either, as if they
reuse an index from an earlier run of the program they’ll either
overflow the table (bad), or get a valid, but unrelated item from the
table (even worse). You’re more likely to crash if you reuse a pointer
like this, though (in this case: good).

–ryan.

If the structure definition wasn’t present in the public SDL API then
that is a strong indication to the programmer that they should not
dereference it. If they go to the trouble of including a private SDL
header or doing some ugly casting to access such members, well I have
no sympathy for them if they are forced to change their code when SDL
makes changes. =)

Personally, I think consistency is the most important thing. SDL has
always used pointers, so it should probably continue using them.

Another thing: pointers have an obvious “failure” state -> NULL. With
integers, it could be 0 like OpenGL, or -1 (which SDL currently uses
for any function that returns an int IIRC). Consistent APIs are
easiest for the user.

2010/1/19 Bob Pendleton :> I would prefer to see SDL use anonymous IDs when ever it possibly can.

Bob Pendleton

If the structure definition wasn’t present in the public SDL API then
that is a strong indication to the programmer that they should not
dereference it. (…)

Couldn’t express it better myself. Thanks Brian. AFAIK GTK and FFmpeg has it done this way, and it works well.
I think every wise C programmer stays away from dereferencing some struct pointer when it is not defined in public API, this is what C struct forward declarations are made for, aren’t they?
Correct me if I’m wrong, but most of the SDL rookie programmers use binary builds where private headers aren’t present, so they won’t mess with them anyway.

Personally, I think consistency is the most important thing. SDL has
always used pointers, so it should probably continue using them.
(…)
Another thing: pointers have an obvious “failure” state -> NULL. With
integers, it could be 0 like OpenGL, or -1 (which SDL currently uses
for any function that returns an int IIRC). Consistent APIs are
easiest for the user.

Well said, if 1.3 API is supposed to be considered stable it must be IMHO consistent - regarding data types, function parameters, return values… finishing on type capitalization, like SDL_mutex vs SDL_Thread which bugs me a little.

But in case of SDL_TextureID we also performance hit there, which can be more painful than inconsistent API.

Thanks for great feedback everyone,

Best regards,–
Adam

There is one real good reason for doing it the way Sam has it, API
stability. If you give a programmer a pointer he will deference it.

Make it a void *, then, and have SDL cast it to a real struct pointer
internally. Make sure the struct declaration is not in any public header. If
someone wants to dereference the pointer directly after that, they get what
they deserve when it breaks.

In an open source project there is no such a thing as a private
header. Let me say that another way. The concept of a private header
is meaningless in an open source project. Nothing is private when all
the source code is just a download a way.

I don’t see a lot of sense in having to maintain an internal table, and
reallocate it as items come and go, deal with gaps in the table when we’re
done with items in the middle, etc.

There are so many trivial ways to handle that problem that I don’t
even see it as a problem.

Giving applications an index into a table isn’t safe, either, as if they
reuse an index from an earlier run of the program they’ll either overflow
the table (bad), or get a valid, but unrelated item from the table (even
worse). You’re more likely to crash if you reuse a pointer like this, though
(in this case: good).

Ok, you lost me there. How do you have access to an index from an
earlier run of the program? Do you write it out to a file and then
read it back? That doesn’t work to well with pointers either. Or are
you talking about run the application in a loop inside say the main
program? In that case you have the same problem with a pointer.

Bob PendletonOn Tue, Jan 19, 2010 at 1:59 PM, Ryan C. Gordon wrote:

–ryan.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


±----------------------------------------------------------

Bob Pendleton wrote:

In an open source project there is no such a thing as a private
header.

Sure there is. This is a public header:
#ifndef FOO_H_INLCUDED
#define FOO_H_INLCUDED

#endif

This is a private header:
#ifndef FOO_H_INLCUDED
#define FOO_H_INLCUDED
/* Private header. */

#endif
Rainer Deyke - rainerd at eldwood.com

Bob Pendleton wrote:

In an open source project there is no such a thing as a private
header.

Sure there is. ?This is a public header:
?#ifndef FOO_H_INLCUDED
?#define FOO_H_INLCUDED
?..
?#endif

This is a private header:
?#ifndef FOO_H_INLCUDED
?#define FOO_H_INLCUDED
?/* Private header. */
?..
?#endif

LOL!

He who lives in a glass house needs good curtains…

Bob PendletonOn Tue, Jan 19, 2010 at 7:02 PM, Rainer Deyke wrote:


Rainer Deyke - rainerd at eldwood.com


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


±----------------------------------------------------------

Den Tue, 19 Jan 2010 18:35:50 -0600
skrev Bob Pendleton :

In an open source project there is no such a thing as a private
header. Let me say that another way. The concept of a private header
is meaningless in an open source project. Nothing is private when all
the source code is just a download a way.

#ifndef SDL_INTERNAL__DO_NOT_USE_OUTSIDE_SDL
#error This header is for internal use only. It may change at any time.
#endif

If someone goes ahead and defines this anyway, they’ve only themselves
to blame when it breaks somewhere down the road.

  • Gerry

One could put it this way: How far are we willing to go to keep programmers in
line?

The argument could be made that even for closed source projects, there aren’t
really such a thing as a “private” object at the end of a pointer, so
therefore pointers should never be used in an API.

Reverse engineering…! Read some “advanced tricks” programming books for the
old (68k based) Amiga, if you think people would never do this.

(I believe that those books were mostly intended to demonstrate how the OS did
things, for educational purposes, as this machine was more or less intended to
be programmed directly to the metal in performance critical applications. That
however, didn’t stop people from using “tricks” that would invariably break if
you didn’t have the exact right OS version…)

My point is just that there will always be developers who have a habit of
doing things the wrong way, and are even willing to go a long way to do so. I
don’t think one should waste too much time and resources trying to stop them,
as it’s a losing proposition anyway - much like software copy protection…On Wednesday 20 January 2010, at 07.16.49, Gerry JJ wrote:

Den Tue, 19 Jan 2010 18:35:50 -0600

skrev Bob Pendleton :

In an open source project there is no such a thing as a private
header. Let me say that another way. The concept of a private header
is meaningless in an open source project. Nothing is private when all
the source code is just a download a way.

#ifndef SDL_INTERNAL__DO_NOT_USE_OUTSIDE_SDL
#error This header is for internal use only. It may change at any time.
#endif

If someone goes ahead and defines this anyway, they’ve only themselves
to blame when it breaks somewhere down the road.


//David Olofson - Developer, Artist, Open Source Advocate

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://olofson.net http://kobodeluxe.com http://audiality.org |
| http://eel.olofson.net http://zeespace.net http://reologica.se |
’---------------------------------------------------------------------’

I played with this a little tonight, and there are a few reasons why
this isn’t necessarily a good idea.

First, it’s easy to validate an ID, but you can’t necessarily validate
a pointer.

Second, you can potentially reuse a memory address, which means that
if you’re doing comparisons against a stored value, you can
potentially get a false positive.

Third, if we do it for textures, we should probably do it for windows
as well, and we currently pass window ID values through events, which
may be processed after the relevant window is destroyed.

I have this change roughed out, but I wanted to raise these
considerations for discussion before I check anything in.On Mon, Jan 18, 2010 at 7:26 PM, Sam Lantinga <@slouken> wrote:

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. ?I’m open to changing that though, if people
think the raw access is worth it…

On Mon, Jan 18, 2010 at 7:27 AM, hardcoder wrote:

Can’t agree more. I would even rewrite my app again if SDL_Texture
/SDL_TextureID compatibility could not be somehow achieved.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


? ? ? ?-Sam Lantinga, Founder and President, Galaxy Gameworks LLC


-Sam Lantinga, Founder and President, Galaxy Gameworks LLC

You might also have textures or windows bound to other objects that
don’t have a life cycle exactly synchronized with that of the SDL
objects, and you may want SDL API calls to fail rather than crash.

This could even happen internally, with the native window
representation and handling events in a separate thread.On Wed, Jan 20, 2010 at 12:59 AM, Sam Lantinga <@slouken> wrote:

I played with this a little tonight, and there are a few reasons why
this isn’t necessarily a good idea.

First, it’s easy to validate an ID, but you can’t necessarily validate
a pointer.

Second, you can potentially reuse a memory address, which means that
if you’re doing comparisons against a stored value, you can
potentially get a false positive.

Third, if we do it for textures, we should probably do it for windows
as well, and we currently pass window ID values through events, which
may be processed after the relevant window is destroyed.

I have this change roughed out, but I wanted to raise these
considerations for discussion before I check anything in.

On Mon, Jan 18, 2010 at 7:26 PM, Sam Lantinga <@slouken> wrote:

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. ?I’m open to changing that though, if people
think the raw access is worth it…

On Mon, Jan 18, 2010 at 7:27 AM, hardcoder wrote:

Can’t agree more. I would even rewrite my app again if SDL_Texture
/SDL_TextureID compatibility could not be somehow achieved.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


? ? ? ?-Sam Lantinga, Founder and President, Galaxy Gameworks LLC


? ? ? ?-Sam Lantinga, Founder and President, Galaxy Gameworks LLC


-Sam Lantinga, Founder and President, Galaxy Gameworks LLC

Regarding performance hit discussions, please remember that optimizations
without
sound reasons are very bad ideas.

I hate this C culture of the programmers wanting to know more than the
compiler does.

The time where compilers weren’t able to proper optimize code is long gone.

Please first profile your applications with the right set of tools and then
complain with
facts.On Wed, Jan 20, 2010 at 10:08 AM, Sam Lantinga wrote:

You might also have textures or windows bound to other objects that
don’t have a life cycle exactly synchronized with that of the SDL
objects, and you may want SDL API calls to fail rather than crash.

This could even happen internally, with the native window
representation and handling events in a separate thread.

On Wed, Jan 20, 2010 at 12:59 AM, Sam Lantinga wrote:

I played with this a little tonight, and there are a few reasons why
this isn’t necessarily a good idea.

First, it’s easy to validate an ID, but you can’t necessarily validate
a pointer.

Second, you can potentially reuse a memory address, which means that
if you’re doing comparisons against a stored value, you can
potentially get a false positive.

Third, if we do it for textures, we should probably do it for windows
as well, and we currently pass window ID values through events, which
may be processed after the relevant window is destroyed.

I have this change roughed out, but I wanted to raise these
considerations for discussion before I check anything in.

On Mon, Jan 18, 2010 at 7:26 PM, Sam Lantinga wrote:

Mostly it’s to prevent crashes caused by the application holding onto
pointers after shutdown. I’m open to changing that though, if people
think the raw access is worth it…

On Mon, Jan 18, 2010 at 7:27 AM, hardcoder wrote:

Can’t agree more. I would even rewrite my app again if SDL_Texture
/SDL_TextureID compatibility could not be somehow achieved.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


-Sam Lantinga, Founder and President, Galaxy Gameworks LLC


-Sam Lantinga, Founder and President, Galaxy Gameworks LLC


-Sam Lantinga, Founder and President, Galaxy Gameworks LLC


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

You might also have textures or windows bound to other objects that
don’t have a life cycle exactly synchronized with that of the SDL
objects, and you may want SDL API calls to fail rather than crash.

On the other hand you may never know you deal with borked texture IDs or window IDs (because your app won’t crash on them), unless you check everywhere if API returns -1 :slight_smile:

Cheers,–
Adam

Regarding performance hit discussions, please remember that optimizations without
sound reasons are very bad ideas.

Yup, I think we all know what Mr. Knuth said about premature optimization.
Personally I believe it is TRUE for 95% applications, however excluding games/performance sensitive multimedia apps, where some initial choices can have irreversible impact on performance.

I hate this C culture of the programmers wanting to know more than the compiler does.
The time where compilers weren’t able to proper optimize code is long gone.

Sure you’re right, still I highly doubt compiler will optimize THAT code so the hash table lookup is as fast as straight pointer. Moreover SDL is audio/video HW abstraction library aimed for game/multimedia apps, so the performance IMHO shall be favored over safety.

On the other hand seems that SDL_TextureID based implementation won’t suffer performance hit unless you got really many textures like few hundreds, since texture hash table keeps 64 linked lists. My concern is that I actually deal with hundreds of textures in my application.

Please first profile your applications with the right set of tools and then complain with
facts.

Agreed.

Regards,–
Adam