How should I define OPTIX_SAMPLE_NAME and OPTIX_SAMPLE_DIR in my own optix-based app?

I managed to create my own .cu file to execute some large math calculations. I did that by modifying the optixTriangle sample. Now I am trying to migrate this .cu file to my own Vs2022 solution.
I combined the preprocessor definitions, includes and additional directories of my solution and optixTriangle Solution (some might not be useful though).
I created a “cuda” folder in my solution and I pointed OPTIX_SAMPLE_NAME_DEFINE and OPTIX_SAMPLE_DIR_DEFINE to it:

OPTIX_SAMPLE_NAME_DEFINE=myKernel
OPTIX_SAMPLE_DIR_DEFINE=$(ProjectDir)cuda

When I get to:
const char* input = sutil::getInputData(OPTIX_SAMPLE_NAME, OPTIX_SAMPLE_DIR, "myKernel.cu", inputSize);

I cannot manage to make it read my file.
sutil::samplePTXFilePath couldn't locate myKernel.cu for sample myKernel

Is there a check list of how to integrate optix to an external optix-based solution? How should I make sutil::getInputData read my file?
Thanks!

The OptiX SDK application framework sets the OPTIX_SAMPLE_NAME_DEFINE and OPTIX_SAMPLE_DIR_DEFINE automatically inside the macro OPTIX_add_sample_executable of the root CMakeLists.txt.

 set_target_properties( ${target_name} PROPERTIES
    COMPILE_DEFINITIONS
    "OPTIX_SAMPLE_NAME_DEFINE=${target_name};OPTIX_SAMPLE_DIR_DEFINE=${target_name}" )

The resulting OPTIX_SAMPLE_NAME and OPTIX_SAMPLE_DIR strings will hardly contain any of the MSVS built-in variables like $(ProjectDir). That need to be valid paths.

This is what I think about hardcoding build paths into executables inside the OptiX SDK example framework:
https://forums.developer.nvidia.com/t/optixhello-embeded-in-new-application-run-in-release-but-not-in-debug-mode/253037/4
https://forums.developer.nvidia.com/t/optix7-2-sutil-getptxstring/195507/2
https://forums.developer.nvidia.com/t/sdk-samples-sutil-getptxstring-file-path/70963/2

What really confuses me on this is that I cannot figure out which file(s) does my custom optix-based solution needs to run my custom .cu. It’s something like I have changed a bit the code of optixTriangle sample and I want this changed version of it to be launched from a completely new solution.

In the modified sample of optixTriangle I have made, I see that when I run the cpp file at line:

        const char* input      = sutil::getInputData( OPTIX_SAMPLE_NAME, OPTIX_SAMPLE_DIR, "optixTriangle.cu", inputSize );

the input is actually the file optixTriangle_generated_optixTriangle.cu.optixir.
In other words,

  • I modify the optixTriangle.cu
  • build creates the optixTriangle_generated_optixTriangle.cu.optixir
  • main via optixTriangle.cpp reads the optixTriangle_generated_optixTriangle.cu.optixir

In my optix-based solution I have integrated successfully (or so I think) the optixTriangle.cpp code until the moment we ask for the input:

const char* input = sutil::getInputData(OPTIX_SAMPLE_NAME, OPTIX_SAMPLE_DIR, "myKernel.cu", inputSize);

I have 2 simple questions:

  1. do I need any other files in my solution apart from optixTriangle_generated_optixTriangle.cu.optixir which is created by modifying the optixTriangle.cu.
  2. If so, how can I have a directory in my solution with the optixTriangle_generated_optixTriangle.cu.optixir file and make the sutil::getInputData read it?

Ideally, the way to solve this seems to somehow be able to build both .cu, optixir from my custom solution and make the getInputData from my main to read it, but I am not sure how I could do it. Now I just create these 2 files from the optixTriangle sample solution and I am trying to insert/use them in sutil::getInputData of my solution main function which is problematic.
Thanks!

1.) No, if all OptiX device programs you need inside your OptiX pipeline are inside that single *.optixir file, then you don’t need an additional *.cu file and can load that as your only OptiX module, build all program group descriptions, and the pipeline from the programs inside that.
Of course if these include any headers you would need these as well to build your solution and to translate the *.cu files to their target module code.

2.) If you had carefully read all links I provided, my recommended solution is to NOT use sutil functions and its hardcoded absolute example build paths to locate your OptiX module files (*.optixir or *.ptx) at all.
Instead put them either directly next to your executable and read it with a relative path like "./optixTriangle_generated_optixTriangle.cu.optixir",
or in case you have multiple OptiX device code files and want them to be cleanly separated per application, put them into some folder relative to the executable and load them from there, something like "./my_app_name_modules/optixTriangle_generated_optixTriangle.cu.optixir" which then also doesn’t need that unique prefix "optixTriangle_generated_" to distinguish files per example anymore but can use shorter names

