How sbtRecordStride Works in GLSL traceRayEXT
In Vulkan ray tracing, the sbtRecordStride parameter in
GLSL’s traceRayEXT function directly controls how the GPU
indexes through hit group records in the Shader Binding Table (SBT) when
a bottom-level acceleration structure (BLAS) contains multiple
geometries. By acting as a multiplier against the internal geometry
index, sbtRecordStride dictates the stride between
consecutive geometry records, enabling shaders to efficiently multiplex
between different ray types—such as primary, shadow, or ambient
occlusion rays—without requiring separate acceleration structures.
The Hit Group Indexing Formula
When a ray intersects a geometry within a BLAS, the ray tracing pipeline calculates the index of the hit group shader record in the SBT using the following standard equation:
HitGroupIndex = instanceShaderBindingTableRecordOffset +
(geometryIndex * sbtRecordStride) +
sbtRecordOffset
In this formula:
instanceShaderBindingTableRecordOffsetis defined on the CPU inside theVkAccelerationStructureInstanceKHRdescriptor for the given instance.geometryIndexis the zero-based index of the specific geometry within the BLAS that was intersected.sbtRecordStrideis passed dynamically viatraceRayEXT.sbtRecordOffsetis passed dynamically viatraceRayEXTto identify the specific ray type.
How sbtRecordStride Dictates Memory Progression
The primary purpose of sbtRecordStride is to handle
instances where a single BLAS consists of \(N\) geometries and the application supports
\(M\) ray types.
To organize the SBT for multiple ray types, hit groups are typically grouped by geometry or interleaved by ray type. The standard layout arranges the SBT so that each geometry has a dedicated block of shader records, with one record per ray type:
sbtRecordStridemust equal \(M\) (the total number of ray types per geometry).sbtRecordOffsetmust equal the index of the current ray type (ranging from \(0\) to \(M - 1\)).
When a hit occurs, the hardware multiplies the current
geometryIndex by sbtRecordStride. This jumps
over all the shader records allocated to preceding geometries in the
BLAS. After the stride calculation lands on the base record for the
intersected geometry, sbtRecordOffset is added to select
the precise shader record for the active ray type.
Practical Example
Consider a scene with two ray types:
- Radiance Ray (
sbtRecordOffset = 0) - Shadow Ray (
sbtRecordOffset = 1)
Because there are two ray types per geometry,
sbtRecordStride is set to 2.
If a BLAS contains three geometries (Indices 0, 1, and 2), the SBT layout for that instance appears as:
- Index 0: Geometry 0 — Radiance Hit Group
- Index 1: Geometry 0 — Shadow Hit Group
- Index 2: Geometry 1 — Radiance Hit Group
- Index 3: Geometry 1 — Shadow Hit Group
- Index 4: Geometry 2 — Radiance Hit Group
- Index 5: Geometry 2 — Shadow Hit Group
When tracing a shadow ray (sbtRecordOffset = 1,
sbtRecordStride = 2) that hits Geometry 2
(geometryIndex = 2):
HitGroupIndex = 0 + (2 * 2) + 1 = 5
The stride calculation advances 4 records past Geometries 0 and 1, and the offset selects the shadow record at index 5.
Behavioral Edge Cases
- Single Ray Type: If an application only uses one
ray type across all geometries,
sbtRecordStrideis set to1, advancing one shader record per geometry. - Shared Hit Groups Across Geometries: If all
geometries in a BLAS share the exact same shader record for a given ray
type,
sbtRecordStridecan be set to0. This eliminates the geometry index from the equation, causing every geometry in that BLAS to resolve to the same record determined solely byinstanceShaderBindingTableRecordOffset + sbtRecordOffset.