Bindless Textures vs Traditional Bindings in GLSL

Bindless texture access fundamentally alters how shaders reference and sample image data, shifting the paradigm from a limited, CPU-managed slot architecture to direct 64-bit GPU memory handles. This article examines how the bindless approach transforms sampler management in GLSL compared to traditional binding mechanisms, highlighting how removing fixed texture unit constraints enables massive draw-call reductions, simplifies shader storage, and modernizes GPU resource pipelines.

Traditional Texture Binding in GLSL

In traditional OpenGL pipelines, samplers rely on a fixed-function hardware slot architecture:

  • Texture Image Units: The GPU exposes a limited number of active texture units (typically 16 to 32 per shader stage).
  • CPU State Management: Before issuing a draw call, the CPU must activate a specific texture unit using glActiveTexture, bind a texture via glBindTexture, and optionally bind a separate sampler state with glBindSampler.
  • GLSL Association: In GLSL, a sampler uniform (such as uniform sampler2D u_Texture;) does not hold texture data directly. Instead, it holds an integer index that points to one of the active texture units, set via glUniform1i or modern layout(binding = N) qualifiers.

This system creates significant CPU overhead when rendering scenes with varied materials. Because the number of active slots is strictly capped, renderers must frequently change bindings, split geometry into multiple small batches, and serialize rendering commands.

The Bindless Texture Model

Bindless texturing, introduced via the GL_ARB_bindless_texture extension, replaces slot-based addressing with direct pointers to texture and sampler state combinations:

  • 64-Bit Handles: Textures and samplers are compiled by the driver into unique 64-bit integer handles (represented as uint64_t on the CPU or uvec2 / uint64_t in GLSL).
  • Residency Over Binding: Instead of binding textures to specific slots before every draw call, textures are made "resident" in GPU memory using glMakeTextureHandleResidentARB(). Once resident, the GPU can access the texture data at any time without further CPU intervention.
  • Direct Sampler Construction: GLSL can directly cast a 64-bit integer to a native sampler type (such as sampler2D(handle)), allowing textures to be addressed dynamically.

How Sampler Management Changes

The transition from traditional bindings to bindless textures introduces several distinct operational differences:

1. Decoupling from Hardware Slot Limits

Traditional pipelines force developers to manage texture slots carefully, frequently hitting caps that require multipass rendering or aggressive texture atlasing. Bindless textures completely remove the concept of texture units; a single shader can seamlessly reference thousands of unique textures in a single draw pass.

2. Samplers as First-Class Data Types

In traditional GLSL, samplers are restricted to opaque uniform declarations and cannot be dynamically indexed or packed inside generic memory structures. In a bindless architecture, 64-bit handles behave like standard integers. They can be stored in Uniform Buffer Objects (UBOs), Shader Storage Buffer Objects (SSBOs), vertex attributes, or push constants, enabling per-instance and per-primitive material assignments directly from GPU memory.

3. Shift from Binding to Residency Tracking

Traditional sampler management requires checking which texture is bound to which unit before issuing draw calls. With bindless texturing, sampler management moves entirely to residency tracking. The engine only needs to ensure that required textures are resident on the GPU before execution, eliminating thousands of state-change validation checks on the CPU per frame.

4. Enablement of GPU-Driven Rendering

By removing the CPU-side requirement to rebind texture units, bindless textures allow drawing techniques such as Multi-Draw Indirect (MDI). A single indirect draw call can render thousands of disparate objects, each sampling from entirely different textures resolved via an SSBO lookup using gl_DrawID or gl_InstanceID.

Bindless texturing shifts the role of GLSL samplers from fixed CPU-orchestrated routing points to dynamic, data-driven GPU memory references, drastically reducing driver overhead and restructuring modern engine architectures.