Role of gl_NumSamples in GLSL Multisample Queries
In OpenGL Shading Language (GLSL), the built-in variable
gl_NumSamples provides fragment shaders with direct access
to the total sample count of the currently bound multisample
framebuffer. This article covers the definition of
gl_NumSamples, its availability across pipeline stages, its
primary role in multisample framebuffer queries, and how it is used in
advanced rendering techniques such as custom MSAA resolves, sample
loops, and adaptive sample-rate shading.
Definition and Availability
Declared as a built-in integer (in int gl_NumSamples;),
this variable is available exclusively in the fragment shader stage.
Introduced natively in GLSL 4.00 and backported to earlier versions via
the GL_ARB_sample_shading extension,
gl_NumSamples dynamically reflects the sample count
configured for the current render target.
If rendering to a standard, non-multisampled framebuffer,
gl_NumSamples evaluates to 1. When rendering
to a multisample framebuffer (MSAA) with configurations such as 2x, 4x,
8x, or 16x, the variable evaluates to that specific integer value.
Dynamic Framebuffer Configuration Querying
The primary role of gl_NumSamples is eliminating the
need for application-side uniforms to inform shaders of the active MSAA
state. In complex rendering engines where framebuffers might transition
between different multisample levels (e.g., standard rendering pipelines
alternating with high-precision MSAA passes), passing sample counts
manually can introduce synchronization overhead and state leakage.
Using gl_NumSamples, the GPU queries the hardware
rasterizer state directly at runtime, guaranteeing that shading logic
dynamically adapts to the target buffer's physical sample layout.
Bounding Sample Iterations and Coordinates
gl_NumSamples frequently serves as the loop boundary
when processing individual samples. When working in conjunction with
other sample-specific built-ins, such as gl_SampleID and
gl_SamplePosition, gl_NumSamples provides the
upper limit for per-sample indexing:
- Index Bounds: The built-in
gl_SampleIDranges from0togl_NumSamples - 1. - Custom Resolves: During a manual MSAA resolve pass,
a shader can iterate from
0throughgl_NumSamples - 1to manually fetch, weight, and average individual sample values usingtexelFetchon asampler2DMS. - Explicit Interpolation: When using functions like
interpolateAtSample(interpolant, sample_idx),gl_NumSamplesallows developers to clamp or validate indices dynamically within shader branches to avoid undefined sampling behavior.
Normalization and Weighted Filtering
Beyond simple iteration, gl_NumSamples is used
mathematically to normalize sample accumulations. When calculating
averages across samples for tone mapping, custom anti-aliasing filters,
or depth/stencil-based edge detection, computing the reciprocal
(1.0 / float(gl_NumSamples)) produces the baseline weight
per sample. This ensures that resolve filters adapt correctly regardless
of whether the rendering pipeline changes its target MSAA resolution
between passes.