Jump to content
  • Advertisement
Sign in to follow this  
Stephane DAVID

Texture2D size in XNA

This topic is 3709 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

I have a small problem. I'm working on a turn based strategy game engine in XNA. The view is 2D iso, animations are sprites. I did some trials. I'm using an animation coming from Civilization III, FLC format. The file size is 120 kb. I export it to a storyboard, and I get a 2.5 Mb file (if using true colour bitmap) or a 86 kb file (if using png, 256 colors). I then try to initialize a Texture2D object from this, just to see... Texture2D texture = new Texture2D(filenName). Once my animation editor is started, in debug mod, the process uses 25 Mb in memory. After §I load the texture (png or bitmap give the same result), memory usage by the process jump to 41 Mb. So it's 16 Mb just for ONE animation!! And this was just a quick test. In fact, I have for each animation two arrays of Texture2D in memory, one for each frame. To initialize it, I read the FLC, then uncommpress it, then initialize the texture with SetData. To manage player, I'm using 2 Texture2D for each frame, one with the non player color (rendered wihout tint), another with player color (using tint), so that's 32 Mb for one animation. I don't think I can continue down this path, I'll need several animations for each type of units, and I can virtually have hundreds of unit types (OK, they shouldn't be displayed all at the same time...). So, I'd like to know if someone already had to cope with such problem, and how he solved it. Currently, my idea would be to avoid keeping the texture for each frame in memory, but to store an array of "bytes", a compressed version of the frame (a bit like in FLC). To render a frame, I would first uncompressed this bytes array to create a uint[], then transfer it to a Texture2D (with SetData), and then render the texture. But I'm afraid doing it everytime can seriously reduce the performances. Any idea, advice or feedback?

Share this post


Link to post
Share on other sites
Advertisement
Firstly, remember that unless you're using the D3DFMT_DXT** or DXGI_FORMAT_BC** texture formats then it'll be stored uncompressed in VRAM. Your export to a true-colour bitmap should be pretty indicative of your in-memory storage requirements.

Secondly, how are you measuring memory? Please please don't reply "task manager" [smile]. Memory usage in .NET is non-trivial and memory usage in Direct3D is non-trivial. combine the two and you've got non-stop fun, fun fun [grin]

Thirdly, is this a 3D or 2D game? If the latter you can probably get away without mip-mapping which will knock your memory footprint back down a bit.

Fourth, resource modification is (as you commented) slow - avoid it unless you absolutely have to.

hth
Jack

Share this post


Link to post
Share on other sites
How are you measuring your process memory? (hopefully not through Task Manager)

Also if you're looking to keep your textures compressed in memory, just use one of the DXT compressed surface formats when you load them. Also make sure you disable mipmap generation, which I believe happens by default (you do this by explicitly specifying that you only want one surface level in your texture).

Share this post


Link to post
Share on other sites
As mentionned in the opening post, I said the memory usage with the task manager.

I'd be happy to be pointed to a better way to do this.

IT's a 2D game.

However, if I do some simple maths:

a frame is 150x150 pixels, there are 8 directions in the animation, 15 frames/animation (in that example, there could be more).
And using true colors + 2 textures / frame (to manage player color), I end with
150x150x15x8x4x2 = 21,600,000.

So if I'm using SetData with just a uint[] representing every pixels, then I end with a very big texture.

If you know a way to make a SetData using another way, that will end with little memory usage, I'd be happy to use that.

Share this post


Link to post
Share on other sites
As a general point Task Manager is just a terrible tool for development purposes. It lacks any sort of granularity or ownership that is necessary for proper debugging. Anything loaded in by your process will be combined within that memory usage so you don't actually know which piece of code (yours or 3rd party) is allocating memory and you don't know what type of memory it is.

Run perfmon for a much more comprehensive analysis of memory usage and look into tools like NVPerfHUD for measuring GPU usage.

