How can sparse textures be used for large terrain rendering?

I’m interested in learning more about sparse textures. The functionality seems to be split across two extensions:
https://registry.khronos.org/OpenGL/extensions/ARB/ARB_sparse_texture.txt
https://registry.khronos.org/OpenGL/extensions/AMD/AMD_sparse_texture.txt

There are only two new functions to consider:

void TextureStorageSparseAMD(uint texture,
                                     enum target,
                                     enum internalFormat,
                                     sizei width,
                                     sizei height,
                                     sizei depth,
                                     sizei layers,
                                     bitfield flags);

void TexturePageCommitmentEXT(uint texture,
                              int level,
                              int xoffset,
                              int yoffset,
                              int zoffset,
                              sizei width,
                              sizei height,
                              sizei depth,
                              boolean commit);

I have a very large texture of dimensions 432000 x 216000 on the disk. I want to fetch tiles from it and send them into the sparse texture, as the camera moves around the scene.

I don’t see any function to actually send pixel data to the texture. I am not sure how to define the virtual texture’s tile size? What is the page size?

GL_MAX_SPARSE_TEXTURE_SIZE_ARB is returning 16384 on my AMD 6600. This seems strange for a card with 8 GB memory. Why would I use a sparse texture when I could just use a single 16384 x 16384 texture? Does that really indicate the entire size of the virtual texture?

It’s looking like this is maybe not such a useful feature when we have bindless and array textures.

Sparse textures are solely about how the backing memory of a texture is allocated and managed. It doesn’t change how you load data into them once backing storage is allocated. So you use the SubImage functions as normal.

I am not sure how to define the virtual texture’s tile size? What is the page size?

You don’t define that size. You ask OpenGL what the tile size is for a texture of a particular format.

Why would I use a sparse texture when I could just use a single 16384 x 16384 texture?

Because you don’t want to consume 1.3GB of storage for just one texture.

The point of sparse textures is that they can be partially allocated to actual physical RAM. You can load all but the highest mipmap levels now and load the rest later. Or you can load some of the highest mipmaps, but ensure that the texture is only partially visible, seeing only the parts that are allocated. And you can move those allocations around as the scene changes.

They’re not mega-texturing implemented by OpenGL.

But this is what I wanted. :crazy_face:

With the scale I am working at, is there any reason to continue looking at these?

They’re still very useful as a tool for explicitly controlling OpenGL’s memory, mipmap residency, and so forth. But they’re not going to do the hard work for you.

I think a better approach is probably this:

Create one texture with nearest filter and no mipmaps, RGBA 16 UINT format. This is a lookup table, or virtual texture.

Create another array texture that acts as a cache of all loaded tiles, at all levels.

In the fragment shader, take a sample from the lookup table texture. This provides the X and Y position of the tile, LOD that it corresponds to, and an index into the array texture. You can work out the texcoords from this, and sample from the array texture.

The highest resolution Earth data I have seen is 10 meters. A 1024x1024 texture would cover a distance of 10240 meters. That means the entire Earth’s virtual texture could be stored in less than 4096 x 2048 pixels (64 mb).

The icing on the cake would be if the GPU could feed back information to the CPU about what tiles and LODs were actually needed by the fragment shader. Then it would be a general-purpose megatexture routine.

Do systems like this usually incorporate GPU feedback to determine which tiles are needed, or must it be calculated on the CPU using the scene geometry?

On page 19 here, it looks like id is rendering an extra pass to a low-res texture and then retrieving that data into RAM for analysis. I’m thinking this is probably unnecessary for terrain: