Bindless Texturing, Virtual Texture and Array Texture

Started by
3 comments, last by Corvo 7 years, 5 months ago
Recently, after read some articles of deferred texturing, I decided to try it out.
Here are some useful links to deferred texturing:
Deferred texturing, short version:
1. Write either UV/material ID/vertex ID in to the G-Buffer.
2. Use UV/material ID/vertex ID to sample textures, then do the lighting
Step 2 requires that all textures for shading are accessible. Both Array Texture and Virtual Texture could achieve the same goal.
Virtual Texture
Pros:
1. Artists can use very large textures, no need to worry about memory.
2. Already been used in some shipped games (Rage, Doom, Farcry 4, Trials Funsion etc)
Cons:
1. Extra cost by indirect table lookup,
2. Toolset needs some changes. Live level editing seems hard (requires UV re-mapping, Virtual Texture mipmap generation)
Array Texture
Pros:
1. Implementation seems easier than Virtual Texture.
2. Sample from texture array might be faster than Virtual Texture( no indirect table lookup cost )
Cons:
1. All textures required be the same size (use multiple arrays or textureLod to get around this limit?)
2. Larger memory footprint than virtual texture
There are extensions like ARB_SPARSE_TEXTURE, NV_BINDLESS, but those extensions are not supported by all the hardware.
I'm not sure which method to start first, there got be some missing details. So I'd like to know more options on those methods.
Thanks.
Advertisement

I'm not sure which method to start first, there got be some missing details. So I'd like to know more options on those methods.

You're right, there's one missing thing - you forgot bindless textures. Bindless textures are a concept different from sparse textures - while sparse/virtual textures have potentially large textures that is only partly allocated, bindless textures will give you the same advantage as array textures. Basically, you have a texture and generate a global handle that you can use everywhere in your shaders without having to bind the texture. Before that, the texture is made resident. In your case you could generate a texture handle, save it in your global material buffer and afterwards referencing it via your material attributes, or write it to a texture of your gbuffer (not recommended). Instead of indexing into an array texture, where you can only have textures with the same size and format, you can use the handle directly and sample with the given uvs from the texture in a deferred way.

EDIT: To be clear, you could use sparse textures in combination with this approach. Even it doesn't make that much sense at first sight, you could make every single texture a sparse one. Virtual textures are nowadays mostly used for very large textures...for example you could combine all surface textures of a scene into a large one and make it sparse, with loading/unloading small pieces of it at runtime. But this brings other problems you don't want to have. I would recommend you to use bindless textures at first, I used it, it's simple to integrate if your hardware supports it and it gets the job done 100%. Performance overhead wouldnt matter that much, as I experienced similar experience as with array textures.


I'm not sure which method to start first, there got be some missing details. So I'd like to know more options on those methods.

You're right, there's one missing thing - you forgot bindless textures. Bindless textures are a concept different from sparse textures - while sparse/virtual textures have potentially large textures that is only partly allocated, bindless textures will give you the same advantage as array textures. Basically, you have a texture and generate a global handle that you can use everywhere in your shaders without having to bind the texture. Before that, the texture is made resident. In your case you could generate a texture handle, save it in your global material buffer and afterwards referencing it via your material attributes, or write it to a texture of your gbuffer (not recommended). Instead of indexing into an array texture, where you can only have textures with the same size and format, you can use the handle directly and sample with the given uvs from the texture in a deferred way.

EDIT: To be clear, you could use sparse textures in combination with this approach. Even it doesn't make that much sense at first sight, you could make every single texture a sparse one. Virtual textures are nowadays mostly used for very large textures...for example you could combine all surface textures of a scene into a large one and make it sparse, with loading/unloading small pieces of it at runtime. But this brings other problems you don't want to have. I would recommend you to use bindless textures at first, I used it, it's simple to integrate if your hardware supports it and it gets the job done 100%. Performance overhead wouldnt matter that much, as I experienced similar experience as with array textures.

Thanks for your advice. I could use bindless texture extension for experiment, but my target API is opengl ES 3.0/3.1. As far as I know, ARB_bindless_texture is not supported on most mobile devices, so in the end I got to implement either Array Texture or Virtual Texture anyway.

Hm.... and it would be okay to use sparse textures, but not bindless textures? I don't know for sure, but sparse texture extensions came after bindless textures. And if you ask me, it could be problematic to use ARB_sparse_texture without EXT_sparse_texture2... because without the second extension, you have no chance to figure out whether a texture region is resident or not in your shader....effectively making the sampling cause "undefined behaviour" or returning black color or something. Please correct me if I'm wrong. If I didn't overlook something, sparse_texture2 wasn't even available on my GTX 770 desktop card...so you would rather end up using array textures solely.

Hm.... and it would be okay to use sparse textures, but not bindless textures? I don't know for sure, but sparse texture extensions came after bindless textures. And if you ask me, it could be problematic to use ARB_sparse_texture without EXT_sparse_texture2... because without the second extension, you have no chance to figure out whether a texture region is resident or not in your shader....effectively making the sampling cause "undefined behaviour" or returning black color or something. Please correct me if I'm wrong. If I didn't overlook something, sparse_texture2 wasn't even available on my GTX 770 desktop card...so you would rather end up using array textures solely.

Well, virtual texture can be achieved without hardware extension, use an extra texture as indirect table, just like they did it in Rage.

Also according to this article, it seems Doom still uses software virtual texture.

http://www.adriancourreges.com/blog/2016/09/09/doom-2016-graphics-study/

This topic is closed to new replies.

Advertisement