Sign in to follow this  

7000 128x128 sprite frames

This topic is 3149 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My 2D game (C#) has 2 characters with 3500 unique frames each. On any scene, I could have as much as 100 characters displayed on the screen. I tried loading all my dds (DX1) frames using textureloader and my memory usage jumps to just over 100MB. I then tried putting my dds files into 27 large texture sheets (2048x2048) and get about the same memory usage. Next, I tried loading the dds frames I needed for the scene and then dispose of them after the scene, however, it takes x amount of milliseconds to load a texture, giving me around 5 FPS. I then tried doing the same thing, but load all the textures with it's own thread, which created a huge CPU spike (makes sense). A C++ game uses these same 7000 (bmp format) files in an archive and is able to produce low CPU and 45MB memory with WinG. http://en.wikipedia.org/wiki/WinG I was told to create a few large texture sheets and only load the textures sheets I needed for the scene, however, it is easily possible that I will need all sheets for the scene. What do I do? Is there a faster way of loading textures? (note: I have permission to use these graphics.)

Share this post


Link to post
Share on other sites
Three small points / questions.

1. Is 100MB a problem? Thats not that much memory these days.
2. What are you doing the graphics with XNA or SlimDX?
3. Have you checked if you are creating MIP levels automatically when loading the textures ie you may have multiple sizes of each texture. (On most texture loaders if you use 0 it creates a full set of mip levels)

Share this post


Link to post
Share on other sites
Quote:
Original post by kal_jez
Three small points / questions.

1. Is 100MB a problem? Thats not that much memory these days.
2. What are you doing the graphics with XNA or SlimDX?
3. Have you checked if you are creating MIP levels automatically when loading the textures ie you may have multiple sizes of each texture. (On most texture loaders if you use 0 it creates a full set of mip levels)


Thanks for your reply :)

1. Not really, but if a C++ game can do it in 45MB, I must be doing something wrong..?

2. Microsoft DirectX SDK (November 2008)

3. OMG, you're right! I replaced 0 with 1 and was able to bring it down to 87MB and get greater loading speeds.


Thank you so much with that. You're awesome!

Share this post


Link to post
Share on other sites
The only thing I can think that would cause such a disparity is that the WinG program didn't load everything up front and instead did it as absolutely necessary, keeping loading to a minimum and memory usage down. That explanation would make loads more sense considering the time frame WinG was popular, memory didn't grow on trees like it does now. Now we can just throw everything into the fryer and not really worry about memory.

Share this post


Link to post
Share on other sites
Quote:
Original post by Flimflam
The only thing I can think that would cause such a disparity is that the WinG program didn't load everything up front and instead did it as absolutely necessary, keeping loading to a minimum and memory usage down. That explanation would make loads more sense considering the time frame WinG was popular, memory didn't grow on trees like it does now. Now we can just throw everything into the fryer and not really worry about memory.


Makes sense. Do you think WinG had a way to load bitmaps much faster?

I tried using bitmap.fromfile and was able to load 100 BMPs (100x100) in 100 milliseconds or less, allowing me roughly 10 FPS. 10 FPS shouldn't be noticable, however, I could increase that number with multithreading..

Share this post


Link to post
Share on other sites
<<3. OMG, you're right! I replaced 0 with 1 and was able to bring it down to 87MB and get greater loading speeds.>>

With large 2048x2048 sheets, I was able to bring it down another 8MB (79MB).

Share this post


Link to post
Share on other sites
Well, loading image data has pretty much always been something the developer needs to do himself, and simply supply the raw pixel data to whatever interface (this was true even in DirectX until D3DX came around making it simpler)

Are you using GDI+ or something to render your game? (I ask because you mention Bitmap.FromFile) or are you using XNA?

Either way, should you decide to load any image data while executing your gameplay, I would strongly urge you to do it in another thread, otherwise your game will stutter horribly. To be honest though, since memory really isn't a problem, it would probably just be worth it to take the 80-100mb path and keep everything loaded at startup with the little extra loading time. You're just going to complicate things more for yourself when the memory usage isn't really a problem in in the first place by making premature optimizations.

