What is gl_GlobalInvocationID in a Compute Shader?
gl_GlobalInvocationID is a built-in input variable in
GLSL compute shaders that uniquely identifies the current invocation
across the entire compute dispatch. Because compute shaders execute
tasks in parallel across multiple work groups, this 3D vector provides
the absolute coordinate of an individual thread within the global grid.
Understanding how it is calculated and how to map it to linear data
buffers is fundamental for performing data-parallel computations on the
GPU.
The Compute Shader Hierarchy
To understand global invocation IDs, it helps to examine how the GPU organizes compute work:
- Work Group (Local Grid): The smallest collection of
invocations that can share memory and synchronize with each other. The
dimensions are defined directly in the shader using the
layout(local_size_x, local_size_y, local_size_z)qualifier. - Dispatch (Global Grid): The total execution grid
launched from the host API via commands like
glDispatchCompute(num_groups_x, num_groups_y, num_groups_z).
Each thread inside a work group has a local coordinate, and each work
group within the dispatch has a group coordinate.
gl_GlobalInvocationID bridges these two levels into a
single global coordinate system.
Mathematical Definition
The value of gl_GlobalInvocationID is computed
automatically by the hardware using other built-in GLSL variables:
\[\text{gl\_GlobalInvocationID} = \text{gl\_WorkGroupID} \times \text{gl\_WorkGroupSize} + \text{gl\_LocalInvocationID}\]
gl_WorkGroupID(uvec3): The index of the current work group within the overall dispatch grid.gl_WorkGroupSize(uvec3): The dimensions of a single work group as declared in the layout qualifier.gl_LocalInvocationID(uvec3): The index of the current thread relative to its own work group.
For example, if a work group has a size of 16 along the X-axis
(gl_WorkGroupSize.x = 16), thread 3
(gl_LocalInvocationID.x = 3) within work group 4
(gl_WorkGroupID.x = 4) will have a global X ID of:
\[4 \times 16 + 3 = 67\]
Common Use Cases and Data Mapping
Because gl_GlobalInvocationID represents a 3D coordinate
(uvec3), it must frequently be converted into flat 1D
buffer indices or 2D texture coordinates.
1D Buffer Indexing
When processing simple arrays or flat Shader Storage Buffer Objects
(SSBOs), you typically use only the .x component directly
as the element index:
layout(std430, binding = 0) buffer DataBuffer {
float data[];
};
void main() {
uint index = gl_GlobalInvocationID.x;
data[index] = data[index] * 2.0;
}2D Texture and Matrix Indexing
When operating on 2D images or matrices, global coordinates can be mapped directly to pixel coordinates, or flattened into a 1D index:
// Direct 2D image coordinate
ivec2 pixelCoord = ivec2(gl_GlobalInvocationID.xy);
// Flattened 1D array index from 2D dimensions
uint flatIndex = gl_GlobalInvocationID.y * imageWidth + gl_GlobalInvocationID.x;Guarding Against Out-of-Bounds Invocations
Dispatches are allocated in full work group blocks. If your total
dataset size does not divide evenly into the work group dimensions, the
total number of launched threads will exceed your data size. Always
compare gl_GlobalInvocationID against data boundaries to
prevent out-of-bounds memory accesses:
void main() {
if (gl_GlobalInvocationID.x >= totalElementCount) {
return;
}
// Perform compute operations safely
}