In particular, if you're creating .NET data structures and writing to a MANAGED texture (not sure if thats exposed in XNA though) you'll potentially end up with two system memory copies. You also need to watch out for garbage collection as your allocated memory may just be rubbish waiting around to be picked up and not actually be in use.

XNA requires the use of pixel shaders, right? In which case you can potentially halve your memory usage by simply storing a mask in the alpha channel indicating the weighting of a sprite's player colour. Do the colour substitution at render-time.


Finally, it may well be the case that you need to put in a proper resource manager over the top of whatever XNA can offer you. I'd imagine some sort of predictive LRU cache/pool should allow you to get good performance whilst controlling the amount of memory. Throw in a bit of threading along with the predictive loading and you should be sorted [grin]

hth
Jack

Share this post


Link to post
Share on other sites

As a general point Task Manager is just a terrible tool for development purposes. It lacks any sort of granularity or ownership that is necessary for proper debugging. Anything loaded in by your process will be combined within that memory usage so you don't actually know which piece of code (yours or 3rd party) is allocating memory and you don't know what type of memory it is.[/QUOTE]
I know, it was just a quick test to check if a priori there was a big difference between two methods.


Run perfmon for a much more comprehensive analysis of memory usage and look into tools like NVPerfHUD for measuring GPU usage.
[/QUOTE]
Thanks, I'd loiik into it.


In particular, if you're creating .NET data structures and writing to a MANAGED texture (not sure if thats exposed in XNA though) you'll potentially end up with two system memory copies. You also need to watch out for garbage collection as your allocated memory may just be rubbish waiting around to be picked up and not actually be in use.
[/QUOTE]
Yes, but I added a button, and when I click on it it just load the texture, nothing else. So I think the memory usage jump cannot be rubbish just afer that.


XNA requires the use of pixel shaders, right? In which case you can potentially halve your memory usage by simply storing a mask in the alpha channel indicating the weighting of a sprite's player colour. Do the colour substitution at render-time.[/QUOTE]
I'm using simple sprites, and no pixel shaders.


Finally, it may well be the case that you need to put in a proper resource manager over the top of whatever XNA can offer you. I'd imagine some sort of predictive LRU cache/pool should allow you to get good performance whilst controlling the amount of memory. Throw in a bit of threading along with the predictive loading and you should be sorted
[/QUOTE]
I already did something like that. I have pooled all the animations, to share them between different units, I load them at the very last moment, and I also count the reference to an animation, to unload it when no unit is using it anymore.

Share this post


Link to post
Share on other sites
Quote:
Original post by Stephane DAVID
As mentionned in the opening post, I said the memory usage with the task manager.

I'd be happy to be pointed to a better way to do this.

IT's a 2D game.

However, if I do some simple maths:

a frame is 150x150 pixels, there are 8 directions in the animation, 15 frames/animation (in that example, there could be more).
And using true colors + 2 textures / frame (to manage player color), I end with
150x150x15x8x4x2 = 21,600,000.

So if I'm using SetData with just a uint[] representing every pixels, then I end with a very big texture.

If you know a way to make a SetData using another way, that will end with little memory usage, I'd be happy to use that.


If it's a texture, isn't it getting loaded into video memory and not system memory?

Share this post


Link to post
Share on other sites
Quote:
Original post by mpipe

If it's a texture, isn't it getting loaded into video memory and not system memory?


By default XNA will load textures into D3DPOOL_MANAGED. Resources in this pool are loaded into system memory, and are loaded in and out of device memory depending on usage.

Share this post


Link to post
Share on other sites
I don't know the exact syntax for XNA-GSE, but in native code you force it to the default pool, D3DPOOL_DEFAULT.

However, you don't want to do this in most cases - you're assuming you know better than the runtime and driver resource manager and you're putting extra responsibility on your application. For example, you'll have to re-load the data from disk in the 'lost device' scenario (=slow) and you'll have to pay attention to out-of-memory situations.

Basically, the common wisdom is to only use D3DPOOL_DEFAULT when you are required to, but if you're aware of the impact then by all means give it a shot!

hth
Jack

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!