General Optix 5 to Optix 7 code

Hello all,

I have been tasked with converting some Optix 5.0.0 code to Optix 7.0. I plan on building some Optix 7.0 code along side currently existing Optix 5.0.0 code. Can these two separate Optix codes coexist within the same CMake build? I am not a CMake expert, having come from a Makefile background but am migrating.

Also, generally speaking, how compatible is Optix 5.0.0 with Optix 7.0 ?

Thanks for any help.

I have been tasked with converting some Optix 5.0.0 code to Optix 7.0. I plan on building some Optix 7.0 code along side currently existing Optix 5.0.0 code. Can these two separate Optix codes coexist within the same CMake build?
I am not a CMake expert, having come from a Makefile background but am migrating.

You can use a different OptiX version per project inside a solution.
That is just a matter of picking the right OptiX versions for each project.
In my OptiX application frameworks that can be done by changing a find_package(OptiX<version>) line inside the project’s CMakeLists.txt, resp. in the newest OptiX 7 examples by picking the desired OptiX include folder.

You can NOT use two different versions of OptiX inside the same project sources!
That will already clash at the OptiX root header optix.h which has the same name but different contents in OptiX SDK 7 versions.

Also, generally speaking, how compatible is Optix 5.0.0 with Optix 7.0 ?

OptiX 7 uses a completely different explicit API. A rewrite of the host code is required
It’s a header-only API. The core implementation resides inside the display drivers.
The entry points of the API are loaded into a function table dynamically by the application.

The general OptiX device program structure is the same (no attribute programs like in OptiX 6), but variable declarations and scopes, as well as all built-in device function names are different.

OptiX 7 applications are programmed with the CUDA runtime API or CUDA driver API to do all resource management explicitly. OptiX 7 doesn’t know about multiple GPU devices or even textures. All that is done with native CUDA code which allows much more flexible and predictable application behavior.

OptiX 5 didn’t support the RT cores for hardware BVH traversal and triangle intersections present in RTX boards. There everything was a custom primitive. Support for RTX hardware was added in OptiX 6 with the GeometryTriangles nodes. This is is similar for OptiX 7, there you pick the “build input” type for triangle, curve, or custom geometric primitives.

Please find more explanations here:
https://forums.developer.nvidia.com/t/porting-to-optix-7/79249/2
https://forums.developer.nvidia.com/t/optix-7-breaking-changes/156801/2

Please follow these resources which are explicitly meant to show the difference between OptiX 5.x and OptiX 7 programs:
https://forums.developer.nvidia.com/t/optix-7-2-release/156619
https://forums.developer.nvidia.com/t/optix-advanced-samples-on-github/48410/2

Basically read all OptiX 7 related threads in this developer sub-forum. :-)

Please always read the OptiX Release Notes (link beneath the download button for each OptiX version) before setting up a development environment to use compatible CUDA toolkit and host compiler versions.

@droettger thank you for the reply, as I said I am relatively new to the CMake world. You have provided me with a wealth of information. I think I will go the route of different OptiX versions per project inside a solution. That way I can keep older OptiX version code while building newer OptiX version.

I have been looking into using a FindOptiX7.cmake script to locate include directories, etc… Do you have a example using this that I can look at ?

Thanks again.

Yes, I wrote these here for my OptiX 7 examples: https://github.com/NVIDIA/OptiX_Apps/tree/master/3rdparty/CMake

They look for the default OptiX installation folders, but if you install SDKs to a different location like me, you can use an environment variable OPTIX7_PATH, OPTIX71_PATH, and OPTIX72_PATH to let the scripts look there first.

In the most recent commits there, I moved the find_package(OptiX<version>)to the top-level CMakeList.txt which generates the solution with all projects. That way it looks for all shipping OptiX 7 versions and individual examples use the newest found OptiX 7 version by selecting just the include directory.
https://github.com/NVIDIA/OptiX_Apps/blob/master/CMakeLists.txt#L78

