How GLSL Sample Qualifier Forces Per-Sample Shading
This article explains the mechanism by which the sample
interpolation qualifier alters fragment shader execution in OpenGL and
Vulkan. Under standard multisample anti-aliasing (MSAA), fragment
shaders run once per pixel, but declaring a fragment input with the
sample keyword compels the GPU pipeline to execute the
shader for every covered sub-sample location. The following sections
explore default MSAA behavior, the language semantics of the
sample qualifier, and its practical implications for
rendering performance and image quality.
Default Multisample Anti-Aliasing (MSAA) Behavior
In standard MSAA pipelines, rasterization occurs at sub-pixel resolution, but shading typically occurs at pixel frequency:
- Coverage Testing: The GPU tests depth, stencil, and geometric coverage at multiple sub-sample positions per pixel (e.g., 4x or 8x MSAA).
- Shader Execution: If at least one sub-sample passes the coverage test, the fragment shader executes once per pixel, usually evaluated at the pixel center or the centroid of covered samples.
- Result Distribution: The single computed color is then copied to all covered sub-samples.
While this approach efficiently smooths silhouette edges with minimal performance cost, it does not anti-alias internal shading artifacts, specular highlights, or procedural textures.
The Mechanism of the
sample Qualifier
The sample keyword in GLSL is an interpolation qualifier
introduced to provide direct access to sample-rate operations. Declaring
an input variable with this qualifier alters the execution model:
#version 400 core
// Declaring an input with the 'sample' qualifier
sample in vec2 vTexCoord;
sample in vec3 vNormal;
out vec4 fragColor;
void main()
{
fragColor = texture(uTexture, vTexCoord);
}When an input variable is declared with sample in, the
GLSL specification mandates that:
- Unique Sample Location Evaluation: The variable must be interpolated independently at the exact coordinate of each individual sub-pixel sample rather than an aggregate or central coordinate.
- Execution Rate Promotion: Because the input value differs at each sample point, the GPU cannot evaluate the fragment shader once and reuse the results. The hardware is forced to elevate the fragment shader invocation rate from once per pixel to once per covered sample.
Even if only a single input uses the sample qualifier
while others use standard smooth or flat
qualifiers, the entire fragment shader is promoted to per-sample
execution for any pixel containing that primitive.
Differences from Centroid Interpolation
It is common to confuse the centroid and
sample qualifiers:
centroid in: Ensures that the attribute is evaluated at a location within the primitive's covered area rather than strictly at the pixel center. It avoids sampling outside the geometry, but the shader still executes only once per pixel.sample in: Mandates that the attribute is evaluated at the specific coordinates of each individual MSAA sample point, triggering an independent shader invocation for each covered sample.
Performance and Quality Impact
Forcing per-sample shading via the sample qualifier
effectively converts MSAA into full Supersample Anti-Aliasing (SSAA) for
shaded fragments:
- Visual Quality: Internal detail aliasing, specular shimmering, and high-frequency texture noise are effectively eliminated because normal maps, lighting equations, and texture coordinates are evaluated uniquely at each sub-sample point.
- Performance Cost: Fragment shader invocations scale linearly with the number of covered samples. For 4x MSAA, fragment shader execution can increase up to fourfold, substantially increasing arithmetic and memory bandwidth demands on the GPU.