SLProject  4.3.020
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLOptixHelper.h
Go to the documentation of this file.
1 /**
2  * \file SLOptixHelper.h
3  * \brief Error checking macros and helpers for the OptiX ray tracer
4  * \details Everything in this header is compiled only when SL_HAS_OPTIX is
5  * defined, which the build sets when SL_BUILD_WITH_OPTIX is ON
6  * (OFF by default). SL_HAS_OPTIX is not in the Doxyfile PREDEFINED
7  * list either, so none of these symbols appear in the generated
8  * documentation — read the header itself.
9  *
10  * The OPTIX_CHECK, OPTIX_CHECK_LOG, CUDA_CHECK and CUDA_SYNC_CHECK
11  * macros wrap a call, compare its result against the success code
12  * and throw an SLOptixException carrying the file and line on
13  * failure. They are adapted from NVIDIA's OptiX sutil samples.
14  * \date October 2019
15  * \authors Nic Dorner
16  * \copyright http://opensource.org/licenses/GPL-3.0
17  * \remarks Please use clangformat to format the code. See more code style on
18  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
19  */
20 
21 #ifdef SL_HAS_OPTIX
22 # ifndef SLOPTIXHELPER_H
23 # define SLOPTIXHELPER_H
24 
25 # include <iostream> // std::cout, std::ios
26 # include <sstream> // std::ostringstream
27 # include <stdexcept>
28 # include <string>
29 # include <functional>
30 # include <chrono>
31 # include <SLVec3.h>
32 # include <SLVec4.h>
33 
34 using namespace std;
35 
36 using namespace std::placeholders;
37 using namespace std::chrono;
38 
39 // Optix error-checking and CUDA error-checking are copied from nvidia optix sutil
40 //------------------------------------------------------------------------------
41 // OptiX error-checking
42 //------------------------------------------------------------------------------
43 
44 # include <optix_stubs.h>
45 // clang-format off
46 //------------------------------------------------------------------------------
47 #define OPTIX_CHECK( call ) \
48  { \
49  OptixResult res = call; \
50  if( res != OPTIX_SUCCESS ) \
51  { \
52  stringstream ss; \
53  ss << "Optix call '" << #call << "' failed: " __FILE__ ":" \
54  << __LINE__ << ")\n"; \
55  throw SLOptixException( res, ss.str().c_str() ); \
56  } \
57  }
58 //------------------------------------------------------------------------------
59 #define OPTIX_CHECK_LOG( call ) \
60  { \
61  OptixResult res = call; \
62  if( res != OPTIX_SUCCESS ) \
63  { \
64  stringstream ss; \
65  ss << "Optix call '" << #call << "' failed: " __FILE__ ":" \
66  << __LINE__ << ")\nLog:\n" << log \
67  << ( sizeof_log > sizeof( log ) ? "<TRUNCATED>" : "" ) \
68  << "\n"; \
69  throw SLOptixException( res, ss.str().c_str() ); \
70  } \
71  }
72 //------------------------------------------------------------------------------
73 // CUDA error-checking
74 //------------------------------------------------------------------------------
75 
76 #define CUDA_CHECK( call ) \
77  { \
78  CUresult result = call; \
79  if( result != CUDA_SUCCESS ) \
80  { \
81  const char *errorstr; \
82  cuGetErrorString(result, &errorstr); \
83  stringstream ss; \
84  ss << "CUDA call (" << #call << " ) failed with error: '" \
85  << errorstr \
86  << "' (" __FILE__ << ":" << __LINE__ << ")\n" \
87  << result << "\n"; \
88  throw SLOptixException( ss.str().c_str() ); \
89  } \
90  }
91 //------------------------------------------------------------------------------
92 #define CUDA_SYNC_CHECK( call ) \
93  { \
94  CUstream stream = call; \
95  CUresult result = cuStreamSynchronize(stream); \
96  if( result != CUDA_SUCCESS ) \
97  { \
98  const char *errorstr; \
99  cuGetErrorString(result, &errorstr); \
100  stringstream ss; \
101  ss << "CUDA error on synchronize with error '" \
102  << errorstr \
103  << "' (" __FILE__ << ":" << __LINE__ << ")\n"; \
104  throw SLOptixException( ss.str().c_str() ); \
105  } \
106  }
107 //------------------------------------------------------------------------------
108 // clang-format on
109 //! Exception thrown by the OPTIX_CHECK and CUDA_CHECK macros on failure
110 class SLOptixException : public std::runtime_error
111 {
112 public:
113  //! Constructs the exception from a ready-made message
114  SLOptixException(const char* msg)
115  : std::runtime_error(msg)
116  {
117  }
118 
119  //! Constructs the exception from an OptiX result code and a message
120  /*! The result code is expanded to its OptiX error name and prefixed to
121  the message, so the thrown what() reads "ERROR_NAME: message". */
122  SLOptixException(OptixResult res, const char* msg)
123  : std::runtime_error(createMessage(res, msg).c_str())
124  {
125  }
126 
127 private:
128  //! Prefixes msg with the OptiX error name belonging to res
129  string createMessage(OptixResult res, const char* msg)
130  {
131  std::ostringstream os;
132  os << optixGetErrorName(res) << ": " << msg;
133  return os.str();
134  }
135 };
136 //------------------------------------------------------------------------------
137 //! Reads a compiled PTX module from file, for handing to the OptiX pipeline
138 /*! \param filename Name of the CUDA C input file whose PTX is read
139  \param log Optional pointer to a compiler log string; no output when
140  *log is NULL
141  \return The PTX source as a string */
142 string getPtxStringFromFile(
143  string filename, // Cuda C input file name
144  const char** log = NULL); // (Optional) pointer to compiler log string. If *log == NULL there is no output.
145 //------------------------------------------------------------------------------
146 //! Converts an SLVec4f into the CUDA float4 the device code expects
147 float4 make_float4(const SLVec4f& f);
148 //------------------------------------------------------------------------------
149 //! Converts an SLVec3f into the CUDA float3 the device code expects
150 float3 make_float3(const SLVec3f& f);
151 //------------------------------------------------------------------------------
152 # endif // SLOPTIXHELPER_H
153 #endif // SL_HAS_OPTIX
void log(const char *tag, const char *format,...)
logs a formatted string platform independently
Definition: Utils.cpp:1100