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(), and fwidthFine()
  • Coarse derivatives: dFdxCoarse(), dFdyCoarse(), and fwidthCoarse()

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.