Question Regarding SBT Indexing

Hi there,

I am currently learning about the SBT in OptiX and how records are indexed. My question concerns the “sbt-geometry-acceleration-structure-index”.

From my current understanding, this value indexes SBT records that are referenced by the build inputs of a Geometry AS and is constructed as the sum of the previous SBT records of this Geometry AS plus the per-primitive index.

What I do not fully understand is how this works together with the trace stride and the trace offset.

Let’s say I have two records for each primitive (one for a primary ray and one for a secondary ray). Could I conceptually understand the sbt-geometry-acceleration-structure-index as a base index for all SBT records (amount equal to the trace stride) that are bound to a primitive, and the trace offset as the value that selects the exact SBT record needed?

Thanks in advance!

Hi @oscarfffff,

I think the answer to your question is yes, I believe you have the right understanding. But just to clarify, and to make sure I’m not misunderstanding you…

Typically if you have multiple ray types (like primary & secondary rays), then the stride is the number of ray types, and the offset selects which ray type you’re using for a given ray. The SBT-GAS-Index is multiplied by the stride, and then the offset is added, to arrive at the final SBT index, like so:

sbt-index =
    sbt-instance-offset
    + (sbt-geometry-acceleration-structure-index * sbt-stride-from-trace-call)
    + sbt-offset-from-trace-call

This formula comes from the Acceleration Structures section of the Programming Guide. I think in your case, it might also be helpful to study the section “Example SBT for a scene”. Note that the SBT table shows the final SBT index in the middle of the table on row 6, and maybe it should be the bottom/last row of the table. Hopefully staring at this for a minute it becomes clear that there are 2 ray types, and that the SBT-GAS-Index is multiplied by 2 (which is the stride, or number of ray types) and then added to the instance offset and the trace offset to arrive at the SBT index used at run time.


David.

Hey @dhart ,

thank you very much for your quick response.

To clarify my understanding and question a bit:

A geometry AS has one or multiple Build Inputs it is constructed from. Each Build Input can reference one or more SBT Records (each SBT Record can belong to exactly one primitive but does not need to). Where I am not 100% sure is what the sbt-geometry-acceleration-structure-index actually references on an “abstract level” (so without the ray types as a concrete example for trace stride and trace offset). Is it the base index of a group of sbt records with the same data block but different programgroups (so trace stride = amount of different program groups per sbt data block)?

I hope this clarifies it a bit.

Again, thank you very much!

Abstractly, the SBT-GAS-Index is a way to get one or more SBT entries for each build input.

Conceptually you need an SBT entry for at least every combination of geometry primitive type (triangle, sphere, curve, etc.) and material type that you use in your scene. Since currently each build input is a single geometry type, the build input can be a decent proxy for geometry+material combinations.

For example, if you have 3 materials and 3 different geometry types in your scene, and all 3 materials could be applied to all 3 geometry types, then you might need as many as 3*3=9 SBT entries. But if one of your geometries is curves, and the curves only accept a single hair material, then you might avoid creating every combination of geo type and mat type, and instead assign an SBT entry to only the combinations you actually use. Sometimes build inputs are good at representing those actually used combinations. Other times, you might need per-GAS or per-build-input attributes because you want visual changes for each build input. SBT-GAS-Index gives you the ability to address both of those cases.

The SBT is intentionally made very flexible so that you can choose how you want to organize it for your application, but this does make it abstract and a little confusing at times.

Trace stride and offset are basically orthogonal to geometry & materials. All our examples use stride + offset for ray types, but you could conceivably use the stride and trace offset for something else, like swapping materials interactively or associating materials with visibility masks or other tricky rendering features.

Broadly speaking, you could think about the number of instance + geometry type + material combinations you would need for a single primary ray type, and then if you add more ray types (such as shadow rays) then you will multiply the number of ray types with the number of instance-geometry-material combinations to arrive at the total number of SBT entries you need.

Note that there are two different ways of thinking about what an SBT entry even means, because an SBT entry represents (1) the shader programs that OptiX will call when a ray intersects something (or misses) and (2) the data you can access inside those shader programs that OptiX calls - the SBT record data. The way that you create and use your SBT depends on whether you need (2), the SBT record data. Initially we advised putting per-instance data in the SBT record, which will cause you to have to create a new set of SBT entries per instance, but that can sometimes get unwieldy and cause the SBT to grow too large, so in that case we recommend storing per-instance data outside of the SBT. If you limit your SBT to only geometry+material+rayType combinations, you can get closer to having one SBT entry for each set of unique hitgroup functions in your code.


David.

Sorry for the late reply but thank you very much!

That clarified a lot of things.

1 Like