Ho to determine if my __intersect_ or __anyhit_ program is being called

Hi,

I am trying to use Optix as a tool to calculate some physical properties, in the part for which I am using optix I am specifically testing some rays I calculate otherwise and testing:

  • blocking by triangles (a triangle soup in a single GAS, built with OPTIX_GEOMETRY_FLAG_DISABLE_ANYHIT)
  • blocking by custom geometry
  • passing through a semi-transparent material (always a custom geometry)

each custom geometry is in a seperate GAS.
All the GAS are in an IAS for placing the custom objects at the right location. The InstanceId of each instance encodes the type of geometry and the index of the custom geometry in an array (for getting the exact parameters) The visibility of the instance is used to group geometries. When calling optixtrace I can select which groups of geometry to use by using the visibility mask.

  • I have a single intersection program (in which I use optixGetInstanceId to determince which function to call). When there is an intersection, I report it and set 2 attributes with information.
  • I have a single anyhit program that uses 2 attributes to compensate some per ray data for the material through which the ray passes and then calls optixIgnoreIntersection.
  • I have a single closesthit program that flags some per ray data to indicate to the raygen program that the ray should be ignored.

I have several miss programs that I use in my raygen program for the different parts of the path that I am following.

The good news is that I get values reported after launching an optix launch. The problem I have is that when I enable the transparent geometry by means of the visibility mask, it appears that my intersection and anyhit programs are never running. (I try setting some per ray data to 0 that gets copied to global memory at the end of the raygen program, but the values that I see after the optix launch are not 0.

My SBT has a single raygenrecord, a single hitgrouprecord and 3 missrecords (of which I am currently only using the first)
When calling OptixLaunch I set SBToffset and SBTstride both to 0, in order to always arrive at hitrecord 0.
Maybe this is where I go wrong?
If I go the ‘more normal way’ I am afraid that I need to have a lot of (identical) hitgrouprecords in my SBT.

Any ideas of how to debug this? Is there a standard ‘easy’ way of debugging these kinds of issues?
I am using Optix 7.2 and I get no errors whatsoever.

My SBT has a single raygenrecord, a single hitgrouprecord and 3 missrecords (of which I am currently only using the first)
When calling OptixLaunch I set SBToffset and SBTstride both to 0, in order to always arrive at hitrecord 0.
Maybe this is where I go wrong?

Yes, you cannot have triangle and custom geometric primitives handled by the same hit group record in the SBT because the hit group record consists of the intersection, anyhit, closesthit programs.
Since built-in triangle geometry don’t have an intersection program you can control, using that hit group record for custom primitives will not result in any intersections being triggered for those custom primtives.

Though you can use the same anyhit and closesthit programs for different geometric primitives if your custom intersection program set the hit kind flags to identify the specific geometric primitive type properly.
That allows distinguishing the potentially different amount and meaning of the intersection attributes inside the hit programs, which then allows calculating the respective hit attributes on the surface correctly.
https://raytracing-docs.nvidia.com/optix7/guide/index.html#device_side_functions#intersection-information

Means in your case of opaque built-in triangle primitives, opaque custom primitives, and transparent custom primitives. you could use three SBT hit records to make things easy.

  • I have a single intersection program (in which I use optixGetInstanceId to determine which function to call). When there is an intersection, I report it and set 2 attributes with information.

If that means there are multiple different custom geometric primitives, I would recommend benchmarking a dedicated intersection program for each type as well, because that is the most often called program and it should be as fast as possible.

The instanceId doesn’t really need to encode the type of the geometry. That would be implicit by the hit record group which you control by the instance’s sbtOffset. But if you index additional vertex attributes via that instancId, yes, that is a good way to keep the SBT small, which might not even be a real concern. For example with an SBT hit record per instance, additional data can also be stored there. It’s also just another buffer addressed via CUdeviceptr in the end.

Thanks for the pointers. I have not yet implemented all your advice, but because of it I have found at least the most pressing problem. I now experience rays being blocked.

My problems (at least the ones I have fixed now, I was not yet able to test everything)
maxTraversableGraphDepth was set to 1

after setting this to 2 I had to set
pipelineCompileOptions.traversableGraphFlags = OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING;
instead of OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_GAS

If I encounter other things that needed fixing I will add them here. It might help others with fixing bugs in their code.