Images and threads

There have been threads like this before, but I’m not sure my own problem has
been covered and/or solved (in fact, since it’s OpenGL-related, I’m not even
sure if this is the right place for this question - if not, please feel free
to point me in the right direction).

I’m writing a 2D game based on MySDL with OpenGL. For my sprites, I load PNGs
into SDL surfaces from which I create both GL textures and bitmasks (from
alpha data, where needed) before freeing the SDL surface (not needed once I
have the texture and bitmask). Since I also calculate and outer and and inner
bounding box for each bitmask, and the latter is a comparably lengthy
procedure (perhaps my algorithm is suboptimal, but I don’t see how I could
optimize it further), loading all the animated sprite images for the game
takes a while (about 15 seconds on my current system).

So what I’d like to do is first load the graphics for the title screen, then
display the starfield (which is displayed both in-game and in the menu), the
logo and a progress bar, and load the in-game graphics in the background.
Which would mean:

  1. drawing the actual screen in the main thread
  2. loading PNG files into texture memory in another thread

glGenTextures in the second thread crashes, not surprisingly, since video
memory in SDL should not be accessed from more than one thread. However, I
can see only two solutions to this problem, and I don’t like either of them:

  1. only one thread - load the images in the main thread, e.g. one per frame,
    during the normal main loop. For larger textures this might noticeable slow
    down the framerate though.

  2. use the second thread for loading, but use a system of flags to do the
    actual video memory transfers in the main thread.

Both solutions would mean that I could either load only one or two (or at
least a fixed number of) images per frame (meaning it would take even
longer), or I would have to estimate how many images I can load in the
remaining time for each frame.

Of course, I could just load all the video data first, and then do only the
bitmask calculations in the second thread, but that would mean having to keep
the SDL surface for bitmap generation, while I currently only need it during
the load() method. Also, I would like to keep the possibility of
swapping/re-loading images on the fly in my engine.

Ultimately, my question is: Is there absolutely no way to access OpenGL video
memory from two different SDL threads, even if the data from the secondary
thread is never used by the first thread while the secondary thread is alive?

Thx,
Marian.–
Hofstadter’s law: “It always takes longer than you think, even when you take
account of Hofstadter’s law”.

I don’t know much about threads, but you COULD (rather than estimate the
load time for each image) set a desired minimum framerate for the one
screen, and then ACTUALLY use the leftover time for loading images.

while(!bDone) {
if(!bLoadDone) {
while(GetTicks() - lastTickCount < fpsTimerValue) {
LoadNextImage();
}
lastTickCount = GetTicks();
// draw next frame loop
//…
}
}

Anyway, I hope you get what I mean, and that it turns out you can load
the images from threads.

–Scott Harper

Marian Schedenig wrote:> There have been threads like this before, but I’m not sure my own problem has

been covered and/or solved (in fact, since it’s OpenGL-related, I’m not even
sure if this is the right place for this question - if not, please feel free
to point me in the right direction).

I’m writing a 2D game based on MySDL with OpenGL. For my sprites, I load PNGs
into SDL surfaces from which I create both GL textures and bitmasks (from
alpha data, where needed) before freeing the SDL surface (not needed once I
have the texture and bitmask). Since I also calculate and outer and and inner
bounding box for each bitmask, and the latter is a comparably lengthy
procedure (perhaps my algorithm is suboptimal, but I don’t see how I could
optimize it further), loading all the animated sprite images for the game
takes a while (about 15 seconds on my current system).

So what I’d like to do is first load the graphics for the title screen, then
display the starfield (which is displayed both in-game and in the menu), the
logo and a progress bar, and load the in-game graphics in the background.
Which would mean:

  1. drawing the actual screen in the main thread
  2. loading PNG files into texture memory in another thread

glGenTextures in the second thread crashes, not surprisingly, since video
memory in SDL should not be accessed from more than one thread. However, I
can see only two solutions to this problem, and I don’t like either of them:

  1. only one thread - load the images in the main thread, e.g. one per frame,
    during the normal main loop. For larger textures this might noticeable slow
    down the framerate though.

  2. use the second thread for loading, but use a system of flags to do the
    actual video memory transfers in the main thread.

Both solutions would mean that I could either load only one or two (or at
least a fixed number of) images per frame (meaning it would take even
longer), or I would have to estimate how many images I can load in the
remaining time for each frame.

Of course, I could just load all the video data first, and then do only the
bitmask calculations in the second thread, but that would mean having to keep
the SDL surface for bitmap generation, while I currently only need it during
the load() method. Also, I would like to keep the possibility of
swapping/re-loading images on the fly in my engine.

