1 – Bindless Textures Overview
I spent some time last week to add into GeeXLab the support of bindless textures. Bindless textures is the very cool feature introduced with the GeForce GTX 680.
But what are bindless textures? In 3D programming (OpenGL or Direct3D), to use a texture, you have to bind it to a texture unit. In OpenGL for example, a GeForce GTX 680 has 32 texture units you can use in your GLSL shader programs. That means you can do multi-texturing with a max of 32 textures (which is enough for most cases). If you need more textures, you must re-think your algorithm.
With bindless textures, there’s no longer need to bind a texture to a texture unit. Just create your textures and, quickly said, enable their bindless status (read: make them resident textures). Now you can have more than 32 textures to make your greedy shaders happy.
Here’s the slide for explaining the bindless texture concept:
Currently, bindless textures are only available in OpenGL applications (like GeeXLab). If you want to dive into bindless texture programming, check out this OpenGL extension: GL_NV_bindless_texture.
2 – Bindless Textures Demo
So what kind of simple demo could I do to show the use of bindless textures? After some tests, I ended up on this mosaic-like demo:
This demo simply loads a bunch of textures (here 1024 textures on the screenshot), makes them resident (with glMakeTextureHandleResidentNV()) and draws a simple quad with all textures, using one render call only. An uniform buffer is used to pass all texture handles (a texture handle is an 64-bit unsigned int or uint64_t, NVIDIA extension provides some functions to manage uint64_t uniform variables) to the pixel shader. In this particular demo and thanks to bindless textures, it’s like if the GTX 680 had virtually 1024 texture units…
On my EVGA GeForce GTX 680 (with R301.24), the demo runs at 1015 FPS (640×480, default camera settings) and at 790 FPS in full HD resolution (1920×1080).
Here is the GLSL shader (vertex + pixel shader) that renders all textures on the quad:
[Vertex_Shader] void main(void) { gl_Position = ftransform(); gl_TexCoord[0] = gl_MultiTexCoord0; } [Pixel_Shader] #version 420 compatibility #extension GL_NV_bindless_texture : require #extension GL_NV_gpu_shader5 : require // for uint64_t #define TEX_X 32 #define TEX_Y 32 #define NUM_TEXTURES TEX_X*TEX_Y uniform SamplersNV { uint64_t allTheSamplers[NUM_TEXTURES]; }; void main (void) { vec2 uv = gl_TexCoord[0].st * vec2(TEX_X, TEX_Y); int x = int(uv.x); int y = int(uv.y); int index = y*TEX_Y + x; sampler2D s = sampler2D(allTheSamplers[index]); gl_FragColor.rgb = texture(s, uv).rgb; gl_FragColor.a = 1; }
|
If you have a GTX 680, GTX 690 or GTX 670, you can download and test the GeeXLab Bindless Textures Demo (left-click to grab the file): |
The source code of the GeeXLab demo is available in the GXL_NV_Bindless_Texture_Demo.xml file.
You have to use GeeXLab 0.4.0 or newer to tweak and hack the demo.
If the OpenGL renderer does not support bindless textures, you should see something like this:
*Yawn* another feature that has been part of Direct3D since version 10
Of course. I wonder why this requires a modern 680 then if it is apparently from D3D10 times.
@DrBalthar
Not true. This is new *hardware* feature available only in GTX 600. How could it be part of D3D 10?
I stated the same as Michal but my message was silently removed which is ultra lame. Maybe the moderator can drop me few lines what the reason was. Bad day?
Anyhow, if it would have been exposed in D3D 10 it would be available as OpenGL ext long time ago (even earlier then D3D 10 i guess).
@DrBalthar:
From D3D10 docs (http://msdn.microsoft.com/en-us/library/windows/desktop/bb173604(v=vs.85).aspx):
NumSamplers [in]
Type: UINT
Number of samplers in the array. Each pipeline stage has a total of 16 sampler slots available.
D3D10 only has 16 texture units vs 32 for normal OpenGL vs unlimited with the extension.
I have GTX 480. I’m weird if I can run but this demo has still same Shader Model 5.0.
Nice! When the 680 first came out I couldn’t wait to play with this extension, as it should allow for a more rich game environment in future game engines!!!
According to David Baumann, AMD’s GCN can do this with it’s Scalar Unit. Don’t know how would the code be though.
but still, dx-games dont support this feature even in 600series, which is kinda useless to mention. how many opengl games these days?
good for demomakers probably
Bindless is the future!
Seriously because the driver determines how to assign tasks to the texture units it can be build to do this in the most optimal way.
This is only possible with deep information about the hardware. This information is (in theory) only known to the driver developer(s).
There is a real future in making graphics programming faster, easier to debug, more performant and less error-prone.
We need this for all kinds of units, not just textures.
@Leith Bade
No, since D3D10 textures and sample units are not the same. Textures are just shader resource views, maximum number of SRVs are 128(according to MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/bb173606(v=vs.85).aspx). So you pass SRVs and sampler states to the shader, inside your shader you just take sampler state and use it for SRV sampling. That’s all. ARB_sampler_objects are the same as method proposed in D3D10.
http://www.nvidia.com/content/PDF/kepler/NVIDIA-Kepler-GK110-Architecture-Whitepaper.pdf
2880 CUDA cores, Compute Capability 3.5.