That way your program only uses relative paths to locate its files and would work anywhere when copied into a different folder location, which the OptiX SDK examples don’t(!) unless you set two environment variables which is a completely unnecessary restriction.

Loading *.optixir binary or *.ptx text files from disk can be done with the same function and I show that in my OptiX examples.
This builds the OptiX module paths depending on what target has been used inside the project (PTX or OptiX-IR):
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/GLTF_renderer/Application.cpp#L6357
This reads the module from disk: https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/GLTF_renderer/Application.cpp#L6386
using this function: https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/GLTF_renderer/Application.cpp#L3503

It’s that simple when not using sutil’s method with the hardcoded absolute example paths.

If you do not know how to build your CMakeLists.txt to generate the OptiX module files into the desired folder with the shorter names (e.g. optixTriangle.optixir), look into the CMake macro I’m using to generate custom build rules for the OptiX device code here:
https://github.com/NVIDIA/OptiX_Apps/blob/master/3rdparty/CMake/nvcuda_compile_module.cmake
Used here: https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/GLTF_renderer/CMakeLists.txt#L159

In case you’re building a CUDA application using the CMake native LANGUAGE CUDA feature, the CMakeLists.txt should not use that macro to build custom build rules but a CMake Object Library to separate the OptiX device code from native CUDA kernel code because latter get translated and linked to native CUDA objects.
Explained here: https://forums.developer.nvidia.com/t/code-organization-and-cmake/290506/2
and here: https://forums.developer.nvidia.com/t/converting-vs-property-sheet-into-cmake-settings/287159/5

I followed your advice and I am halfway now :)
After re-reading the programming guide and following your links:
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/GLTF_renderer/Application.cpp#L6357
This reads the module from disk: https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/GLTF_renderer/Application.cpp#L6386
using this function: https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/GLTF_renderer/Application.cpp#L3503

I managed to get rid off the sutil library, which I remember your older advice to not use it, but I didn’t remember the reason. In this case it was the fixed paths.

Now, I use the modified optixTriangle sample to build and generate the .optixir file, which then I copy to my own optix solution dedicated folder. From this directory I manage to read it and run the optixLaunch succesfully. Thank you very much for your suggestions!

This practice is not very handy as everytime I want to change something in the kernel, I have to go back to the modified optixTriangle sample solution, apply changes, rebuild and copy again manually the .optixir file to my own optix solution folder. The magic scenario would be to include the .cu file in my own solution, generate the .optixir file and place at the right folder by just building my solution.
The solution I am working on has no CMakeLists.txt file and all compiling and linking is configured by the solution properties (I don’t know if this is 100% correct).
Having included the CUDA 12.1 runtime and templates I can create for instance a new clean “hello world” cuda solution and build/run it successfully.

In my own optix-based solution the default CUDA compile and link commands are:

CUDA C/C++ Compilecommand:

# (Approximate command-line.  Settings inherited from host are not visible below.)
# (Please see the output window after a build for the full command-line)

# Driver API (NVCC Compilation Type is .cubin, .gpu, or .ptx)
set CUDAFE_FLAGS=--sdk_dir "C:\Program Files (x86)\Windows Kits\10\"
"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin\nvcc.exe" --use-local-env -ccbin "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64" -x cu      -G   --keep-dir myOwnOptixApp\x64\Debug  -maxrregcount=0   --machine 64 --compile -cudart static   -o C:\Users\myuser\code\myOwnOptixApp-master\myOwnOptixApp\x64\Debug\%(Filename)%(Extension).obj "%(FullPath)"

# Runtime API (NVCC Compilation Type is hybrid object or .c file)
set CUDAFE_FLAGS=--sdk_dir "C:\Program Files (x86)\Windows Kits\10\"
"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin\nvcc.exe" --use-local-env -ccbin "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64" -x cu      -G   --keep-dir myOwnOptixApp\x64\Debug  -maxrregcount=0   --machine 64 --compile -cudart static  -g   -Xcompiler "/EHsc  /nologo  /FS /Zi   " -Xcompiler "/Fd[ProgramDataBaseFileName]" -o C:\Users\myuser\code\myOwnOptixApp-master\myOwnOptixApp\x64\Debug\%(Filename)%(Extension).obj "%(FullPath)"

CUDA C/C++ Link command:

# (Approximate command-line.  Settings inherited from host are not visible below.)
# (Please see the output window after a build for the full command-line)

