Dynamically limit texture sizes

Started by
5 comments, last by RichardGe 14 years, 4 months ago
I'm writing a program that loads several hundred textures in a scene. On some cards, I don't have enough texture memory to load all of the textures at the maximum size. One good solution I've found is to limit the texture size when I call D3DXCreateTextureFromFileEx to something small, like 256. Unfortunately, I don't want to force all of the textures to be that size, as I have many situations where I want to load the full texture, and many situations where the texture is smaller than 256. Currently, I'm loading the texture first without limiting the size, then getting the lowest surface with GetLevelDesc, then determining if the texture is above 256 and then releasing the original texture and calling D3DXCreateTextureFromFileEx again, but this time adding the size specifier (256). This seems very slow, as I'm loading large textures twice. Is there a better way of going about this? I originally started with using D3DXCreateTextureFromMemory, but when I'm not limiting the size of the texture I want to load the texture into D3DPOOL_DEFAULT, with default usage, which doesn't allow me to lock the texture and read it's bits into a new texture, as I'd hoped. Some ideas that I think would work, though I don't know how to do them in directX - drop the mip-levels of the texture above 256, causing the memory to be released - query the texture's size without loading the whole texture, then make a decision on how to load it Thanks for any ideas.
Advertisement
D3DXGetImageInfoFromFile should do exactly what you want.
First of all, why are you not using the managed pool? For situations when your textures take a little more than graphics memory, it might provide okay performance (assuming you're not using all textures on the screen at once). It also saves reloading textures at device reset time.

Regarding copying textures, if you're using the default pool you don't need to lock and copy. You can copy directly from one surface to another in card memory using StretchRect. You'll have to make your texture render targets for this.
If you just want to drop mip levels you can use the D3DX_SKIP_DDS_MIP_LEVELS macro with D3DXCreateTextureFromFileEx().

Another option to save memory is to use DXT compression on your textures. The SDK comes with a texture tool for converting textures to DXT compressed - load the texture, generate mipmaps change the surface format and save as a .dds file. You want DXT1 for textures without an alpha channel, and DXT5 for ones with an alpha channel.

You can also convert at load time by passing the appropriate surface format to D3DXCreateTextureFromFileEx() but the conversion process is a little slow, and converting them in the tool saves you disk space too.

DXT compressed textures are 1/8 (DXT1) or 1/4 (DXT5) of the size of standard 32-bit textures. The only downside is that the compression is a little lossy, but for most textures you won't notice the difference.
Holy crap, thanks for the suggestions guys. I knew this would be the place to go. I'll try a couple of them and post back here how the results went.

As for the DXT compression, we're already using that, thanks.

I should try using the managed pool. A developer before me went unmanaged all the way for performance reasons, but I don't know what quantifiable gains they made, and using managed would greatly simplify the as-yet-uncoded fix for loosing the rendering context. Sadly, because the original developer wasn't exactly proficient at detecting memory leaks, our current device reset procedure is to dump the entire directx subsystem and reload everything...

If I make my textures render targets, won't I incur a performance penalty there?

D3DXGetImageInfoFromFile was exactly what I was originally looking for, thanks!
Making the textures render targets probably won't help save memory - you can't have a DXT compressed render target. Also render targets have to be created in the default pool. There shouldn't be any other differences to a normal texture though.
actually, you can act on the dimension.But keep in mind that you can also act on the quality : A8R8G8B8, A5G6B5.....
Have a great day!Richard Geslot, 3D game developermy 3D creation

This topic is closed to new replies.

Advertisement