Ultimately, my question is: Is there absolutely no way to access OpenGL video
memory from two different SDL threads, even if the data from the secondary
thread is never used by the first thread while the secondary thread is alive?

Thx,
Marian.

[…]

glGenTextures in the second thread crashes, not surprisingly, since
video memory in SDL should not be accessed from more than one
thread.

Actually, that has nothing to do with SDL; only the OpenGL driver -
two completely different things.

However, if you’re using SDL calls to load and process textures,
expect trouble there. (As well.)

Anyway, I don’t think you can manipulate a single OpenGL context from
different threads, but at least, there are some extensions for
asynchronous texture uploading. Problem is that works only with
certain drivers, and from what I’ve heard, those extensions are a
mess anyway. :-/

However, I can see only two solutions to this problem, and
I don’t like either of them:

  1. only one thread - load the images in the main thread, e.g. one
    per frame, during the normal main loop. For larger textures this
    might noticeable slow down the framerate though.

You can use glTexSubImage() - but of course, it turns out that some
drivers just fake it and upload the whole texture anyway, so if you
use it for incremental loading, all it does is hurt performance.

  1. use the second thread for loading, but use a system of flags to
    do the actual video memory transfers in the main thread.

But then you’d be doing the gl uploading calls in the main thread
anyway, right? Of course, doing the loading and
conversions/processing in another thread might help a bit, but I
think you’ll have to stay away from SDL surfaces then…

Ultimately, my question is: Is there absolutely no way to access
OpenGL video memory from two different SDL threads, even if the
data from the secondary thread is never used by the first thread
while the secondary thread is alive?

Sounds simple in theory, but the only reliable way of using OpenGL
from multiple threads is with multiple contexts (one per thread; the
API senses which thread is calling) - but AFAIK, contexts don’t share
textures. Not sure about that, though. If contexts can share
textures, that might be a solution, at least on some
platforms/drivers. (Some drivers can’t even handle multiple contexts
within a process properly, so don’t rely on it in any case.)

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Wednesday 18 August 2004 02.49, Marian Schedenig wrote:

Anyway, I don’t think you can manipulate a single OpenGL context from
different threads, but at least, there are some extensions for
asynchronous texture uploading. Problem is that works only with
certain drivers, and from what I’ve heard, those extensions are a
mess anyway. :-/

I won’t even try looking into those then. :slight_smile:

  1. use the second thread for loading, but use a system of flags to
    do the actual video memory transfers in the main thread.

But then you’d be doing the gl uploading calls in the main thread
anyway, right? Of course, doing the loading and
conversions/processing in another thread might help a bit, but I
think you’ll have to stay away from SDL surfaces then…

Couldn’t I load the image files to software surfaces in a second thread? Or
does that cause problems as well?

If that’s ok, the main thread would do the transfers from software surfaces to
texture memory, while the loader thread keeps loading all the images in the
background…though I do wonder if a two-phase approach (first load all the
textures in the main thread, then do the additional calculations in the
background thread) would be easier after all.

Sounds simple in theory, but the only reliable way of using OpenGL
from multiple threads is with multiple contexts (one per thread; the
API senses which thread is calling) - but AFAIK, contexts don’t share
textures. Not sure about that, though. If contexts can share
textures, that might be a solution, at least on some
platforms/drivers. (Some drivers can’t even handle multiple contexts
within a process properly, so don’t rely on it in any case.)

Which means I won’t even try to find out if that would work on some
platforms… it’s not important enough for me to potentially break
compatibility to certain systems.

Thanks!
Marian.On Wednesday 18 August 2004 11:45, David Olofson wrote:


Hofstadter’s law: “It always takes longer than you think, even when you take
account of Hofstadter’s law”.

That’s what I meant. I’ll probably end up first loading all the images in this
way and then doing the remaining calculations in a background thread. I
wanted to avoid splitting the process into two phases, but I suppose that
doesn’t really have advantages if I still have to use the main thread for
loading.

Thx,
Marian.On Wednesday 18 August 2004 04:42, Scott Harper wrote:

I don’t know much about threads, but you COULD (rather than estimate the
load time for each image) set a desired minimum framerate for the one
screen, and then ACTUALLY use the leftover time for loading images.

while(!bDone) {
if(!bLoadDone) {
while(GetTicks() - lastTickCount < fpsTimerValue) {
LoadNextImage();
}
lastTickCount = GetTicks();
// draw next frame loop
//…
}
}


Hofstadter’s law: “It always takes longer than you think, even when you take
account of Hofstadter’s law”.