"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin\nvcc.exe" -dlink  -o myOwnOptixApp\x64\Debug\myOwnOptixApp.device-link.obj -Xcompiler "/EHsc  /nologo  /Zi   " -Xcompiler "/Fd[ProgramDataBaseFileName]" -L"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin/crt"

These obviously don’t work and I am getting:

**Error	MSB3721**	
The command ""C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin\nvcc.exe" -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env -ccbin "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\bin\HostX64\x64" -x cu   -I"C:\Program Files\Rhino 8 SDK\inc" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\cuda" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\build\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\build" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\support\imgui\.." -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\support\." -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\sutil\\" -I"C:\Users\myuser\code\myOwnOptixApp-master\\" -I"C:\Users\myuser\source\repos\vcpkg\vcpkg\installed\x64-windows\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\include"  -G   --keep-dir myOwnOptixApp\x64\Debug  -maxrregcount=0   --machine 64 --compile -cudart static -Mnopgdllmain -g  -DWIN64 -D_WINDOWS -DNDEBUG -D_USRDLL -DOPTIX_SAMPLE_NAME_DEFINE=optixTriangle -DOPTIX_SAMPLE_DIR_DEFINE=optixTriangle -D_USE_MATH_DEFINES -DNOMINMAX -DGLFW_DLL -DGLAD_GLAPI_EXPORT -D"CMAKE_INTDIR=\"Debug\"" -D_WINDLL -D_UNICODE -DUNICODE -D_AFXDLL -Xcompiler "/EHsc /W4 /nologo /Od /FS /Zi  /MD " -Xcompiler "/FdmyOwnOptixApp\x64\Debug\vc143.pdb" -o C:\Users\myuser\code\myOwnOptixApp-master\myOwnOptixApp\x64\Debug\File.cu.obj "C:\Users\myuser\code\myOwnOptixApp-master\File.cu"" 

exited with code 1.

	myOwnOptixApp	C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\BuildCustomizations\CUDA 12.1.targets	799

My question is if there is a way to modify the compile and link properties of my optix solution in order to make my .cu build along with the rest of my solution and place the .optixir file at the proper directory. Alternatively, what steps should I follow to manage it?
Thanks!

This practice is not very handy as everytime I want to change something in the kernel, I have to go back to the modified optixTriangle sample solution, apply changes, rebuild and copy again manually the .optixir file to my own optix solution folder.

That’s shouldn’t be necessary at all when setting up a standalone solution with all source files required to build your application.

The magic scenario would be to include the .cu file in my own solution, generate the .optixir file and place at the right folder by just building my solution.

Exactly!

If you use CMake instead to build the MSVS solution, the process to do that is described inside the links I provided.

If you want to use the CUDA Visual Studio Integration, you MUST change the compilation of the input *.cu files to a translation to *.ptx or *.optixir.
You MUST NOT compile the OptiX device code to CUDA object code like you’re doing above.
Read the nvcc.exe --help output for the necessary command line arguments.

Seriously, both of these things are explained inside the two links I already provided.
You are doing exactly the same error as in this thread:
https://forums.developer.nvidia.com/t/converting-vs-property-sheet-into-cmake-settings/287159
This one even links to a thread where I explained the same thing to you before:
https://forums.developer.nvidia.com/t/code-organization-and-cmake/290506

I would like to ask some very plain questions in order to clear out some concepts described in the provided links. I feel the reason for not managing to include the optix cu code in my solution build is because there are some undecided options that keep confusing me.

As I said I have successfully built an new optix based solution which reads an externally generated .optixir file. I add new item, the .cu file. I press build, it fails as described above.

  1. In order to build my .cu file inside my solution, do I need to create any new file or can I do it only by configuring the project properties tab?

  2. Should I add in Build Dependencies->Build Customizations the CUDA 12.1 (targets, props)?

  3. Could I simply run a pre build event and run the proper nvcc command? I tried this with no success:
    "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin\nvcc.exe" --optix-ir "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\bin\Hostx86\x64" -x cu -I"C:\Program Files\Rhino 8 SDK\inc" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\cuda" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\build\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\build" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\include" -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\support\imgui\.." -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\support\." -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\sutil\\" -I"C:\Program Files\Rhino 8 SDK\inc" -I"C:\Users\tgf\source\repos\vcpkg\vcpkg\installed\x64-windows\include" -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\include" -G --keep-dir x64\Debug -maxrregcount=0 --machine 64 -g -DWIN32 -DWIN64 -D_DEBUG -D_CONSOLE -D_MBCS -Xcompiler "/EHsc /W3 /nologo /Od /FS /Zi /RTC1 /MDd " --compile--use_fast_math File.cu \ -o File.optixir

  4. Is there a guide like this for integrating Optix .cu files to VS solution?:
    Configure CUDA Project Properties
    Thanks!