Share this post


Link to post
Share on other sites
Quote:
Original post by Flimflam
Are you using GDI+ or something to render your game? (I ask because you mention Bitmap.FromFile) or are you using XNA?


No. I was considering Bitmap.FromFile had I made the change to DirectDraw. I'm using Direct3D for rendering, since my computer does not support XNA (pixel shader 1.1+).

Quote:
Original post by Flimflam
To be honest though, since memory really isn't a problem, it would probably just be worth it to take the 80-100mb path and keep everything loaded at startup with the little extra loading time. You're just going to complicate things more for yourself when the memory usage isn't really a problem in in the first place by making premature optimizations.


You're absolutely right. I am going to take your advice. Thank you for all your help. :))

Share this post


Link to post
Share on other sites
Load up all the textures into a compressed format ( vector quantization and simple RLE, etc.. ) which gives u reasonable compression ratios but more importantly super fast decompression. That's how the games of old stored their bitmap animation data, since they couldn't load it off the disk fast enough for real time ( and still can't ) random realtime playback.

See this link :

http://www.gamasutra.com/features/20010416/ivanov_01.htm

It's possible to get down to 3 bits per pixel, or 10:1 compression, so raw 7000 128x128 (~432 megs) can be compressed down to ~43 megs which correlates closely with the original C++ application.

This is just my guess.

Good Luck!

EDIT: It is better and simpler now to just load it all in memory. That's the best way, imo too.

-ddn

Share this post


Link to post
Share on other sites
ddn3, thanks. I think this is what I was trying to figure out.

I am going to look into it more, but will most likely take your guys' advice and just load it all into memory.


Edit:

For the record, loading into memory, I got 71MB memory usage. Not bad! With the debugger it was 79MB.

Share this post


Link to post
Share on other sites
since you keep talking about loading bringing your framerate down, it sounds like you're probably doing a naive, load-every-time-you-need-it scheme, which is always going to be slow.

again, given the timeframe of WinG (when a 300Mhz Pentium 2 would have been new, and 128MBs was uncommon) they were clearly either a) not actually displaying as many images as (or in the same size as) you want to (thereby lightening the load of loading), or b) they were doing it very differently than you.

My money is on them having had some kind of caching system in place. In any typical game there is some logical way to group the images such that the needed and soon-to-be-needed frames are nearby, which is how you want to break your sprite sheets down. Then, you don't want to load those every frame or character from scratch -- instead, define some acceptable amount of memory, load sprite sheets until you hit that wall, and then when you need a different sprite sheet loaded, replace the one which is least important (used fewest times, or longest ago). That way you'll only have to hit the disk when you don't already have that image loaded. Since things don't usually change much between frames, you should see far less need to load things from disk.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ravyne
since you keep talking about loading bringing your framerate down, it sounds like you're probably doing a naive, load-every-time-you-need-it scheme, which is always going to be slow.


Yes, I tried doing a "load-every-time-you-need-it scheme" and dispose as I was trying to keep memory down.

Quote:
Original post by Ravyne
My money is on them having had some kind of caching system in place. In any typical game there is some logical way to group the images such that the needed and soon-to-be-needed frames are nearby, which is how you want to break your sprite sheets down.


I do have my sheets organized, however, I don't see how this could work for me. If there are 100 characters on my screen, all of them may need different sheets depending on their frame.

Share this post


Link to post
Share on other sites
Quote:
Original post by Rich76
Quote:
Original post by Ravyne
since you keep talking about loading bringing your framerate down, it sounds like you're probably doing a naive, load-every-time-you-need-it scheme, which is always going to be slow.


Yes, I tried doing a "load-every-time-you-need-it scheme" and dispose as I was trying to keep memory down.


Yeah, that definitely won't work out, far too much work -- every time you draw a frame you have to seek the disk, load, create a surface/texture, draw it, then be rid of it -- and many of those images you disposed are just going to be needed again soon enough, unless you're speaking about dispose in terms of garbage collection or on a per-frame basis.

