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:

  1. Electing a Reference Value: The hardware identifies the first active invocation in the subgroup (equivalent to subgroupBroadcastFirst()) and reads its local value. This value is placed on a shared cross-lane interconnect or register shuffle bus.
  2. Local Comparison: Every active invocation compares its own local value against 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.
  3. Ballot Reduction: The hardware aggregates these comparison bits across all active lanes using a bitwise AND tree or ballot operation (equivalent to subgroupAll()). If the reduced bitmask matches the active invocation mask—meaning no active lane encountered a mismatch—the intrinsic evaluates to true. If any active lane holds a mismatched value, the reduction yields false.

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 == NaN always evaluates to false. Consequently, if any active invocation holds a NaN value, subgroupAllEqual() will evaluate to false, even if every active lane contains the exact same NaN bit pattern.
  • Signed Zero: Floating-point representations distinguish between positive zero (+0.0) and negative zero (-0.0). However, standard comparison defines +0.0 == -0.0 as true. If some lanes contain +0.0 and others -0.0, subgroupAllEqual() will treat them as identical and return true.