Role of gl_IncomingRayFlagsEXT in GLSL Hit Shaders
The built-in variable gl_IncomingRayFlagsEXT provides
hit shaders in the Vulkan ray tracing pipeline with read-only access to
the flags set when a ray was launched. Defined by the
GL_EXT_ray_tracing extension, this unsigned integer
variable enables closest-hit and any-hit shaders to inspect the
operational parameters of the active ray query. By communicating the
ray's configuration from the caller directly to the hit stages, it
allows shaders to modify their evaluation logic dynamically based on
context.
Source and Availability
When a ray is dispatched using the traceRayEXT() call in
a ray generation, closest-hit, or callable shader, the caller provides a
bitmask of ray flags as one of the arguments. The hardware and driver
propagate this flag bitmask down the ray traversal pipeline.
Inside the resulting hit shaders—specifically Any-Hit
(AHIT) and Closest-Hit (CHIT)—this value is
exposed as:
in uint gl_IncomingRayFlagsEXT;It is also accessible in intersection and miss shaders, maintaining uniform access to the traversal context across the entire ray evaluation pipeline.
Core Roles in Hit Shaders
1. Context-Aware Shading
Hit shaders are often shared across multiple ray types, such as
primary camera rays, reflection rays, and shadow rays.
gl_IncomingRayFlagsEXT allows a single compiled shader to
determine the caller's intent without requiring extra payload space.
For example, if a hit shader detects flags indicating a simple visibility test, it can bypass expensive lighting, texture fetches, or normal mapping calculations:
// Check if the ray was instructed to terminate on the first hit (common for shadow rays)
if ((gl_IncomingRayFlagsEXT & gl_RayFlagsTerminateOnFirstHitEXT) != 0u) {
// Perform simplified calculations for visibility queries
hitPayload.shadowFactor = 0.0;
return;
}2. Managing Geometry Opacity and Traversal
In any-hit shaders, geometry opacity must often be verified manually
(such as evaluating alpha-tested foliage or fences). The shader can read
gl_IncomingRayFlagsEXT to determine if flags like
gl_RayFlagsOpaqueEXT or gl_RayFlagsNoOpaqueEXT
were set upstream, allowing it to honor or override acceleration
structure assumptions accordingly.
3. Handling Culling Behavior
While culling is typically performed fixed-function during traversal via flags such as:
gl_RayFlagsCullBackFacingTrianglesEXTgl_RayFlagsCullFrontFacingTrianglesEXTgl_RayFlagsCullOpaqueEXTgl_RayFlagsCullNoOpaqueEXT
A hit shader can inspect these flags to resolve orientation-dependent shading effects, such as two-sided lighting or distinct inner/outer surface rendering logic when culling is explicitly disabled.
Common Ray Flag Bitmasks
The variable contains a bitwise combination of the ray control flags defined by the SPIR-V and Vulkan specifications, including:
gl_RayFlagsNoneEXT(0x0): Default traversal behavior.gl_RayFlagsOpaqueEXT(0x1): Forces all geometry to be treated as opaque.gl_RayFlagsNoOpaqueEXT(0x2): Forces any-hit shaders to run for all intersections.gl_RayFlagsTerminateOnFirstHitEXT(0x4): Treats the first valid intersection as the final hit.gl_RayFlagsSkipClosestHitShaderEXT(0x8): Prevents execution of the closest-hit shader upon termination.gl_RayFlagsCullBackFacingTrianglesEXT(0x10): Discards back-facing hits.gl_RayFlagsCullFrontFacingTrianglesEXT(0x20): Discards front-facing hits.
By providing direct visibility into these parameters,
gl_IncomingRayFlagsEXT reduces ray payload overhead,
promotes shader code reuse, and gives hit shaders the context needed to
optimize rendering paths.