GL_ARB_derivative_control in GLSL Explained
The GL_ARB_derivative_control OpenGL extension enhances
the OpenGL Shading Language (GLSL) by giving developers explicit,
granular control over how partial derivatives are calculated across
fragment quads. In standard GLSL, built-in derivative operations provide
implementation-dependent precision, often leading to unpredictable
visual artifacts or suboptimal performance. By introducing explicit
"coarse" and "fine" variants of derivative functions, this extension
allows graphics programmers to deliberately choose between per-pixel
accuracy and quad-wide performance optimizations.
Background: Standard Derivative Calculations
In standard GLSL, fragment shaders calculate screen-space derivatives
using functions such as dFdx(), dFdy(), and
fwidth(). Modern GPUs evaluate fragment shaders in parallel
across \(2 \times 2\) pixel regions
known as quads. To calculate partial derivatives, hardware compares
values between neighboring fragments in the quad:
- \(\frac{\partial f}{\partial x}\) evaluates horizontal differences.
- \(\frac{\partial f}{\partial y}\) evaluates vertical differences.
Because the core specification left the exact delta computation method implementation-dependent, drivers could either compute unique derivatives for each pixel pair or compute a single derivative across the quad and share it among all four pixels. This ambiguity caused inconsistency across GPU vendors, especially when sampling high-frequency procedural textures or calculating sharp surface normals.
New Functions Introduced by the Extension
GL_ARB_derivative_control resolves implementation
ambiguity by exposing six explicit derivative functions alongside
standard functions:
- Fine derivatives:
dFdxFine(),dFdyFine(), andfwidthFine() - Coarse derivatives:
dFdxCoarse(),dFdyCoarse(), andfwidthCoarse()
These functions work on float, vec2,
vec3, and vec4 inputs, mirroring the
signatures of standard derivative functions.
How Fine Derivatives Work
The dFdxFine() and dFdyFine() functions
enforce per-pixel precision across the \(2
\times 2\) quad. Instead of sharing a single approximation across
all fragments:
- For a quad with fragments \(P_{0,0},
P_{1,0}, P_{0,1}, P_{1,1}\):
- The top row horizontal derivative evaluates the difference \(P_{1,0} - P_{0,0}\).
- The bottom row horizontal derivative evaluates \(P_{1,1} - P_{0,1}\).
- The left column vertical derivative evaluates \(P_{0,1} - P_{0,0}\).
- The right column vertical derivative evaluates \(P_{1,1} - P_{1,0}\).
Because fine derivatives evaluate independent deltas for each adjacent pair within the quad, they produce distinct gradient values for each fragment. This eliminates quad-edge discontinuities, reduces aliasing in non-linear mathematical expressions, and improves rendering quality on geometric silhouettes and high-frequency analytical patterns.
How Coarse Derivatives Work
The dFdxCoarse() and dFdyCoarse() functions
explicitly evaluate a single partial derivative per \(2 \times 2\) quad and broadcast that
identical value to all four fragments:
- A single horizontal delta is calculated (typically \(P_{1,0} - P_{0,0}\) or \(P_{1,1} - P_{0,1}\)) and applied to every fragment in the quad.
- A single vertical delta is calculated (typically \(P_{0,1} - P_{0,0}\) or \(P_{1,1} - P_{1,0}\)) and applied to every fragment in the quad.
Because all four pixels share the resulting value, arithmetic overhead and register usage are minimized. Coarse derivatives are ideal for linearly varying attributes, smooth lighting calculations, and texture LOD (level-of-detail) lookups where per-pixel derivative variance is negligible.
Deterministic Shader Authoring
By defining clear behaviors for coarse and
fine derivative precision,
GL_ARB_derivative_control allows developers to avoid
lowest-common-denominator shading techniques. Workloads demanding strict
mathematical fidelity can mandate fine derivatives, while
performance-critical tasks can explicitly use coarse derivatives to
maximize GPU execution efficiency.