gl_SubgroupSize in GLSL Across GPU Architectures
In modern GLSL, the gl_SubgroupSize built-in variable
reports the execution width of the current subgroup—the collection of
invocations that execute concurrently on a single hardware compute unit.
While developers often look for a universal standard, this value varies
fundamentally depending on underlying GPU architectures, hardware
generations, and shader compilation flags. This guide breaks down what
gl_SubgroupSize represents and how its value differs across
NVIDIA, AMD, Intel, and mobile GPUs.
Understanding gl_SubgroupSize
gl_SubgroupSize is a built-in constant within the scope
of a subgroup, indicating the number of invocations in that specific
subgroup. In compute and graphics pipelines, hardware schedules threads
in lockstep groups, commonly referred to as warps, wavefronts, or SIMD
vectors.
The gl_SubgroupSize variable reflects this hardware
vector width. Unlike gl_SubgroupInvocationID (which indexes
an individual thread from 0 to
gl_SubgroupSize - 1), gl_SubgroupSize gives
the total active width for that execution slice, allowing developers to
write efficient intra-group algorithms like parallel reductions, ballot
operations, and prefix sums without relying on shared memory.
NVIDIA Architecture (Warps)
On NVIDIA hardware, subgroups map directly to warps.
- Standard Value:
32 - Across virtually all modern NVIDIA architectures—from Kepler and Maxwell through Turing, Ampere, Ada Lovelace, and Blackwell—the hardware warp size is fixed at 32 threads.
- Consequently,
gl_SubgroupSizeon NVIDIA GPUs will consistently evaluate to32.
AMD Architecture (Wavefronts)
AMD hardware implements subgroups as wavefronts, where the size depends on both the generation and the compile-time configuration.
- GCN (Graphics Core Next): Evaluates to
64. GCN architectures natively process wavefronts of 64 threads. - RDNA, RDNA 2, and RDNA 3: Evaluates to either
32or64. RDNA introduced dual-mode execution units that natively support Wave32 and Wave64. - By default, RDNA compilers typically target
32for compute and pixel shaders to improve occupancy and lower register pressure, but the compiler or specific pipeline creation flags can configure it to64. Developers should never hardcode an assumption of 32 or 64 on AMD hardware.
Intel Architecture (Execution Units / Xe-Cores)
Intel GPUs take a dynamic, compiler-driven approach to subgroup widths.
- Standard Values:
8,16, or32 - On Intel Gen9, Gen11, and Xe architectures (including Arc discrete GPUs), the execution units (EUs) or Xe Vector Engines (XVEs) support variable SIMD execution widths.
- The driver's shader compiler selects the subgroup size based on
register pressure, shader complexity, and target hardware profile. A
simple compute shader might execute with a
gl_SubgroupSizeof32, while a register-heavy shader may fall back to16or8to maintain thread occupancy.
Mobile and Embedded Architectures
Mobile graphics architectures exhibit significant diversity in their SIMD pipeline designs:
- Apple Silicon: Evaluates to
32. On Apple M-series and A-series GPUs (when running via Vulkan or MoltenVK translation layers), subgroups map to SIMDgroups, which are standardized at 32 threads. - ARM Mali: Evaluates to
4or16. Older Midgard/Bifrost designs operated on smaller vector or quad widths (often reporting 4 or 8), whereas newer Valhall and 5th Gen Mali architectures standardize on 16-wide warps. - Qualcomm Adreno: Evaluates typically to
32or64, depending on the specific GPU tier, shader stage, and driver implementation.
Practical Implications for Shader Design
Because gl_SubgroupSize can vary from 4 up
to 64 across devices, cross-platform GLSL code should never
assume a fixed warp size of 32. Portable subgroup algorithms must either
query gl_SubgroupSize dynamically at runtime or enforce a
required subgroup size via pipeline extensions (such as
VK_EXT_subgroup_size_control in Vulkan) when a specific
execution width is mathematically required.