Using SBT offsets in GAS in program with only one SBT record?

The formula which calculates the effective SBT index is this:

sbt_index =
    sbt_instance_offset
    + (sbt_geometry_acceleration_structure_index * sbt_stride_from_trace_call)
    + sbt_offset_from_trace_call

from here: https://raytracing-docs.nvidia.com/optix8/guide/index.html#shader_binding_table#accelstruct-sbt

If you have set the SBT offset on a GAS build input, respectively on each primitive in a GAS using the sbtIndexOffsetBuffer (which must contain values in the range [0, numSbtRecords - 1] because these are local to the build input), then there is only one way to get that down to SBT index zero which is by setting the sbt_stride_from_trace_call to zero which in turn would prevent the implementation of different ray types.

That in turn will only work when there are no instances, respectively when all sbtOffset values in all instances are zero as well because that is always added by the sbt_instance_offset in the formula above.

Also note that the sbt_offset_from_trace_call, means the optixTrace SBToffset argument is only 4 bits (see the Limits chapter) which means there can only be 16 different ray types, which shouldn’t be a problem because you can implement different behaviors in one ray type as well.

All the SBT offsets are unsigned so there isn’t any way to subtract the different inputs in that formula.

So in terms of the above formula, if you want sbt_index == 0, but have sbt_geometry_acceleration_structure_index != 0, then you must have sbt_instance_offset == 0, sbt_stride_from_trace_call == 0, and sbt_offset_from_trace_call == 0.

HOWEVER, if my shaders do not ask for the SBT record

I assume you mean you’re not calling optixGetSbtDataPointer to get the additional data stored inside SBT hit record in that case?
If you store per geometry data on the SBT hit records, redirecting the SBT index wouldn’t be able to access the proper vertex attributes then, so all you could do is a hit/miss condition plus all attributes coming from the intersection.

I wouldn’t do that because it’s too restrictive on the SBT layout. Just always setup your SBT exactly as required for your specific render graph instead.

There are other ways to access the GAS data when using an IAS->GAS structure (see the example below).

I’m often using GAS with exactly one SBT record, so sbt_geometry_acceleration_structure_index == 0, and then select the SBT hit record with the OptixInstance sbtOffset only, which selects the material shader.
If that needs to be changed, I simply update the IAS with new sbtOffset values.
All other data is accessed via the user defined OptixInstance instanceId value!
An example doing that is here (rtigo12): https://forums.developer.nvidia.com/t/optix-advanced-samples-on-github/48410/15
When you change the BXDF inside the GUI, the respective instances using that material reference will be updated.

Here are some related threads about how to setup SBTs in different ways. Follow the links at the bottom of this one:
https://forums.developer.nvidia.com/t/question-about-instance-acceleartion-struction/283898/4