Quote:
Quote:
Original post by Ravyne
My money is on them having had some kind of caching system in place. In any typical game there is some logical way to group the images such that the needed and soon-to-be-needed frames are nearby, which is how you want to break your sprite sheets down.


I do have my sheets organized, however, I don't see how this could work for me. If there are 100 characters on my screen, all of them may need different sheets depending on their frame.


Well, it may not be easily laid out, but mathematically speaking you have in memory at any one time a vast glut of image data. You may have up to 100 characters on screen, and have a total 7000 source images -- if they're all in memory, that's an overhead of 70-1. The ideal, of course, is 1-1 -- though as you've seen that is impractical because it introduces too much overhead and latency.

But there is some middle-ground that represents the best trade-off between memory-use and this overhead. I'm not speculating, it must mathematically exist within your data set.

The reason your memory overhead is so high is because you're using those 2048x2048 images -- Thats 256 128x128 images per sheet, and if any one of those frames is in use, the whole sheet must be loaded. Now, here's the bad part -- even in the best-case scenario where all 100 characters come from a single sheet, you've still got a 2.56-1 overhead. Given 27 of these sheets, and 100 on-screen characters, you have, statistically, a little more than 4 selected frames out of those 256 per sheet - yielding a real overhead of about 64-1.

Clearly, you can do better -- if each sheet had only 16 frames of animation, you would have 16 times more sheets, or 432 in total. Given 432 of those sheets, and 100 on-screen characters, you have, statistically, 0.232 frames selected out of those 16. The numbers right now don't look any better, they're basically the same, but you have to look at the bigger picture...

when your selected frames per sheet is near 1, its bad. it means that you're loading a whole sheet, whatever size it is, and only using a single frame. As you get higher numbers, the impact goes down because you're getting more re-use out of that sheet. This is fine if its all you can get, but the real meat and potatoes are to be had by driving that number closer to 0, because that means you have to load a lower percentage of the overall set. For example, if each sheet had only 16 frames of animation, the worse-case scenario is that you'll have 100 512x512 sheets that need to be in memory, or about a quarter of the memory required for the full set.

Now, here's the kicker, for any naive caching (or non-caching, like yours) scheme, those 2560x2560 sheets you have sink the ship, because they include so many frames of animation that it's virtually guaranteed that at least one character will use at least one frame from each of the 27 sheets -- so you are, for all intents and purposes, reloading the complete data set every frame... no wonder its so slow -- of course, if you go all the way to the other side, one frame per sheet, then disk latency and slow disk I/O kills you -- its all about finding the optimal balance.


This is all somewhat academic though, as other's have said, there's not a lot of reason these days to avoid 100MB of memory use, even if you can do much, much better, unless you have a far lower bar to shoot for. But If I knew more about the nature of your animations we might really be able to knock that number down.

Is the number of frames per animation variable, or constant?
How many frames are typical per animation?

Share this post


Link to post
Share on other sites
You could probably cut on system memory by loading your textures into the default memory pool, instead of managed. That will remove the system copy of the textures, leaving them on the graphics card only. It'd be an interesting thing to try, but it's recommended that you keep them in the managed pool.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ravyne
Quote:
Original post by Rich76
Quote:
Original post by Ravyne
since you keep talking about loading bringing your framerate down, it sounds like you're probably doing a naive, load-every-time-you-need-it scheme, which is always going to be slow.


Yes, I tried doing a "load-every-time-you-need-it scheme" and dispose as I was trying to keep memory down.


Yeah, that definitely won't work out, far too much work -- every time you draw a frame you have to seek the disk, load, create a surface/texture, draw it, then be rid of it -- and many of those images you disposed are just going to be needed again soon enough, unless you're speaking about dispose in terms of garbage collection or on a per-frame basis.

Quote:
Quote:
Original post by Ravyne
My money is on them having had some kind of caching system in place. In any typical game there is some logical way to group the images such that the needed and soon-to-be-needed frames are nearby, which is how you want to break your sprite sheets down.


