How gl_LaunchIDEXT Works in GLSL Ray Tracing
This article explains how the gl_LaunchIDEXT built-in
variable identifies the current ray launch thread coordinates in GLSL
ray tracing pipelines. It covers the data structure of the variable, how
the hardware maps it from the API dispatch call, its role in converting
pixel indices into world-space rays, and how it interacts with the
overall launch grid dimensions.
Definition and Data Type
In GLSL, gl_LaunchIDEXT is an input variable provided by
the GL_EXT_ray_tracing extension. It is defined as a 3D
unsigned integer vector:
in uvec3 gl_LaunchIDEXT;This variable represents the unique integer coordinates of the
current execution thread within the overall ray tracing dispatch. Each
invocation of a ray generation shader receives its own distinct
gl_LaunchIDEXT value, corresponding directly to its
position within the launch grid.
Thread Identification Mechanism
When an application issues a ray tracing dispatch command via the
graphics API (such as vkCmdTraceRaysKHR in Vulkan), it
specifies a three-dimensional grid size comprising width, height, and
depth. The hardware scheduler instantiates a thread for every cell in
this grid.
The coordinate assignment works as follows:
- Indexing Range: Coordinates run from
(0, 0, 0)up to(width - 1, height - 1, depth - 1). - Discrete Identification:
gl_LaunchIDEXT.xcorresponds to the current column,gl_LaunchIDEXT.ycorresponds to the current row, andgl_LaunchIDEXT.zcorresponds to the layer or slice of the dispatch. - Dimensional Flexibility: Although ray tracing is
typically performed for 2D render targets—where depth is set to
1andgl_LaunchIDEXT.zremains0—the third dimension allows for multi-layer rendering, stereoscopic setups, or volumetric data generation.
Mapping Coordinates to Ray Generation
The primary function of gl_LaunchIDEXT occurs in the ray
generation shader, where it maps an execution thread to an output pixel
or sample. Because gl_LaunchIDEXT provides integer
coordinates, it must be converted into normalized coordinates to compute
the primary camera ray.
A standard implementation converts gl_LaunchIDEXT to
normalized device coordinates (NDC) using the corresponding grid
dimensions stored in gl_LaunchSizeEXT:
// Add 0.5 to sample the center of the pixel
vec2 pixelCenter = vec2(gl_LaunchIDEXT.xy) + vec2(0.5);
vec2 inUV = pixelCenter / vec2(gl_LaunchSizeEXT.xy);
vec2 d = inUV * 2.0 - 1.0;
// Transform NDC to view-space/world-space ray directions
vec4 target = invProjection * vec4(d.x, d.y, 1.0, 1.0);
vec3 rayDirection = (invView * vec4(normalize(target.xyz), 0.0)).xyz;
vec3 rayOrigin = (invView * vec4(0.0, 0.0, 0.0, 1.0)).xyz;Through this mechanism, each thread uses its ID to calculate the precise angle and starting point of the ray it is responsible for tracing into the scene.
Storing and Writing Results
Beyond ray computation, gl_LaunchIDEXT determines where
to write the final color or payload data. Once scene traversal and
shading conclude, the ray generation shader uses
gl_LaunchIDEXT.xy directly as the write coordinates for
storage images using functions like imageStore():
imageStore(outputImage, ivec2(gl_LaunchIDEXT.xy), vec4(finalColor, 1.0));This guarantees that the computed radiance for a given launch index maps deterministically to the corresponding pixel in the target frame buffer.