Before that, the individual examples’ CMakeLists.txt used find_package(OptiX<version>) themselves to decide which OptiX 7 version to use. I left that in as comment for example here:
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/intro_runtime/CMakeLists.txt#L35
Below that line you see how it’s using the individual OptiX<version>_FOUND CMake variables which have been set by the resp. FindOptiX<version>.cmake scripts to select the newest found version.

So currently you could pick an OptiX 7 version explicitly by just changing that selection to your desired include directory version or by removing the find_package( ) calls from the top-level CMakeLists.txt and uncomment the previous method. (The sub-directory of the intro_motion_blur example is not added when OptiX72_FOUND is not set, so that check would need to be removed from the CMakeList.txt in the apps folder.)

When having projects with older OptiX versions, you would need to use its own FindOptiX.cmake variant, because the APIs were not header-only and need to find and set the link libraries as well, but it’s similarly simple.

The OptiX 5.1.0 based ancestors of these introduction samples contain a FindOptiX.cmake which is a little more involved because of the different library names among OptiX 5 and 6 versions:
https://github.com/nvpro-samples/optix_advanced_samples/blob/master/src/CMake/FindOptiX.cmake

I normally used a smaller version of that for my own projects. Attached is one which finds OptiX 6.5.0 if the environment variable OPTIX_PATH is not set. Or change the hardcoded default 6.5.0 in there.
FindOptiX.txt (3.7 KB)
(Rename to *.cmake. The forum doesn’t allow that extension in attachments.)

I never used the optixu libraries of the SDKs, and the script doesn’t add that to the OPTIX_LIBRARIES, but all code required for that is left inside the *.cmake as comment if you need that.

The include_directories() section of the CMakeLists.txt of the project would then need the ${OPTIX_INCLUDE_DIR} and the target_link_libraries() would need the ${OPTIX_LIBRARIES} among all other dependencies.

Cool, that is exactly what I was looking for. So, given that I have different versions of Optix (used by different project(s)) is in same CMake build and older Optix 5.0.0 is using Optix_INCLUDE_DIR I would just need to call the FindOptix7.cmake with Optix7_INCLUDE_DIR, etc. so there would be no mixing of uses? That is to say, my project using Optix7 would use Optix7_INCLUDE_DIR, etc and my project using Optix5 would use Optix_INCLUDE_DIR, etc (given this is currently the path for Optix5 calls and I don’t want to disturb currently existing cmake build.

Thanks again.

Exactly, just that my CMake variables for the include directories and library lists are all capital letters.
The OptiX_FOUND variable is an exception because that is created by CMake and should match the spelling of the FindOptiX.cmake to avoid warnings in newer CMake versions.
But you can change the scripts to whatever you need.

I would just need to call the FindOptix7.cmake with Optix7_INCLUDE_DIR

You call find_package(OptiX7 REQUIRED) in your OptiX 7.0.0 based project and that script sets the OPTIX7_INCLUDE_DIR for you, which you then use inside the include_directories().
Similar for the other two OptiX 7.1.0 and 7.2.0 versions. (I would just use OptiX 7.2.0.)

All these user defined *.cmake scripts are found at all because there is this instruction inside the top-level CMakeLists.txt:
https://github.com/NVIDIA/OptiX_Apps/blob/master/CMakeLists.txt#L8

Great - I have learned something new :)

Thanks again @droettger for all the help

You’re welcome. That’s what my examples are meant to show.

@droettger one last question/statement, if I may. Optix 7.x on Windows is header-only as well? Meaning there is no need to pass library dll paths to cmake which is same situation for Linux using Optix 7.x.

I don’t have a Windows machine so am more or less just guessing that it will be similar as far as Optix 7.x is concerned.

Thanks again.

Correct.

Inside the OptiX SDK check the helper header optix_stubs.h or my example code to see how Windows and Linux load their respective OptiX library dynamically.
That’s a lot more involved under Windows because the OptiX DLL lives inside the Windows driver store.

The optix_stubs.h lifts the OptiX entry point functions into the global namespace.
My code loads the function table per device.
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/rtigo3/src/Device.cpp#L496

1 Like

Thanks again.