SBT problem when using multiple GAS objects.

I am currently working on a OptiX 7 renderer where i have multiple GAS objects and multiple IAS objects. The GAS objects are never rendered directly, and are only rendered by being refereed to by a IAS.

I am currently able to render with a single GAS and multiple IAS referring to it, without any issue.
The problem arise when i try to render with two GAS objects and two IAS objects, one IAS for each of the GAS objects.

I know the problem has something to do with my SBT as i get the same value from optixGetSbtDataPointer in the closest hit program irregardless of which object is hit. So the second IAS refering to the second GAS is getting the SBT data for the first GAS, which causes illegal memory access in my code. If i comment out the internals of my closest hit program i can see that OptiX is getting the correct geometry data as the black outline of the 3D objects looks correct against the color set by my miss program.

The problem is that i am unsure where to change the SBT to correct this issue.

The documentation describes the formula:

sbt-index = sbt-instance-offset + (sbt-GAS-index * sbt-stride-from-trace-call) + sbt-offset-from-trace-call

Am i supposed to use the instance offset variable? This seems a bit strange to me as it seems far more natural that the GAS should store where it’s data in the SBT Hitgroup records is, rather than letting the IAS store it.

I may be misunderstanding how to use the SBT properly, so any guidance would be highly appreciated. I was unable to find any Optix 7 example code that where using multiple GAS objects at the same time.

“one IAS for each of the GAS objects.”
That is exactly what I’m doing in my OptiX 7 apps all the time.

“Am i supposed to use the instance offset variable?”

If your SBT is setup to contain a hitgroupRecord entry per instance per raytype then the formula
sbt-index = sbt-instance-offset + (sbt-GAS-index * sbt-stride-from-trace-call) + sbt-offset-from-trace-call
sbt-index == From where in the SBT optixGetSbtDataPointer() gets the data field of the hitrecord.
sbt-instance-offset == OptixInstance::sbtOffset
sbt-GAS-index == 0 // If GAS build input numSbtRecords == 1 this will be always zero.
sbt-stride-from-trace-call == NUM_RAYTYPES
sbt-offset-from-trace-call == IDX_RAYTYPE
which gives:
sbt-index = OptixInstance::sbtOffset + IDX_RAYTYPE from trace

Means your OptixInstance::sbtOffset needs to be setup to match its index position inside the SBT hitgroupRecordBase memory. That in turn normally has one entry per instance per raytype, like this:
m_sbt.hitgroupRecordCount = NUM_RAYTYPES * numInstances;
m_sbt.hitgroupRecordBase must contain the necessary record headers per instance data per ray type.

So OptixInstance::sbtOffset is set to the index inside that SBT data, something like its instance index in a vector * NUM_RAYTYPES for the case of GAS with one SBT entry.

(There are other ways to setup an SBT for this case as well.)

Thanks. That cleared things up for me.

I was able to get everything working now, with multiple GAS and multiple IAS objects, by setting OptixInstance::sbtOffset correctly.