Porting APP from Optix 3.8 (32 bit) to Optix 6.5 (64 bit) : Need some help, please

Hi, after many years i’m trying to port my APP from Optix 3.8 (32 bit) to Optix 6.5 (64 bit) but I receive errors that i cannot fix (such as the error below), please help.
Thanks
:-(

This is the error: “Unknown error (Details: Function “_rtProgramCreateFromPTXString” caught exception: Compile Error: Call to rtReportIntersection is not directly controlled by a single call to rtPotentialIntersection)”

See “mesh_triangle.cu” for the source of the error

mesh_triangle.cu (6.7 KB)

Not sure why that is the error message.
You have the single rtReportIntersection(0) inside the if (rtPotentialIntersection(t)) block.
https://forums.developer.nvidia.com/t/setacceleration-fails-after-upgrading-from-3-9-1-to-4-0-0/156842/10

But what is definitely incorrect inside your mesh_triangle.cu code is the use of rtIgnoreIntersection() inside an intersection program.
That function is only allowed inside anyhit programs.
This table describes which OptiX device functions are available in which program domains:
https://raytracing-docs.nvidia.com/optix6/guide_6_5/index.html#programs#the-program-scope-of-api-function-calls

You need to remove that function and either simply return instead or restructure the conditions to not reach the rtReportIntersection call when you want to ignore it.

You are right, i’ve added rtIgnoreIntersection trying to fix the error. I went back to the original code but the error is still there.

I suspect that the check for a single rtReportIntersection(0) inside the if (rtPotentialIntersection(t)) block has some problem for my code.

I get the error non in the Cuda compile phase (no errors no warnings) but when I load the PTX file via “rtProgramCreateFromPTXString” function.

I include the CU file and the PTX file, can you try by yourself to load it with rtProgramCreateFromPTXString? (I use Optix 6.8.1)

Thank you

mesh_triangle.m64.ptx (24.2 KB)

mesh_triangle.cu (6.6 KB)

OK, when trying to load the mesh_triangle.m64.ptx into an OptiX 6.5.0 based example with createProgramFromPTXFile() I can reproduce the error on a Pascal GPU running 495.97 drivers and an Ampere GPU running 511.79 drivers.

I’ll file a bug report. If this requires a display driver fix, that would not happen soon, so something else would need be required as workaround.

I cannot experiment with the attached mesh_triangle.cu file because that is missing the necessary header to let it compile.
For example, I wonder if it works if you remove the return call by inverting the logic, or if it works when removing the very first if-statement checking the visibility.

Note that this intersection program would not be required when using built-in triangles and the expensive attribute calculations would then need to happen in an attribute program which is deferred to the hit programs of which the closest hit program is called less often.

If the visibility condition is per mesh and not per triangle, then that could probably be handled with ray visibility masks on Groups and GeometryGroups and the rtTrace call, otherwise you would need an anyhit program calling ignore intersection for the primitives which shouldn’t be visible which would be slower than keeping traversal and triangle intersection on the RTX hardware.

Here are the missing include file to compile the CU file
Thanks

commonStructs.h (1.6 KB)
easy_architect.h (15.2 KB)

I did some tests, the problem disappears if I delete the code below (see rectangle in red)

OK, I have another error. Now I’m able to compile and validate the program but I get an error when I call “_rtContextLaunch2D”

Where to look?

Thanks

(Unknown error (Details: Function “_rtContextLaunch2D” caught exception: Assertion failed: “Unconditional assertion failure: CanonicalState still used in function: directcallable__bounds_selector_ptx0xc3db3bb81df72d16”))

P.S. I had to move the following statement outside “#if 0”

	geometric_normal = normalize( n );

Right, it’s the return which seems to confuse the check for correctly paired rtPotentialIntersection and rtReportIntersection calls.

EDIT: Turns out that this is expected behavior and not a bug.
The chapter 4.8.2 Reporting Intersections inside the OptiX 6.5.0 Programming Guide says:
“If rtPotentialIntersection returns true, the intersection program may then set any attribute variable values and must subsequently call rtReportIntersection.”

That is easy to solve by moving the return before the rtPotentialIntersection like this.
Should also be faster to not call normalize(n) more than once in your code.

    if (intersect_triangle(CurrentRay, p0, p1, p2, n, t, beta, gamma))
    {
      n = normalize(n); // The normalized geometric normal in object space 

      if ((Options & MESH_FORCE_SINGLE_SIDED) != 0)
      {
        if (optix::dot(-CurrentRay.direction, n) < 0.0f) // Maybe use <= here. Also no need for the negation operator when you invert the comparison.
          return;
      }

      if (rtPotentialIntersection(t))
      {
        // Writing to attributes will only take effect between rtPotentialIntersetion and rtReportIntersection!

        // Primitive Normal value (Flat)
        geometric_normal = n;

         ...
         rtReportIntersection();
      }

Right

Originally the check was outside the block (rtPotentialIntersection / rtReportIntersection), I had to move it inside due to an Optix error on the use of attribute “geometry normal” outside rtPotentialIntersection / rtReportIntersection calls

So I can roll back to old version using “n” in place of “geometric_normal”

Thanks, now I’m stuck in the _rtContextLaunch2D error… :-(

P.S. My compliments for your analysis and advice given

P.S. My compliments for your analysis and advice given

Thanks. Call it experience.

(Unknown error (Details: Function “_rtContextLaunch2D” caught exception: Assertion failed: “Unconditional assertion failure: CanonicalState still used in function: directcallable__bounds_selector_ptx0xc3db3bb81df72d16”))

Sorry, I have no idea what is going in your code.
Since OptiX 6 doesn’t handle selectors anymore, what is that directcallable__bounds_selector doing?
When and how is it called?
The “direct” implies it’s a bindless callable program, but what is bounds_selector meaning?
(Avoid bound callable programs if you can, use bindless.)

I’d need a minimal and complete reproducer to be able to look at this or file bug reports.

My program is written in Delphi (Object Pascal) and uses rtSelectors.

I searched everywere and there is no trace of the word “bounds_selector” in my source code

This is the selector program

item_selector.cu (2.4 KB)

item_selector.m64.ptx (7.8 KB)

So in Optix 6 I have to eliminate the concept of Selector?
I used them to “show” or “hide” entire objects (each object was composed of mesh). You can find an example of use in “item_selector.cu” that I attached above.
Can you point me to a thread or document that explains how to “eliminate” the selector without damaging my program?
Thanks
R

From documentation: Note: Selector nodes are deprecated in RTX mode (default with OptiX 6.0).

How can I disable “RTX mode” ?
Maybe this is the problem…
Thanks

EDIT: I have a RTX 3060 but if I call “rtGlobalGetAttribute(RT_GLOBAL_ATTRIBUTE_ENABLE_RTX, sizeof(int32_t), &RTXEnabled);” I obtain “RTXEnabled=0” (???)

Yes, that would be the problem.
There is no support for Selectors in OptiX 6 with the RTX execution strategy and the legacy mega-kernel execution model has now been completely removed from current drivers.
Please see this thread for explanations:
https://forums.developer.nvidia.com/t/problem-with-turning-off-rtx-mode-on-gtx-1050-ti-on-newer-drivers/204549

I have a RTX 3060 but if I call “rtGlobalGetAttribute(RT_GLOBAL_ATTRIBUTE_ENABLE_RTX, sizeof(int32_t), &RTXEnabled);” I obtain “RTXEnabled=0”

RTX is disabled on my card

It’s driver version dependent. The RTX mode is the only supported mode in currently released display drivers.
The RT_GLOBAL_ATTRIBUTE_ENABLE_RTX is meaningless now.

But if I ask to Optix, Optix says “disabled”, I’m confused

Please read the forum thread I linked above and compare your display driver version number to that. Selectors are gone.

:-(

See it as a chance to make your renderer a lot faster.

Since your visit program works on a per “item” base, the case if( (item_options & OPTIX_ITEM_ENABLED)!=0 ) could be converted to a rebuild of the top-level acceleration structure with only the enabled objects contained in the scene.
Assuming you only have one top-level Group node and many GeometryGroups holding the GeometryInstances.
(This is what OptiX 7 specifies with OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING.)
Rebuilding the top-level AS is pretty fast.

Then the remaining item_options in that visit code can be handled with ray visibility flags.
There is an 8-bit mask available which should be sufficient to handle the three options you’re checking.
Actually all four checks in your visit program can be handled with ray visibility masks.

Note that the OptiX 6 API is not receiving any updates. That will only happen in OptiX 7. In the long term you should consider porting to that explicit and more modern OptiX 7 API which will always be faster than the old OptiX API used in versions 1 - 6. There have been quite some threads on this forum discussing the necessary changes.