How GLSL subgroupAllEqual Compares Invocations
The subgroupAllEqual() intrinsic in GLSL is a subgroup
voting operation designed to determine whether a given expression
evaluates to the exact same value across every active invocation in the
current subgroup. This article examines the low-level mechanics of
subgroupAllEqual(), detailing how it utilizes execution
masks to filter active lanes, how hardware implements the comparison via
broadcast and reduction operations, and key behavioral nuances such as
floating-point precision.
The Role of the Subgroup and Invocation Masks
In modern GPU architectures, invocations (threads) are grouped into hardware execution units known as subgroups or warps/wavefronts. Code execution within a subgroup is lock-step, but conditional branches can cause control flow divergence. When divergence occurs, individual lanes are temporarily disabled using a hardware bitmask, commonly referred to as the active invocation mask.
When subgroupAllEqual(value) is evaluated, the GPU
restricts its evaluation strictly to invocations where the execution
mask bit is enabled. Any invocation that has diverged or exited prior to
reaching the call is ignored.
Hardware Execution Mechanism
Under the hood, graphics hardware typically avoids an \(O(N^2)\) pairwise comparison among all
invocations. Instead, subgroupAllEqual is implemented via a
two-step broadcast-and-reduce strategy:
- Electing a Reference Value: The hardware identifies
the first active invocation in the subgroup (equivalent to
subgroupBroadcastFirst()) and reads its localvalue. This value is placed on a shared cross-lane interconnect or register shuffle bus. - Local Comparison: Every active invocation compares
its own local
valueagainst the broadcast reference value (local_value == reference_value), producing a 1-bit boolean result per lane. Inactive lanes are forced to a true (1) state or masked out of consideration. - Ballot Reduction: The hardware aggregates these
comparison bits across all active lanes using a bitwise
ANDtree or ballot operation (equivalent tosubgroupAll()). If the reduced bitmask matches the active invocation mask—meaning no active lane encountered a mismatch—the intrinsic evaluates totrue. If any active lane holds a mismatched value, the reduction yieldsfalse.
Supported Types and Equality Semantics
The subgroupAllEqual function is overloaded to accept
scalar types, vectors, matrices, and custom data types, provided the
underlying type supports standard GLSL equality (==)
operators. For composite types, such as vectors or matrices, every
component must be identical across all lanes for the overall expression
to evaluate to true.
Floating-Point Nuances
Because the operation relies on standard GLSL equality semantics, floating-point numbers introduce special considerations:
- NaN (Not a Number): Under IEEE 754 rules,
NaN == NaNalways evaluates tofalse. Consequently, if any active invocation holds aNaNvalue,subgroupAllEqual()will evaluate tofalse, even if every active lane contains the exact sameNaNbit pattern. - Signed Zero: Floating-point representations
distinguish between positive zero (
+0.0) and negative zero (-0.0). However, standard comparison defines+0.0 == -0.0astrue. If some lanes contain+0.0and others-0.0,subgroupAllEqual()will treat them as identical and returntrue.