Progressive loading

Hello,

i have several large bitmaps(backgrounds), in realtime game. They are so

big that i can’t load them into memory at once because it would stop the game
for seconds. I also can predicate time in which i need to load new bitmap. So
i don’t want to load it at once like LoadBmp or IMG_LoadImage, but every time
load part of it. My question is: does help SDL with it or you manage loading
by yourself? (Or you leave it in memory comressed and then decompress it on
the fly?)

I would like to stay singlethread for some reason. So i think i can’t use
SDL_RWops to delay reading of the file. Am I wrong?

best regards
mao

I would highly suggest that you download and use SDL_Image and convert your
BMPs into a small sized format (for example JPG). Even though the JPG will
still have to be decoded, the speed difference will probably be quite
significant.

Look on the SDL homepage in the libraries section. SDL_Image can load a wide
variety of images.

Hope that helps (and if not, sorry for wasting your time!)

Steve :)> -----Original Message-----

From: obr at nri.cz [SMTP:obr at nri.cz]
Sent: Monday, February 03, 2003 2:28 PM
To: sdl at libsdl.org
Subject: [SDL] progressive loading

Hello,

i have several large bitmaps(backgrounds), in realtime game. They
are so
big that i can’t load them into memory at once because it would stop the
game
for seconds. I also can predicate time in which i need to load new
bitmap. So
i don’t want to load it at once like LoadBmp or IMG_LoadImage, but every
time
load part of it. My question is: does help SDL with it or you manage
loading
by yourself? (Or you leave it in memory comressed and then decompress it
on
the fly?)

I would like to stay singlethread for some reason. So i think i can’t use
SDL_RWops to delay reading of the file. Am I wrong?

best regards
mao


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

.sophos.3.64.01.29.

I don’t quite see how SDL_RWops would help here… You’d either need
to split your images up into smaller images, or use a tiled image
format - something that allows a background worker thread to load the
backgrounds piece by piece.

And yes, I think you’ll need an extra thread for this, or you’ll have
serious trouble getting smooth animation on most platforms.

You might get away with asynchronous file I/O, though. Maybe that’s
what you were thinking with SDL_RWops? Have the OS do the "threading"
for you, poll for completed reads, gather the blocks and load images
from memory through SDL_RWops whenever you get a complete file. This
is rather hairy and probably not very portable, though.

How about the traditional approach; structured graphics? This can mean
anything from basic, single layer tiled backgrounds through
multilayer tiles with per-tile displacement, through full textured
vector graphics, or even “off-line” 3D rendering.

I would think something tiled and pure 2D should do for most 2D games.
Basically rip your images apart into tiles and static sprites. Use
alpha blending and stuff, and draw the backgrounds in real time,
pretty much like the artist/mapper would do it in PhotoShop, GIMP, or
whatever you’re using.

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

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —On Monday 03 February 2003 15.28, obr at nri.cz wrote:

Hello,

i have several large bitmaps(backgrounds), in realtime game. They
are so big that i can’t load them into memory at once because it
would stop the game for seconds. I also can predicate time in
which i need to load new bitmap. So i don’t want to load it at once
like LoadBmp or IMG_LoadImage, but every time load part of it. My
question is: does help SDL with it or you manage loading by
yourself? (Or you leave it in memory comressed and then decompress
it on the fly?)

I would like to stay singlethread for some reason. So i think i
can’t use SDL_RWops to delay reading of the file. Am I wrong?

Tiling is really the only way to go - as stated in other posts. However I
would recommend you implement some form of tile caching mechanism (see an
article on this under gamedev). The key is to cache more than you tiles
than you need, this way any background loading will load tiles that aren’t
needed yet - and it means that the current tiles being drawn are not been
accessed.

Take a look at the TIFF file format and libtiff (IMO its brill) it supports
tiling and allows the actual image data to be in various compression formats

  • JPEG/LZW(if licensed)/ZLIB etc, etc your choice…

The library is actually pretty fast too at loading. I can pan an entire UK
raster dataset (340mb) at very blazing speeds using this library to load
tiles (without caching) and good ole GDI calls to blit to the screen.

At 2003-02-03 15:28, you wrote:

    i have several large bitmaps(backgrounds), in realtime game. They 

