Add OptiX to existing Visual Studio Project

Hello,

I’ve got an existing OpenGL renderer project that should be enhanced by OptiX Raytracing. So the core question is: How do I add OptiX Support to existing VS projects?

To start with the issue, I grabbed some code from an OptiX course (GitHub - ingowald/optix7course) and created a new empty VS project (the “existing” sandbox project) to which I’m adding code from that course.

Adding the first code from the “OptiX Init Test Example” worked just fine, however, moving on from there I ended up with those errors:

Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 68; error : Call to '_optix_get_launch_index_x' requires call prototype
Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 74; error : Call to '_optix_get_launch_index_y' requires call prototype
Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 136; error : Call to '_optix_get_launch_index_x' requires call prototype
Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 139; error : Call to '_optix_get_launch_index_y' requires call prototype
Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 68; error : Unknown symbol '_optix_get_launch_index_x'
Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 74; error : Unknown symbol '_optix_get_launch_index_y'
Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 136; error : Unknown symbol '_optix_get_launch_index_x'
Temp/tmpxft_00006a48_00000000-7_devicePrograms.ptx, line 139; error : Unknown symbol '_optix_get_launch_index_y'

I managed to build the OptiX examples with cmake without any problems, though, so this is most likely caused by wrong settings for the .cu files (seems like NVCC isn’t the right thing, as cmake sets the build tool to custom whereas in the existing project uses CUDA C/C++ build tools. So I checked the cmake files of the OptiX examples, but… the information is buried deep…

So, are there somewhere step by step instructions to add OptiX to an existing project or any other info to make it work in an existing project?

The existing project isn’t a cmake project, though.

From the error messages, you’re probably missing some OptiX include directories in the build setting of your *.cu to *.ptx translation step.

Hmm, or you’re actually not only translating to PTX, but try to build CUBINs and those do not know about the OptiX device code intrinsics because those are translated by OptiX from the input PTX code.
Means you’re compiling the *.cu code to the wrong target. It needs to compile to the --ptx target only.

How do I add OptiX Support to existing VS projects?

Please have a look into the OptiX SDK 7.6.0 example optixConsole.
As mentioned inside the OptiX SDK Release Notes:
New sample optixConsole
demonstrates how to build OptiX applications in Microsoft Visual Studio without the use of CMake
Prints to stdout an OptiX generated image converted to ASCII art

It contains a *.vcxproj and *.sln file.

Please look through the individual settings done for all *.cu files inside the CUDA Visual Studio Integration.

Both build environments (CMake custom build rules and the CUDA Visual Studio Integration) are using the NVCC compiler in the end.

You basically need to set all CUDA compiler settings to the values mentioned in this section of the OptiX Programming Guide:
https://raytracing-docs.nvidia.com/optix7/guide/index.html#program_pipeline_creation#program-input

Thank you very much for your help. I’ll try it.

So, turns out, all I had to change in my already set up property sheet was the NVCC compilation type.

So, my (probably) final issue is to emulate the cuda_compile_and_embed behaviour used in the cmakelists of the example code. Unfortunately, I couldn’t figure out so far where the function even comes from, but it’s probably linked to the c++ code.

There’s this call:

cuda_compile_and_embed(embedded_ptx_code devicePrograms.cu)

and embedded_ptx_code is then used in the cpp file as

extern "C" char embedded_ptx_code[];

and later as

const std::string ptxCode = embedded_ptx_code;

char log[2048];
size_t sizeof_log = sizeof(log);
OPTIX_CHECK(optixModuleCreateFromPTX(optixContext, &moduleCompileOptions, &pipelineCompileOptions, ptxCode.c_str(), ptxCode.size(), log, &sizeof_log, &module));
if (sizeof_log > 1)
	PRINT(log);

So the function probably creates some sort of connection between this extern c call and the cu file. Is there a way to do that directly in visual studio? The console example doesn’t help here, as it doesn’t use any cu files.

Thank you very much for your help

Great.

You don’t necessarily need to embed the PTX code inside your executable.
You could also simply load it from disk and call optixModuleCreateFromPTX() with the loaded input source code.
I do that all the time and this is probably reducing the turnaround times when developing as well.

Here’s a code example from one of my OptiX 7 applications doing that with PTX or OptiX IR input:
https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/rtigo10/src/Device.cpp#L627

If you really want to embed the input data into the executable’s data segment, Ingo’s examples use the bin2c tool inside the CUDA toolkit which converts any data into a char array inside a C source.

If you search the repository for cuda_compile_and_embed you’ll find that macro inside ingowald\optix7course\common\gdt\cmake\configure_optix.cmake

That compiles the *.cu files to *.ptx and generates a custom build rule for each of the *.ptx files in which it calls CUDA’s bin2c executable with its proper command line options to generate a matching *.c file with the respective char array containing the data.

Since CMake can generate that as custom build rule, Visual Studio should be able to do the same.
I just don’t know how because I’m also using CMake for that to be platform independent. :-)
Looks like the *.vcxproj contains the call to CMake to generate custom build rules on the fly.

A search for “creating custom build rules in Visual Studio” turned up this page:
https://learn.microsoft.com/en-us/cpp/build/understanding-custom-build-steps-and-build-events?view=msvc-170

If you want to see what command line such custom build rules execute exactly, you need to raise MSBuild verbosity levels inside Visual Studio under: the menu Tools → Options → Projects and Solutions → Build And Run.
Maybe that helps understanding what the example repository does exactly.

Thank you very much for your help. I went with the first option and it’s compiling (and even working) now.

Only thing is that I would have expected an *.optixir or *.ptx file to be created somewhere. Instead, an obj file is created (redirected from the intermediate folder for easier reading), as it is set up.

image

However, if I change .obj to .ptx or .optixir the build fails, saying that the nvcc linking process has no idea what to do with the ptx or optixir file. Is the nvcc linking here needed at all? And is there a way to disable it?

Kind regards and thank you very much

Is the nvcc linking here needed at all?

No, for OptiX device code the *.cu compilation must only generate PTX or OptiX IR sources which are both intermediate representations and go into the optixModuleCreateFromPTX() function at application runtime.

You cannot link these to CUDA object files because, as you’ve experienced, there are OptiX intrinsics inside the code which do not exist as code but get replaced by an OptiX internal parser to the resp. underlying CUDA instructions which only then can get compiled by the CUDA driver.

I would compare the CUDA C/C++ command line of the *.cu files inside the optixConsole solution with the command line in your project’s *.cu files and change all parameters until they look identical in both release and debug targets.

Well, since there was no CUDA C/C++ section in the settings for the *.cu files (seems like those settings are only limited to a single project in a solution? Totally strange, somehow) and the nvcc reported the error “don’t know what to do with an *.optixir file” I set the -dlink to no in the CUDA Linker section and it seems to work now even with the Compiler Output (previous image) extension set to *.optixir. Thank you very much for your help.