04/11/2012 GL_AMD_sparse_texture comments

We have heard of AMD_sparse_texture for quite some time but finally the extension is available. It rose quite some excitement from OpenGL programmers: Having textures for which we can allocate and unallocate memory pages sounds great especially for virtual texturing where we need to address large amount of data. It handles case where wecan't espect that all the textures can fit entierely into graphics memory. Sparse texture allows sampling across texture pages without artefacts even with high anisotropic filtering.

Creating a sparse texture
  • // Create a sparse texture
  • glGenTextures(1, &TextureName);
  • glTextureStorageSparseAMD(TextureName, GL_TEXTURE_2D,
  • GL_RGBA8, // Internal format
  • 16384, 16384, 1,// width, height, depth
  • 1, // layers
  • GL_TEXTURE_STORAGE_SPARSE_BIT_AMD); // Handle the texture as a sparse texture. (Not a hint)
  • // Allocate the texture pages of the sparse texture
  • for(std::size_t i = 0; i < n; ++i)
  • {
  • ...
  • glTextureSubImage2DEXT( // Using the classic texture sub image function.
  • TextureName, GL_TEXTURE_2D,
  • GLint(Level),
  • GLint(Position.x), GLint(Position.y),
  • GLsizei(Size.x), GLsizei(Size.y),
  • GL_RGBA, GL_UNSIGNED_BYTE, Texture[0].data());
  • }

Texture pages can be deleted using the same glTextureSubImage2DEXT function but passing NULL for the data. This behavours highlight a design issue with this extension which prevents allocating a texture page without passing data to fill the texture pages. A workaround to reduce the performance impact is to source a pack buffer object, reading (even garbage) from GPU memory instead of through the PCI express bus.

The texture page size must be multiple of the value returned by the GL_VIRTUAL_PAGE_SIZE_[X,Y,Z]_AMD queries.

Query texture page sizes
  • GLint PageSizeX(0), PageSizeY(0), PageSizeZ(0);
  • glGetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_VIRTUAL_PAGE_SIZE_X_AMD, 1, &PageSizeX);
  • glGetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_VIRTUAL_PAGE_SIZE_Y_AMD, 1, &PageSizeY);
  • glGetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_VIRTUAL_PAGE_SIZE_Z_AMD, 1, &PageSizeZ);

In practice the texture page memory size must be a multiple a 64 KB so that if the texture internal format store large texels (RGBA32F = 16 bytes per texels), the number of texels per page will be reduced only bound by the 64 KB memory size. Hence, the texture page dimensions for a RGBA32F texture is 64 by 64 texels. For a DXT1/BC1 texture, a texel is encoded with 4 bits which results in a mimimum of 256 by 256 texels per texture page.

Sparse textures can be used for texture 2d, texture 2d array and texture 3d. Unfortunately, on Southern Islands GPUs, the texture pages dimensions are always the same shape, flat 2D slices even for texture 3d. An application (global illumiation with sparse voxel octrees) could take advantage of 3d texture pages (dices instead of slices) for texture 3d, unfortunately this shape reflects the texture 3d layout of Southern Islands GPUs memory layout.

On the GLSL size, the usual texture sampling language can be used to sample a sparse texture. However, in some cases it can be useful to sample in area where no texture pages have been allocated. For this, AMD_sparse_texture provides some new GLSL functions that return a code qualified the result of the sampling.

New GLSL functions returning a code:
  • #version 420 core
  • #extension AMD_sparse_texture : require
  • layout(binding = DIFFUSE) uniform sampler2D Diffuse;
  • ...
  • void main() {
  • vec4 Color;
  • int Code = sparseTexture(Diffuse, Texcoord, Color);
  • // Did we fetch somewhere all the texels are resident?
  • bool Resident = sparseTexelResident(Code);
  • // Do we need a texel from any LOD lower than the user specified LOD warning threshold?
  • bool MinLodWarning = sparseTexelMinLodWarning(Code);
  • int LodWarningFetch = sparseTexelLodWarningFetch(Code);
  • ...
  • }

It is also possible to do rendering to sparse framebuffer but unfortunately not to depth textures. Supporting depth textures could make high resolution shadow mapping a lot easier and particularly memory efficient.

Even if this extension remains quite experimental from my opinion, it defines one of the key feature for post OpenGL 4 hardware. Considering that NVIDIA GPUs support some form of virtual memory system, I wouldn't be surprise to see them releasing an implementation with at least a subset of the functionnalities given by this extension.

Some people will argue that NVIDIA supports bindless textures and hence NVIDIA doesn't need sparse textures. This is either a misleading argument, a misunderstanding of the features or simply a marketing lie. Bindless textures are great but bindless and sparse textures are simply complementary features. Bindless textures allows an unlimited number of textures while sparse textures ensure filtering between texture pages. We need both!

Surviving without gl_DrawID >
< October 2012 OpenGL drivers status
Copyright Christophe Riccio 2002-2016 all rights reserved
Designed for Chrome 9, Firefox 4, Opera 11 and Safari 5