are so
big that i can’t load them into memory at once because it would stop the game
for seconds. I also can predicate time in which i need to load new bitmap. So
i don’t want to load it at once like LoadBmp or IMG_LoadImage, but every time
load part of it. My question is: does help SDL with it or you manage loading
by yourself? (Or you leave it in memory comressed and then decompress it on
the fly?)

As indicated other solutions are generally nicer and my personal view is
that unless you have a good reason not to do this in a separate thread, you
should really consider that. It takes only a little programming and it’s
very powerful (you don’t have to worry at all about the impact it will have
on your main thread, if you keep its priority low enough).

However, if you really want to ‘incrementally’ load a file in a single
(game) thread, here is what I can figure. If you know the format of the
file you want to load well enough, you can keep a private counter of where
in the file you are currently reading. Then in each ‘gameloop’ you read X
bytes from the file until it is complete. Make sure you know where each
’chunk’ you read goes on the surface (keep track of counters or x/y
positions, etc.)
Pseudo-code:

while (not finished playing)
if (have to load from file)
readfromfile(CHUNKSIZE,destination_buffer[currentposition])
converttosurface(CHUNKSIZE,destination_surface,currentposition)
if (finished reading)
set_surface_finished_flag
else
currentposition = currentposition + CHUNKSIZE;
endif
endif
… (do your normal game-related code)
endwhile

I’ve actually seen a program that loads large non-tiled images
progressively and smoothly: gqview (I have version 1.2.1 and it seems to
do well). I can scroll around smoothly inside 6400x3200 jpegs as they
load, on a 2.5 year old computer too.

                                            -ray

Cullum, Steve wrote:>Tiling is really the only way to go - as stated in other posts. However I

would recommend you implement some form of tile caching mechanism (see an
article on this under gamedev). The key is to cache more than you tiles
than you need, this way any background loading will load tiles that aren’t
needed yet - and it means that the current tiles being drawn are not been
accessed.

Take a look at the TIFF file format and libtiff (IMO its brill) it supports
tiling and allows the actual image data to be in various compression formats

  • JPEG/LZW(if licensed)/ZLIB etc, etc your choice…

The library is actually pretty fast too at loading. I can pan an entire UK
raster dataset (340mb) at very blazing speeds using this library to load
tiles (without caching) and good ole GDI calls to blit to the screen.


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

However, if you have a game running at a solid 75 FPS, and you suddenly
spend 30ms seeking to disk to start reading data, and you do it in the
same thread the renderer, then you’ve skipped a few frames, which will
probably be noticable. (Whether pushing it into a thread helps is
probably computer-dependent–IDE isn’t very nice.)

Ultimately, you can always either preload all bgs, or (if memory is
too tight) preload PNG data into memory and decompress them on first
use.

(SDL_image will load from memory, but I don’t think it’ll do incremental
decompression.)On Mon, Feb 03, 2003 at 06:27:13PM -0900, Ray Skoog wrote:

I’ve actually seen a program that loads large non-tiled images
progressively and smoothly: gqview (I have version 1.2.1 and it seems to
do well). I can scroll around smoothly inside 6400x3200 jpegs as they
load, on a 2.5 year old computer too.


Glenn Maynard

The second proposal is very interesting to me. How can you load PNGs
into memory and decompress on the fly, using SDL?

Thank you,
RobertOn Mon, 2003-02-03 at 22:10, Glenn Maynard wrote:

On Mon, Feb 03, 2003 at 06:27:13PM -0900, Ray Skoog wrote:

I’ve actually seen a program that loads large non-tiled images
progressively and smoothly: gqview (I have version 1.2.1 and it seems to
do well). I can scroll around smoothly inside 6400x3200 jpegs as they
load, on a 2.5 year old computer too.

However, if you have a game running at a solid 75 FPS, and you suddenly
spend 30ms seeking to disk to start reading data, and you do it in the
same thread the renderer, then you’ve skipped a few frames, which will
probably be noticable. (Whether pushing it into a thread helps is
probably computer-dependent–IDE isn’t very nice.)

Ultimately, you can always either preload all bgs, or (if memory is
too tight) preload PNG data into memory and decompress them on first
use.

(SDL_image will load from memory, but I don’t think it’ll do incremental
decompression.)


