How GLSL Discard Terminates Fragment Processing
In OpenGL Shading Language (GLSL), the discard keyword
provides a mechanism to unconditionally abandon the processing of the
current fragment during the execution of a fragment shader. This article
explains the functional mechanics of the discard statement,
how it halts data output to the framebuffer, its underlying behavior
within GPU execution pipelines, and its performance implications
regarding depth testing.
When the execution flow of a fragment shader encounters the
discard statement, the current fragment is permanently
eliminated from the rendering pipeline. The graphics pipeline ensures
that no fragment outputs—such as color values, depth values, or stencil
modifications—are committed to the bound framebuffer attachments. From
the logical perspective of the rendering output, the fragment simply
ceases to exist, leaving previously rendered pixels or the background
color unaltered.
At the hardware execution level, "immediate termination" behaves with
specific nuances due to the Single Instruction, Multiple Threads (SIMT)
architecture of modern GPUs. GPUs execute fragment shaders in parallel
groups of threads, commonly referred to as warps or wavefronts
(typically 32 to 64 threads). When one thread in a warp hits a
discard instruction:
- Output Masking: The GPU marks the executing thread as inactive for subsequent memory writes. Even if execution continues, the results generated by that thread are discarded and will never be written to render targets.
- Lockstep Execution: Because threads within a warp
execute instructions in lockstep, the physical thread may continue
executing dummy or masked instructions alongside active neighbor threads
until the entire warp finishes, unless all threads in that warp have hit
a
discardor reached an exit point. - Derivative Calculations: Downstream operations that
depend on neighboring fragment information, such as implicit
level-of-detail (LoD) texture fetches using finite differences
(
dFdxanddFdy), can be disrupted if discarded fragments terminate abruptly. Hardware often maintains discarded fragments as "helper invocations" to provide valid data for neighboring active pixels requiring partial derivative computations.
The presence of a discard keyword within a fragment
shader also alters pre-fragment pipeline stages, most notably Early
Depth Testing (Early-Z). Normally, GPUs test and write depth before
running the fragment shader to eliminate occluded pixels early. Because
the GPU cannot predict whether a fragment will evaluate a conditional
branch leading to discard, Early-Z writes are generally
disabled. The pipeline must delay depth and stencil writes until the
fragment shader finishes to avoid leaving "holes" in the depth buffer
from fragments that are ultimately dropped.
In summary, the GLSL discard statement stops a fragment
from producing any visible impact on the framebuffer by masking all
subsequent pipeline outputs, converting the thread to an inactive or
helper state within its warp, and deferring standard depth and stencil
operations until execution concludes.