Error Compiling .ptx files from within Visual Studio

Hello,
I have trouble compiling .ptx Files from within Visual Studio, I’ll tell you what i’m trying to do and go into the exact error afterwards

Optix Prime 3.7
Windows 7 Enterprise
Visual Studio 2012

I’m working with the “tutorial” project and i’m trying to add a sphere to this scene.
In order to do so i’ve basically copied the sample5pp sphere.cu file and added the following in the main “tutorial.cpp”

std::string sphere_ptx( ptxpath( "tutorial", "sphere.cu" ) ); 
  Program sphere_bounds = m_context->createProgramFromPTXFile( sphere_ptx, "sphere_bounds" );
  Program sphere_intersect = m_context->createProgramFromPTXFile( sphere_ptx, "sphere_intersect" );


  Geometry sphere = m_context->createGeometry();
  sphere->setPrimitiveCount( 1u );
  sphere->setBoundingBoxProgram( sphere_bounds ); //TO be written: sphere_bounds, sphere_intersect
  sphere->setIntersectionProgram( sphere_intersect );
  sphere["sphere"]->setFloat( 0, 0, 0, 1.5 );

  Material sphere_matl = m_context->createMaterial();
  Program sphere_ch = m_context->createProgramFromPTXFile( m_ptx_path , "closest_hit_radiance" );
  sphere_matl->setClosestHitProgram( 0, sphere_ch );

to the createGeometry part.

now if i try to compile sample5pp i get an compilation error

1>------ Build started: Project: sample5pp, Configuration: Debug x64 ------
1>  Building NVCC ptx file lib/ptx/sample5pp_generated_sphere.cu.ptx
1>  CMake Warning (dev) at sample5pp_generated_sphere.cu.ptx.cmake:136 (if):
1>    Policy CMP0054 is not set: Only interpret if() arguments as variables or
1>    keywords when unquoted.  Run "cmake --help-policy CMP0054" for policy
1>    details.  Use the cmake_policy command to set the policy and suppress this
1>    warning.
1>  
1>    Quoted keywords like "COMMAND" will no longer be interpreted as keywords
1>    when the policy is set to NEW.  Since the policy is not set the OLD
1>    behavior will be used.
1>  Call Stack (most recent call first):
1>    sample5pp_generated_sphere.cu.ptx.cmake:219 (cuda_execute_process)
1>  This warning is for project developers.  Use -Wno-dev to suppress it.
1>  
1>  sphere.cu
1>  
1>  sphere.cu
1>  
1>C:/ProgramData/NVIDIA Corporation/OptiX SDK 3.7.0/SDK/sample5pp/sphere.cu(55): error : identifier "use_robust_method" is undefined
1>  
1>  1 error detected in the compilation of "C:/Users/BLOODY~1/AppData/Local/Temp/tmpxft_00001694_00000000-8_sphere.cpp1.ii".
1>  
1>  CMake Error at sample5pp_generated_sphere.cu.ptx.cmake:320 (message):
1>    Error generating file
1>    C:/Users/bloodydragon/Documents/OptiX/lib/ptx/sample5pp_generated_sphere.cu.ptx
1>  
1>  
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========

I compile by checking CUDA 7.0 in the Build Customizations of the project

In my tutorial project the sphere.cu file contains the following:

/*
 * Copyright (c) 2008 - 2009 NVIDIA Corporation.  All rights reserved.
 *
 * NVIDIA Corporation and its licensors retain all intellectual property and proprietary
 * rights in and to this software, related documentation and any modifications thereto.
 * Any use, reproduction, disclosure or distribution of this software and related
 * documentation without an express license agreement from NVIDIA Corporation is strictly
 * prohibited.
 *
 * TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS*
 * AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE.  IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY
 * SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT
 * LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF
 * BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
 * INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGES
 */

#include <optix_world.h>
#include <optixu/optixu_math_namespace.h>
#include <optixu/optixu_matrix_namespace.h>
#include <optixu/optixu_aabb_namespace.h>

using namespace optix;

rtDeclareVariable(float4,  sphere, , );
rtDeclareVariable(float3, geometric_normal, attribute geometric_normal, ); 
rtDeclareVariable(float3, shading_normal, attribute shading_normal, ); 
rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );

template<bool use_robust_method>

RT_PROGRAM void sphere_intersect(int)
{
  float3 center = make_float3(sphere);
  float3 O = ray.origin - center;
  float3 D = ray.direction;
  float radius = sphere.w;

  float b = dot(O, D);
  float c = dot(O, O)-radius*radius;
  float disc = b*b-c;
  if(disc > 0.0f){
    float sdisc = sqrtf(disc);
    float root1 = (-b - sdisc);

    bool do_refine = false;

    float root11 = 0.0f;

    if(use_robust_method && fabsf(root1) > 10.f * radius) {
      do_refine = true;
    }

    if(do_refine) {
      // refine root1
      float3 O1 = O + root1 * ray.direction;
      b = dot(O1, D);
      c = dot(O1, O1) - radius*radius;
      disc = b*b - c;

      if(disc > 0.0f) {
        sdisc = sqrtf(disc);
        root11 = (-b - sdisc);
      }
    }

    bool check_second = true;
    if( rtPotentialIntersection( root1 + root11 ) ) {
      shading_normal = geometric_normal = (O + (root1 + root11)*D)/radius;
      if(rtReportIntersection(0))
        check_second = false;
    } 
    if(check_second) {
      float root2 = (-b + sdisc) + (do_refine ? root1 : 0);
      if( rtPotentialIntersection( root2 ) ) {
        shading_normal = geometric_normal = (O + root2*D)/radius;
        rtReportIntersection(0);
      }
    }
  }
}

RT_PROGRAM void sphere_bounds (int, float result[6])
{
  const float3 cen = make_float3( sphere );
  const float3 rad = make_float3( sphere.w );

  optix::Aabb* aabb = (optix::Aabb*)result;
  
  if( rad.x > 0.0f  && !isinf(rad.x) ) {
    aabb->m_min = cen - rad;
    aabb->m_max = cen + rad;
  } else {
    aabb->invalidate();
  }
}

If i build the tutorial project i get:

1>------ Build started: Project: tutorial, Configuration: Debug x64 ------
1>sphere.cu.obj : error LNK2019: unresolved external symbol cudaSetupArgument referenced in function “void __cdecl __device_stub__Z13sphere_boundsiPf(int,float *)” (?__device_stub__Z13sphere_boundsiPf@@YAXHPEAM@Z)
1>sphere.cu.obj : error LNK2019: unresolved external symbol cudaLaunch referenced in function “enum cudaError __cdecl cudaLaunch(char *)” (??$cudaLaunch@D@@YA?AW4cudaError@@PEAD@Z)
1>sphere.cu.obj : error LNK2019: unresolved external symbol __cudaRegisterFatBinary referenced in function “void __cdecl __nv_cudaEntityRegisterCallback(void * *)” (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)
1>sphere.cu.obj : error LNK2019: unresolved external symbol __cudaUnregisterFatBinary referenced in function “void __cdecl __cudaUnregisterBinaryUtil(void)” (?__cudaUnregisterBinaryUtil@@YAXXZ)
1>sphere.cu.obj : error LNK2019: unresolved external symbol __cudaRegisterVar referenced in function “void __cdecl __nv_cudaEntityRegisterCallback(void * *)” (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)
1>sphere.cu.obj : error LNK2019: unresolved external symbol __cudaRegisterFunction referenced in function “void __cdecl __nv_cudaEntityRegisterCallback(void * *)” (?__nv_cudaEntityRegisterCallback@@YAXPEAPEAX@Z)
1>C:\Users\bloodydragon\Documents\OptiX\bin\Debug\tutorial.exe : fatal error LNK1120: 6 unresolved externals
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========

Can you explain to me wheter my apporach to building is flawed - how come sample projects cannot be build?
or what else could be wrong?

lg
Mike

PS: please let me know how to improve my question asking approach

First, OptiX 3.7.0 does not support CUDA 7.0.
Please always refer to the OptiX Release Notes before setting up a development environment for OptiX.

You would either need to use CUDA 6.5 for OptiX 3.7.0 or use OptiX 3.8.0 for CUDA 7.0.
I would always recommend to use the newest available OptiX release due to bug fixes which went into the latest versions.