Glenn Maynard


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Tiling is really the only way to go - as stated in other posts. However I
would recommend you implement some form of tile caching mechanism (see an
article on this under gamedev).

I had similar problems and created a cache, too.
Maybe you should look up such terms as “LRU” (Last recently used) or “n-way
mapped cache”.
Those are mostly used in hardware (afaik) but work pretty fine on the
software side, too (imho).

My case - I have maps and on those up to 255 different textures.

  • First thing was bundling textures (64x64 pixels each) to bigger groups,
    meaning putting 4x4 Textures on one image.
    Thats better, because this way I can pack e.g. all floor tiles for a path on
    one image -> less loading, faster texture bindings in OpenGl

  • Second thing was using themes (every map has a theme, two maps can have
    the same theme) and always storing just 4 of them (max), because in my case
    you wont have more than 4 maps on the screen at the same time

  • Third thing was caching - in this case - loading the textures at request,
    which stay in memory as long as I need them, and marking the textures I don
    t use anymore as “unused” with a timestamp (those stay in memory, too). If I
    come to use them again - fine. If I need space for other textures - the ones
    I haven’t used for the longest time are overwritten (thats LRU).

Hope that’s halping you a bit =)

MfG
Arne
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: image/gif
Size: 494 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20030203/dee31af0/attachment.gif

I’ve actually seen a program that loads large non-tiled images
progressively and smoothly: gqview (I have version 1.2.1 and it
seems to do well). I can scroll around smoothly inside 6400x3200
jpegs as they load, on a 2.5 year old computer too.

However, if you have a game running at a solid 75 FPS, and you
suddenly spend 30ms seeking to disk to start reading data, and you
do it in the same thread the renderer, then you’ve skipped a few
frames, which will probably be noticable.

Yeah… “Smoothly” means different things to different applications
and users.

(Whether pushing it into
a thread helps is probably computer-dependent–IDE isn’t very
nice.)

IDE is not a problem, unless you want sub ms worst case latencies and
can’t use DMA. And then, the only real problem is actually the
drivers and/or OS; not the hardware. (Though PIO sucks, it locks up
the machine only if the driver is non-preemptable and transfers too
big blocks at a time.)

Ultimately, you can always either preload all bgs, or (if memory is
too tight) preload PNG data into memory and decompress them on
first use.

(SDL_image will load from memory, but I don’t think it’ll do
incremental decompression.)

Anyone considered implementing an SDL surface manager with ZIP or
BZip2 compression? You could just load the images, chop them up in
suitably large tiles and throw them in. The manager would compress
the pixels data, and then you can decompress tile surfaces as you
need them.

This is most probably best done in an asynchronous worker thread,
although if the tiles are small enough, it should be possible to do
it in the main loop. Decompression into preallocated surfaces is just
number crunching. You don’t even have to risk hitting the swap by
allocating memory.

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

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —On Tuesday 04 February 2003 05.10, Glenn Maynard wrote:

On Mon, Feb 03, 2003 at 06:27:13PM -0900, Ray Skoog wrote:

[…attachment…]

Hmm… A tiny colorkeyed GIF. What’s your point? :slight_smile:

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

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —On Tuesday 04 February 2003 08.07, Arne Claus wrote:

I don’t quite see how SDL_RWops would help here… You’d either need

Well the first idea was: to create new thread for reading. There i could
create SDL_RWops structure for file where pointer for read function should
point to my function. First i count how much time is read called and then count
from it the value for delaying something like this:

read(…)
{
if (have to wait)
wait_some_time;

read_another_bytes;

}

And then to use standard SDL_Image
extern DECLSPEC SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src);
it will use my delayed reading no?

I never used SDL_RWops before, so maybe i’m wrong about it.

to split your images up into smaller images, or use a tiled image
format - something that allows a background worker thread to load the
backgrounds piece by piece.

And yes, I think you’ll need an extra thread for this, or you’ll have
serious trouble getting smooth animation on most platforms.

:) but using threads means sometimes to have serious trouble in debugging.

My other idea was to read few bytes every time. In jpeglib - theres a function
to push bytes and then you get decompressed. But you are right, the threads
might be better because the disk might “seek” for a while and then smoothnes
goes away.

