I’ve been looking into using Nvidia Optix for my Fractal lookdev tool, as I need realtime feedback while traversing the landscape.

I really like the API so far, it even comes with a Julia example demo in the SDK! I’ve modified it to render the Mandelbulb instead, with little trouble (and with refraction).

12318072_10208255826582355_1853094794_o

However, I needed to read the buffer data to write .exr’s to disk (this is a vital feature, better to make sure it’s viable at the beginning of the project). That shouldn’t be a problem, as I can easily grab the buffer’s device pointer and then cudaMemcpy it over.

All I need to do is include and , no big deal right?

#include <cuda.h>
#include <cuda_runtime.h>

#include <optixu/optixpp_namespace.h>
#include <optixu/optixu_math_namespace.h>
Linking CXX executable ../bin/julia
CMakeFiles/julia.dir/julia.cpp.o: In function `AnimCamera::apply(optix::Handle<optix::ContextObj>)':
/home/tom/src/optix/SDK/julia/julia.cpp:151: undefined reference to `PinholeCamera::PinholeCamera(float3, float3, float3, float, float, PinholeCamera::AspectRatioMode)'
/home/tom/src/optix/SDK/julia/julia.cpp:153: undefined reference to `PinholeCamera::getEyeUVW(float3&, float3&, float3&, float3&)'
collect2: error: ld returned 1 exit status

Oh.

Well maybe it’s because I included them before OptiX.

#include <optixu/optixpp_namespace.h>
#include <optixu/optixu_math_namespace.h>

#include <cuda.h>
#include <cuda_runtime.h>

using namespace optix;

/usr/local/cuda-7.0/include/cuda_runtime_api.h:257:17: error: ‘cudaError_t’ does not name a type
 extern __host__ cudaError_t CUDARTAPI cudaDeviceReset(void);
                 ^
/usr/local/cuda-7.0/include/cuda_runtime_api.h:274:36: error: ‘cudaError_t’ does not name a type
 extern __host__ __cudart_builtin__ cudaError_t CUDARTAPI cudaDeviceSynchronize(void);
                                    ^
/usr/local/cuda-7.0/include/cuda_runtime_api.h:349:17: error: ‘cudaError_t’ does not name a type
 extern __host__ cudaError_t CUDARTAPI cudaDeviceSetLimit(enum cudaLimit limit, size_t value);
                 ^

...

/home/tom/src/optix/SDK/julia/julia.cpp:299:95: error: ‘cudaMemcpy’ was not declared in this scope
   cudaMemcpy( (void*)h_ptr, (void*)d_ptr, sizeof(float) * totalPixels, cudaMemcpyDeviceToHost );

Oh.

This is dire, could it be related to the optix namespace somehow?

#include <optixu/optixpp_namespace.h>
#include <optixu/optixu_math_namespace.h>
using namespace optix;

#include <cuda.h>
#include <cuda_runtime.h>
Linking CXX executable ../bin/julia
[100%] Built target tutorial

Success! Looks blindly using the optix namespace causes clashes with Cuda, setting it up like I did above fixes that in a janky way. Maybe this is mentioned in the documentation somewhere but I never found any reference to it.

So if you’re getting undefined references when you need cudaMemcpy in an OptiX project, check out your include order and namespace setup (and don’t forget to add ${CUDA_LIBRARIES} to target_link_libraries in the cmake configuration if it’s not there already).

The best solution would be to only bring in the stuff you actually need from the optix namespace, so there’s no namespace clashing at all.

So far OptiX seems pretty solid though, I hope I’ll have fun with it!

Update

Turns out in this particular instance I was better off using the map() and unmap() functions within the Optix Buffer class instead of cudaMemcpy(), they remove the dependency of including the CUDA headers. However, I would no doubt have run into the same problems using something like the NVRTC headers.