In order to build my .cu file inside my solution, do I need to create any new file or can I do it only by configuring the project properties tab?

To setup a standalone OptiX application, you should put all files which belong to your application into your own application folder(s).
That is, you do not reference any *.cpp or *.cu source files directly from the OptiX SDK, except for the things inside OptiX SDK <version>/include which defines the OptiX 7 or 8 API and some helper functions.
Instead you copy everything you need to your local application folders and then build your project from those.

Everything the OptiX SDK examples do to setup their own application framework is not strictly necessary inside your own OptiX applications.
The only thing you really need, are the OptiX API headers inside the include folder.
Just look at my examples. I’m only using the headers from the OptiX SDK include folder, nothing else.

If you insist on using the OptiX SDK sutil library, which I would highly discourage, then you should also copy the necessary files locally and use them inside your code directly instead of building a library. The basic headers in there are useful but if you want your own OptiX application framework, you should only learn from the things done inside sutil.cpp.

Should I add in Build Dependencies->Build Customizations the CUDA 12.1 (targets, props)?

How you configure your own application MSVS solution is your choice!

If you want to use CMake to easily build solutions for various platforms and compilers, look at how my standalone CMake scripts do it.

If you want to build your own solution and projects manually inside the MSVS IDE and use the CUDA Visual Studio Integration to control the translation rules for each *.cu file individually, that is also possible, but that is tedious and you must meticulously set every NVCC options exactly as required for the OptiX device code.

The default CUDA compilation settings won’t work for OptiX device code!
Read all comments I added to the nvcc.exe command line options here again.

Could I simply run a pre build event and run the proper nvcc command? I tried this with no success:

Because you are still doing exactly the same error as in the thread I linked above.

That command line compiles a *.cu file to a native CUDA object module because of the --compile option inside that. That is simply wrong for OptiX device code *.cu files.
Instead you must use only either --ptx to translate to PTX intermediate source code or --optixir to translate to OptiX-IR intermediate binary code. Either is what optixCreateModule requires.

Let’s do the same analysis like in the above links:

"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin\nvcc.exe"
 --optix-ir // You cannot have --optixir and --compile inside the same nvcc command line!
 "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\bin\Hostx86\x64" // This looks wrong. Is there a --ccbin missing before this?
 -x cu // This lets nvcc handle all given input files as *.cu files. Not necessary when the only input file is *.cu anyway.
 -I"C:\Program Files\Rhino 8 SDK\inc"
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\include" // Yes, required.
  // I do not recommend referencing any other files inside the OptiX SDK directly when building own applications. 
  // They can change with any OptiX SDK version. Copy them locally and include them from your own application folders.
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\cuda" 
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK"
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\build\include" // No. Anything in build is just a copy of the original SDK sources. 
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\build" // No
 -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\include" // Yes, required.
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\support\imgui\.."
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\support\."
 -I"C:\ProgramData\NVIDIA Corporation\OptiX SDK 8.0.0\SDK\sutil\\"
 -I"C:\Program Files\Rhino 8 SDK\inc" // Duplicate.
 -I"C:\Users\tgf\source\repos\vcpkg\vcpkg\installed\x64-windows\include"
 -I"C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\include" // Duplicate
 -G // Avoid this. Debug device code will be really slow.
 --keep-dir x64\Debug // Unnecessary when not using --keep, which is also not necessary other than for CUDA compiler bugs.
 -maxrregcount=0 // OK
 --machine 64 // Yes, required.
 -g // Debug host code is not needed when only building OptiX device code 
 -DWIN32 
 -DWIN64
 -D_DEBUG
 -D_CONSOLE
 -D_MBCS
 -Xcompiler "/EHsc /W3 /nologo /Od /FS /Zi /RTC1 /MDd "
 --compile--use_fast_math  // The --compile is wrong when it's used. There is a space missing here. --use_fast_math is recommended for performance 
 File.cu \ -o File.optixir // Not sure why there is a backslash, it's single line. Rest is OK, File.cu is the input, File.optixir is the output

Is there a guide like this for integrating Optix .cu files to VS solution?:

You need to set all CUDA compilation options exactly as described here:
https://raytracing-docs.nvidia.com/optix8/guide/index.html#program_pipeline_creation#program-input

I would still recommend using CMake and following the process described here. That will save a lot of time in the long run.
https://forums.developer.nvidia.com/t/converting-vs-property-sheet-into-cmake-settings/287159/5