thanks
maoOn Mon, Feb 03, 2003 at 06:46:34PM +0100, David Olofson wrote:

I don’t quite see how SDL_RWops would help here… You’d either
need

Well the first idea was: to create new thread for reading. There i
could create SDL_RWops structure for file where pointer for read
function should point to my function. First i count how much time
is read called and then count from it the value for delaying
something like this:

read(…)
{
if (have to wait)
wait_some_time;

read_another_bytes;
}

And then to use standard SDL_Image
extern DECLSPEC SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src);
it will use my delayed reading no?

The RWops are direct calls, so I don’t see how this would buy you
anything. If you call IMG_Load*_RW() from within the main thread,
that thread will be blocked until the leading and decoding is done,
no matter how the actual reading is performed.

You have to move “the whole package” to that other thread. (I think
SDL_image is thread safe, but I’m not sure. Forget about using SDL
blitters and stuff, though.)

Set up two lock-free FIFOs or something, and have the main loop
request images from the other thread. The loading thread would just
read requests off the FIFO, load the files and send the surfaces back
to the main loop through the other FIFO.

You can use my “sfifo” for this (check the mixed page on my site), but
of course, it’s lock-free and thus non-blocking, so if the loading
thread ever goes to sleep, you have to use other means of waking it
up. SDL sync primitives should cover that part. Alternatively, just
poll the request FIFO a few times/second when you have nothing else
to do. Not too sexy, but it’s an easy way to get started.

[…]

And yes, I think you’ll need an extra thread for this, or you’ll
have serious trouble getting smooth animation on most platforms.

:slight_smile: but using threads means sometimes to have serious trouble in
: debugging.

Well, it does mean trouble at times. For example, you might not even
have a debugger that can handle threads properly. (Never could get
that to work on Mandrake - even installed the latest gdb from source.
Haven’t had any problems after I switched to Debian… Weird.)

My other idea was to read few bytes every time.

Yes, that could work in theory, but unfortunately, it depends totally
on the file system read-ahead doing what you want - and trust me, it
doesn’t. As soon as you hit the file system at the wrong time, you
simple have to wait until it decides to get your data. This could
mean tens or hundreds of ms.

In jpeglib - theres
a function to push bytes and then you get decompressed.

Cool… :slight_smile:

But you are
right, the threads might be better because the disk might "seek"
for a while and then smoothnes goes away.

Yep. And I think it would be a lot easier to just plain load, unwrap,
chop or whatever you want to do in a worker thread, sending the data
off to the main loop as it’s ready.

BTW, there’s actually an advantage to “hog” the CPU quite a bit in the
loading thread. (So don’t be too careful about being nice, basicall!
:wink: This kind (ie burning lots of CPU and never sleeping) of behavior
is penalized by any serious OS, resulting in the dynamic priority
being lowered, so other threads can breathe when they occasionally
wake up. That is, the main loop will get higher priority than the
loader thread, and prempt it as intended, even if you can’t set
priorities explicitly. (And you can’t with the SDL API. And it’s not
much point either, as the OS scheduler will just undo your tweaking
anyway, if you try to give the hogs higher priority or something.)

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

.- The Return of Audiality! --------------------------------.
| Free/Open Source Audio Engine for use in Games or Studio. |
| RT and off-line synth. Scripting. Sample accurate timing. |
`---------------------------> http://olofson.net/audiality -’
http://olofson.nethttp://www.reologica.se —On Tuesday 04 February 2003 11.47, obr at nri.cz wrote:

On Mon, Feb 03, 2003 at 06:46:34PM +0100, David Olofson wrote:

Just load the whole file into a buffer, set up an SDL_RWops to pretend
it’s a file, and use IMG_LoadTyped_RW (or IMG_Load_RW, if you’re not
completely sure the loaded data is PNG; it’ll do a search).On Mon, Feb 03, 2003 at 11:03:47PM -0600, Robert Diel wrote:

The second proposal is very interesting to me. How can you load PNGs
into memory and decompress on the fly, using SDL?


Glenn Maynard

Hmm… A tiny colorkeyed GIF. What’s your point? :slight_smile:

Ah - sorry - that’s my mail program (IncrediMail).
Seems to be some kind of “please register me”.

MfG
Arne