Understanding GL_EXT_ray_query in GLSL Shaders

This article provides an overview of the GL_EXT_ray_query extension in GLSL, focusing on how ray query objects function within compute and fragment shaders. By introducing inline ray tracing capabilities, this extension allows developers to query acceleration structures directly within standard shader stages without requiring a dedicated ray tracing pipeline. Below, we examine the fundamental mechanics of ray query objects, their integration into compute and fragment workloads, key use cases, and performance considerations.

What is GL_EXT_ray_query?

The GL_EXT_ray_query extension introduces inline ray tracing to traditional execution stages, such as compute, fragment, and vertex shaders. Unlike the dedicated ray tracing pipeline (GL_EXT_ray_tracing)—which relies on separate shader stages like ray generation, closest-hit, any-hit, and miss shaders—ray queries operate entirely within a single shader invocation.

The core mechanism is the rayQueryEXT object. This opaque type manages the traversal state of a ray intersecting a top-level acceleration structure (TLAS).

How Ray Query Objects Work

A ray query follows an explicit, step-by-step traversal loop managed directly in the shader code:

  1. Declaration: The shader declares an acceleration structure uniform (accelerationStructureEXT) and a local rayQueryEXT object.
  2. Initialization: The function rayQueryInitializeEXT() initializes the query with parameters such as the target acceleration structure, ray flags (e.g., cull masks, terminate on first hit), ray origin, direction, and clipping distances (\(t_{min}\) and \(t_{max}\)).
  3. Traversal: The shader advances through the acceleration structure using rayQueryProceedEXT(), typically within a while loop. This function returns true while traversal is ongoing and false when it finishes.
  4. Hit Evaluation: For geometries with custom intersection or transparency needs (non-opaque geometry), the shader can process candidate hits during traversal.
  5. Result Extraction: Once traversal completes, functions such as rayQueryGetIntersectionTypeEXT() determine if a primitive was struck, alongside functions to retrieve intersection distances, hit instance IDs, and barycentric coordinates.

Role in Fragment Shaders

In fragment shaders, ray query objects bring hardware-accelerated ray tracing to standard rasterization pipelines:

  • Hard and Soft Shadows: Instead of relying on shadow maps and dealing with cascading or biasing artifacts, a fragment shader can cast a single shadow ray directly toward a light source to determine visibility.
  • Ambient Occlusion (RTAO): Fragment shaders can shoot a small set of randomized hemisphere rays around the surface normal to compute accurate local ambient occlusion.
  • Simple Reflections: Fragment shaders can perform simple secondary ray casts to sample reflections directly from screen-space buffers or acceleration structures for glossy materials.

Role in Compute Shaders

Compute shaders gain fine-grained, parallel spatial querying capabilities with ray queries:

  • Hybrid Post-Processing: Compute passes can gather lighting data, compute diffuse indirect illumination, or trace glossy reflections across full-screen tiles without leaving the compute workflow.
  • Non-Graphics Computations: Compute shaders can use ray queries for game physics, light baking, sound propagation tracing, and line-of-sight/visibility testing for artificial intelligence.

Key Advantages and Trade-Offs

Advantages:

  • Pipeline Simplicity: Ray queries avoid the overhead and complexity of configuring dedicated ray tracing pipelines, shader binding tables (SBTs), and pipeline compilation.
  • Seamless Integration: They integrate directly into existing deferred or forward rendering architectures.
  • Dynamic Control: Shaders retain complete control over ray flow, allowing for early exits or conditional tracing based on material properties or screen-space information.

Trade-offs:

  • Divergence and Register Pressure: Manual traversal loops can lead to execution divergence across thread warps/wavefronts and require higher register usage, which may lower GPU occupancy compared to hardware-scheduled ray tracing pipelines.
  • No Dynamic Shading: Because ray queries do not invoke separate hit shaders automatically, complex multi-material handling must be decoded and executed manually by the initiating shader.