I do have my sheets organized, however, I don't see how this could work for me. If there are 100 characters on my screen, all of them may need different sheets depending on their frame.


Well, it may not be easily laid out, but mathematically speaking you have in memory at any one time a vast glut of image data. You may have up to 100 characters on screen, and have a total 7000 source images -- if they're all in memory, that's an overhead of 70-1. The ideal, of course, is 1-1 -- though as you've seen that is impractical because it introduces too much overhead and latency.

But there is some middle-ground that represents the best trade-off between memory-use and this overhead. I'm not speculating, it must mathematically exist within your data set.

The reason your memory overhead is so high is because you're using those 2048x2048 images -- Thats 256 128x128 images per sheet, and if any one of those frames is in use, the whole sheet must be loaded. Now, here's the bad part -- even in the best-case scenario where all 100 characters come from a single sheet, you've still got a 2.56-1 overhead. Given 27 of these sheets, and 100 on-screen characters, you have, statistically, a little more than 4 selected frames out of those 256 per sheet - yielding a real overhead of about 64-1.

Clearly, you can do better -- if each sheet had only 16 frames of animation, you would have 16 times more sheets, or 432 in total. Given 432 of those sheets, and 100 on-screen characters, you have, statistically, 0.232 frames selected out of those 16. The numbers right now don't look any better, they're basically the same, but you have to look at the bigger picture...

when your selected frames per sheet is near 1, its bad. it means that you're loading a whole sheet, whatever size it is, and only using a single frame. As you get higher numbers, the impact goes down because you're getting more re-use out of that sheet. This is fine if its all you can get, but the real meat and potatoes are to be had by driving that number closer to 0, because that means you have to load a lower percentage of the overall set. For example, if each sheet had only 16 frames of animation, the worse-case scenario is that you'll have 100 512x512 sheets that need to be in memory, or about a quarter of the memory required for the full set.

Now, here's the kicker, for any naive caching (or non-caching, like yours) scheme, those 2560x2560 sheets you have sink the ship, because they include so many frames of animation that it's virtually guaranteed that at least one character will use at least one frame from each of the 27 sheets -- so you are, for all intents and purposes, reloading the complete data set every frame... no wonder its so slow -- of course, if you go all the way to the other side, one frame per sheet, then disk latency and slow disk I/O kills you -- its all about finding the optimal balance.


This is all somewhat academic though, as other's have said, there's not a lot of reason these days to avoid 100MB of memory use, even if you can do much, much better, unless you have a far lower bar to shoot for. But If I knew more about the nature of your animations we might really be able to knock that number down.

Is the number of frames per animation variable, or constant?
How many frames are typical per animation?


Well, when I was loading file as needed, I wasn't loading texture sheets. I had the files as individual (128x128) dds textures. I was using texture sheets when I was experimenting with loading all in memory.

My frames per animation are a variable.

My frames per animation range from as low as 3 to as much as 24. The average would probably be around 18.


Thanks for your help. :)

Share this post


Link to post
Share on other sites
Quote:
Original post by ET3D
You could probably cut on system memory by loading your textures into the default memory pool, instead of managed. That will remove the system copy of the textures, leaving them on the graphics card only. It'd be an interesting thing to try, but it's recommended that you keep them in the managed pool.


Hmm, very interesting. What are the drawbacks to this?

Share this post


Link to post
Share on other sites
You'll have to reload the textures yourself whenever you get a device lost event (e.g. the user alt-tabs out of your fullscreen application, or his system enters sleep mode, etc etc).

The managed pool keeps a second copy of the bitmaps in system memory and restores them automatically. A tradeoff between convenience and memory.

Share this post


Link to post
Share on other sites
Quote:
Original post by Fiddler
You'll have to reload the textures yourself whenever you get a device lost event (e.g. the user alt-tabs out of your fullscreen application, or his system enters sleep mode, etc etc).

The managed pool keeps a second copy of the bitmaps in system memory and restores them automatically. A tradeoff between convenience and memory.


Thanks for the information.

Share this post


Link to post
Share on other sites

This topic is 3149 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this