Creating custom Optix 7 functions

First off, thank you to all who have helped me in the past. I am learning a lot about Optix thanks to all the members of this forum and am so grateful.

Now my question (which is probably easy for experts):
Does Optix 7.0.0. have a method whereby I can create a function that it will call similar to one of the predefined Optix 7 programs (e.g. closest_hit, miss, etc.)?
For example, using Optix 5.x I can write something like: RT_PROGRAM void MyQuadIntersect( int quadIdx ) - does Optix 7.0.0 offer a method like this?

This is probably a simple question, but I appreciate any help.

Thanks again.

The programming model hasn’t changed between earlier OptiX versions and OptiX 7. You still define the same programs like intersect, closest_hit, miss, etc. The API functions you use are updated, and you have to take care of your own shader binding table (the lookup table that maps each geometry to the programs/shaders you want to associate with that geometry).

Don’t be scared to just dive into the documentation and SDK samples, they are there to answer these kinds of questions and help you understand the structure of OptiX.

https://raytracing-docs.nvidia.com/optix7/guide/index.html#basic_concepts_and_definitions#basic-concepts-and-definitions

It’s WAY easier for me to start from a working example, so I highly recommend installing the OptiX 7 SDK, building the samples and getting them to run. And then look through the code and just play around with it. Try to change what happens. Start small, like with background colors or easy things like that, and then work your way up to bigger changes like changing the lights, or adding shadows, or inserting new geometry. Keep the programming guide open while you play, look at what API calls are being made, and everything will start to become more clear.

–
David.

Thank you for the response.

I will take a look at the documentation.

So the RT_PROGRAM definition is just a macro in Optix 6.x that simply means __global__ ?

Thus, these are CUDA kernels?

Thanks again @dhart

Feeling dumb about Optix now - I should have taken more time to review the docs.

No worries, we’re here to help. Yes, RT_PROGRAM just means __global__ technically, but it’s a good reminder that OptiX and CUDA are compiled differently and are not necessarily binary compatible.

–
David.

1 Like

It’s also a good idea to sync these two github repositories optix_advanced_samples and OptiX_Apps and run a source code diff tool between the example folders optixIntroduction_07 with the OptiX 5.1.0 based code and the intro_runtime resp. intro_driver folders in the new OptiX 7 based code.

The README.md in the OptiX 7 based example repository explains the connections between these samples.

The general structure of the OptiX device code inside the shaders folders is identical, e.g. look at the miss.cu for example.
The differences are due to the required changes to use OptiX 7 device functions instead of semantic variables, which includes a different attribute handling as well, and the overall different variable handling (scoped variables in the old API vs. launch parameters and SBT data in the new OptiX 7 API).

That also shows the new program domain naming scheme, e.g.
RT_PROGRAM void miss_env_constant()
extern "C" __global__ void __miss__env_constant().

Mind the new required program name prefixes like __miss__ to tell OptiX 7 what kind of program domain that is for.
Similar for the other program domains.

You can also compare the OptiX 6.5.0 and OptiX 7.2.0 programming guides and API references here: NVIDIA Raytracing Doumentation

Thanks @droettger for the links and information.

So, if I understand correctly, if I want to convert an optix 5.x function with the following signature:
RT_PROGRAM void MyQuadIntersect( int quadIdx)
I would just create the Optix 7.0.0 version as:
extern "C" __global__ __intersect__quad( int quadIdx) ?

BTW, the program function I am trying to convert is to be compiled as a PTX shader - if that helps.

Thanks again for all the help.

Actually no. The correct prefix for intersection programs in OptiX 7 is __intersection__. See this OptiX 7 Programming Guide chapter: 6.1 Program Input

When you’ve compiled that into an OptixModule you would then need to assign it to all OptixProgramDescriptions which get assigned to such primitive.
Fill in the fields hitgroup.moduleIS and hitgroup.entryFunctionNameIS with the module and intersection program name.
The anyhit and closesthit programs which should be called for these custom primitives will otherwise not be invoked.
The rest is the same as in all OptiX 7 programs: create the OptixPipeline, calculate and set the pipeline’s stack space, call optixSbtRecordPackHeader to get each program’s SBT record information, put everything together inside the SBT.

Read these threads to see what else should be done inside custom intersection programs to be able to determine what primitive type actually has been hit. That allows reusing anyhit and closesthit programs for multiple geometric primitive types and calculation of the respective final vertex attributes of the hit surface accordingly.
https://forums.developer.nvidia.com/t/how-to-get-the-transform-matrix-of-an-instance/157125/2
https://forums.developer.nvidia.com/t/optix-triangle-hit-face/83511/2
https://forums.developer.nvidia.com/t/objects-appearing-in-the-wrong-order-after-scaling/83884/7

For runtime performance reasons it doesn’t make sense to implement a custom quad primitive.
Since only BVH traversal and ray-triangle intersections are fully hardware accelerated on RTX boards, implementing a custom geometric primitive which can be represented with two triangles is definitely going to render slower.
The potential benefit would be less data for the acceleration structure, but that will also only become relevant for a huge number of quads. The AS compaction is pretty effective.

Also is there any reason to use the OptiX 7.0.0 version instead of the current OptiX 7.2.0?

Thanks for the information.

I agree the quad primitive implementation would slow performance, so this is probably a bad idea.

The reason I am using Optix 7.0.0 rather than Optix 7.2 is it is what is installed on the system and I don’t have administrator privileges. I will try and convince them to upgrade if possible.

You can install OptiX 7.2 locally and ignore the system install. All you need to do is point your build at the local header files in your OptiX 7.2 folder. The larger issue, of course, is getting the system driver up to the right version (455 or higher).

–
David.

Cool. Thanks.

Another quick question, if I may. Does Optix 7 have a version of rtPotentialIntersection?

please take a look at the “optixWhitted” sample of the OptiX 7.2 SDK in file: geometry.cu in line 49, what is done instead of “rtPotentialIntersection” in OptiX 7 :

1 Like

That ^^^ and these docs: OptiX device-side functions and optixReportIntersection

Please also follow all links in post number 9 to avoid some common pitfalls when writing OptiX 7 intersection programs.

1 Like

Thank you @droettger and @m001. The information you provided was exactly what I was looking for.