Texture Array Memory Allocation

Started by
1 comment, last by Matias Goldberg 9 years, 7 months ago

I'm working on my terrain editor to allow quite a handful of texture splats (say up to 64).

If I create a texture array 64 levels deep, but only upload to the first 4 levels (if I only use 4 splats), it wouldn't have allocated any memory until I call glTexImage right?

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

Advertisement
I can't recall the precise semantics for when OpenGL textures get their backing store but all of the memory is reserved at once.

So if you created a 1024*1024 64 layer texture then as soon as memory is allocated ALL the memory will be allocated at once.

This is the reason for the sparse texture and buffer extensions; they allow you to create the texture but only commit a certain amount of backing memory to it as required on demand; so you'd create your texture as before but before writing data you'd tell OGL 'give me memory for level 0, mip 0' and at that point it would allocate that memory, and only that memory.

OpenGL has now two types of textures:

Mutable storage.

Gets allocated when you call glTexImageND (where N is 1, 2 or 3). Additional calls to glTexImageND destroy and recreate the texture if the format changes in any way (resolution, bit depth, internal format). You can use glTexSubImageND to upload portions (or the entire image) without reformatting the texture.

  • If you call glTexImageND( 1024, 1024, 64 ); then glTexSubImageND( 1024, 1024, 4 ) you will allocate a 1024x1024x64 texture then upload the 4 slices (you waste 60).
  • If you call glTexImageND( 1024, 1024, 64 ); then glTexImageND( 1024, 1024, 4, ..., data ); you will allocate a 1024x1024x64, then destroy it, create a 1024x1024x4 texture and upload the 4 slices. You don't waste memory, but you burn a lot of CPU & GPU cycles with unnecessary allocations, deallocations, and pipeline stalls.
  • glTexImageND( 1024, 1024, 4, ..., data ); you will create and upload the 4 slices. No waste. If you later call glTexImageND( 1024, 1024, 64, ..., data ); you will destroy the old texture and create a 1024x1024x64 and upload all 64 slices. It's as wasteful as the previous point.

Immutable storage.

The "modern" way. glTexStorageND? allocates the texture and can never be changed afterwards. Subsequent glTexStorageND & glTexImageND calls are invalid. You can use glTexSubImageND to reupload the entire image or parts of it.

  • If you call glTexStorageND( 1024, 1024, 4 ) you will create a 1024x1024x4 texture. But you can't change it to a 1024x1024x64 later. You will need to call glDeleteTextures and recreate it yourself.
  • If you call glTexStorageND( 1024, 1024, 64 ) you will create a 1024x1024x64 texture.

So, bottom line, it depends on how you handle the situation. Immutable storage is preferred over mutable storage, because with immutable storage the wrong parameter will just trigger an error. On mutable storage, with the wrong parameter the driver will silently try to honour your weird request, slowdown your app a lot, and you may see random glitches without a warning of what's wrong.

Don't mix glTexImageND & glTexStorageND on the same texture ID btw. You can use glTexImageND on both though.

This topic is closed to new replies.

Advertisement