The errors in the tutorial example should come from that incorrect CUDA 7.0 use on OptiX 3.7.0.

Second, comparing with the original code of sphere.cu you removed the templated versions and forgot to also remove template in line 33 of your above code which makes your RT_PROGRAM a template but it’s never used like that.

Because files inside the samples/cuda folder are shared by all examples the error …/sample5pp/sphere.cu(55): error : identifier “use_robust_method” is undefined is because you broke the file for that sample. Not sure where you wanted to copy things (see below) but it looks like you inadvertently edited the shared version.

You’d need to keep the sphere.cu file with the two RT_PROGRAMs void intersect(int primIdx) and void robust_intersect(int primIdx) intact. A lot of the SDK examples use these.

My recommendation for own OptiX examples is to copy all required *.cu files into your new example sub-folder. I think the CMakeLists.txt inside the example’s sub-folder will look in the local directory first. If not, there are CMake variables resolving the current path like the CMAKE_CURRENT_SOURCE_DIR variable.
Another way would be to copy the files you want to change inside the samples/cuda folder to own filenames to prevent breaking shared files, but that adds clutter.

Hello Developer,
I have been trying the same thing(placing sphere in tutorial example), I have copied sphere.cu file to tutorial, than I have added the following code in createGeometry class of tutorial.cpp (shown below), I didnt get any error in building , but my program does not work in the end it gives a message that “The program ‘[9076] tutorial.exe’ has exited with code 2 (0x2).”

void Tutorial::createGeometry()
{
	//sphere 
	std::string sphere_ptx(ptxpath("tutorial", "sphere.cu"));
	Program sphere_bounds = m_context->createProgramFromPTXFile(sphere_ptx, "sphere_bounds");
	Program sphere_intersect = m_context->createProgramFromPTXFile(sphere_ptx, "sphere_intersect");


	Geometry sphere = m_context->createGeometry();
	sphere->setPrimitiveCount(1u);
	sphere->setBoundingBoxProgram(sphere_bounds); //TO be written: sphere_bounds, sphere_intersect
	sphere->setIntersectionProgram(sphere_intersect);
	sphere["sphere"]->setFloat(0, 0, 0, 1.5);

	Material sphere_matl = m_context->createMaterial();
	Program sphere_ch = m_context->createProgramFromPTXFile(m_ptx_path, "closest_hit_radiance");
	sphere_matl->setClosestHitProgram(0, sphere_ch);

Secondly, I didn’t copy PTX file, how could we generate PTX file from Visual Studio?

Did you run a debug version of it inside a debugger?
That should allow you to find where the failure is coming from.

If you want to add files to an OptiX SDK example, you need to change the CMakeLists.txt file inside that example and add the desired filename to the list of sources.

Then start CMake and regenerate the whole samples solution by pointing to the top-level(!) CMakelists.txt file inside the OptiX SDK 3.8.0\SDK folder.
That also contains the documentation for how to use this file and how to add own samples.

Once the solution is regenerated by CMake, re-load it in Visual Studio and rebuild your changed example.

That should take care of generating the necessary PTX files under their proper names and place them where they are expected as specified by the custom build scripts inside the CMakeLists.txt files used.

Thankyou for your reply, I am just running tutorial.cpp in visual studio 2013, it didnt show any error in building nor it highlights any error, but when I run the program it gives that message?
One more thing, I dont have nay optiX wizard in my visual studio.

Sorry, I have no experience with that wizard.
There is an “assemblies” folder after a full OptiX installation which contains the only file with “wizard” in the name. Maybe unzip the archive with the demo project next to it and see what you get.

I also wasn’t up-to-date on the structure of SDK examples after the installation. Looks like most *.cu files are actually inside the individual example sub-folders which reduces the chance to break other examples’ code.
The rest still applies: Don’t use CUDA 7.0 before OptiX 3.8.0, edit the CMakeLists.txt files when adding files to examples, don’t break shared files in the sample/cuda folder.

Thankyou so much foe your help. I have succefully added my own .cu file in one of the example.
I will try this thing for wizard.
Thankyou

Thank you so much for your help!

(it took me a while to get it running, i forgot to set variables for the sphere material)
Adding sphere.cu to the SDK folder and in the CMakeLists file did the trick! Thank you!

lg Mike