What Does gl_WorkGroupID Do in GLSL Compute Shaders?
In GLSL compute shaders, gl_WorkGroupID is a built-in
input variable that identifies the specific work group currently
executing the shader invocation. Compute shaders execute across a
hierarchical domain divided into global dispatches, work groups, and
individual invocations. This article covers the exact data type and
structure of gl_WorkGroupID, how it relates to host-side
dispatch calls, its distinction from other built-in coordinate
variables, and how developers use it to calculate global indices and
partition memory workloads.
Type Definition and Coordinate Space
gl_WorkGroupID is defined by the OpenGL Shading Language
specification as:
in uvec3 gl_WorkGroupID;It is a three-dimensional vector of unsigned integers
(uvec3) representing the three-dimensional index of the
current work group within the overall dispatch grid:
gl_WorkGroupID.x: The index along the X-dimension, ranging from0togl_NumWorkGroups.x - 1.gl_WorkGroupID.y: The index along the Y-dimension, ranging from0togl_NumWorkGroups.y - 1.gl_WorkGroupID.z: The index along the Z-dimension, ranging from0togl_NumWorkGroups.z - 1.
Even if a compute workload is one-dimensional or two-dimensional,
gl_WorkGroupID remains a three-component vector. Unused
dimensions default to an index of 0.
Origin in Host API Calls
The values stored in gl_WorkGroupID directly correlate
with the parameters passed when launching the compute operation from the
host application. In OpenGL, compute shaders are typically launched
using the glDispatchCompute API call:
glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);When this call executes, the GPU driver schedules
num_groups_x * num_groups_y * num_groups_z total work
groups. For any given invocation, gl_WorkGroupID provides
the zero-based (x, y, z) location of the work group within
that launched grid.
Relationship to Other Compute Built-ins
Understanding gl_WorkGroupID requires distinguishing it
from complementary built-in variables provided by GLSL:
gl_LocalInvocationID(uvec3): The relative coordinate of an invocation inside its local work group.gl_WorkGroupSize(uvec3): The compile-time fixed dimensions of the local work group declared via thelayout(local_size_x = ..., ...)qualifier.gl_NumWorkGroups(uvec3): The total number of work groups dispatched across each dimension.gl_GlobalInvocationID(uvec3): The absolute, global coordinate of the current invocation across the entire dispatch.
The mathematical relationship between these variables is defined as:
\[\text{gl\_GlobalInvocationID} = \text{gl\_WorkGroupID} \times \text{gl\_WorkGroupSize} + \text{gl\_LocalInvocationID}\]
Practical Use Cases
Developers use gl_WorkGroupID primarily for tile-based
resource distribution, shared memory coordination, and coarse-grained
memory offsets.
Tile-Based Image Processing and Spatial Partitioning
When processing large textures or framebuffers, compute workloads are
often broken into rectangular tiles (such as 16x16 pixels). Each work
group processes one tile. gl_WorkGroupID indicates which
tile is being handled, allowing shaders to compute base memory offsets
or tile bounding boxes before individual threads read local pixels.
Managing Work-Group-Level Resources
Resources such as shared memory variables exist per work
group rather than per invocation. While
gl_LocalInvocationID indexes elements inside shared memory
buffers, gl_WorkGroupID determines which slice of global
memory or Shader Storage Buffer Object (SSBO) data is copied into that
shared memory bank.
Custom Work Queues and Coarse Indexing
In multi-pass algorithms or indirect rendering pipelines,
gl_WorkGroupID can index directly into global descriptor
arrays, dispatch argument buffers, or per-tile light lists, ensuring
that work is grouped efficiently according to hardware scheduling
capabilities.