| 1 | // Copyright 2009-2021 Intel Corporation |
| 2 | // SPDX-License-Identifier: Apache-2.0 |
| 3 | |
| 4 | #pragma once |
| 5 | |
| 6 | #if defined (__AVX__) |
| 7 | #pragma GCC target("no-sse3") |
| 8 | #endif |
| 9 | |
| 10 | #define _CRT_SECURE_NO_WARNINGS |
| 11 | |
| 12 | #include <cstddef> |
| 13 | #include <cassert> |
| 14 | #include <cstdlib> |
| 15 | #include <cstdio> |
| 16 | #include <memory> |
| 17 | #include <stdexcept> |
| 18 | #include <iostream> |
| 19 | #include <iomanip> |
| 20 | #include <fstream> |
| 21 | #include <string> |
| 22 | #include <cstring> |
| 23 | #include <stdint.h> |
| 24 | #include <functional> |
| 25 | |
| 26 | //////////////////////////////////////////////////////////////////////////////// |
| 27 | /// detect platform |
| 28 | //////////////////////////////////////////////////////////////////////////////// |
| 29 | |
| 30 | /* detect 32 or 64 Intel platform */ |
| 31 | #if defined(__x86_64__) || defined(__ia64__) || defined(_M_X64) |
| 32 | #define __X86_64__ |
| 33 | #define __X86_ASM__ |
| 34 | #elif defined(__i386__) || defined(_M_IX86) |
| 35 | #define __X86_ASM__ |
| 36 | #endif |
| 37 | |
| 38 | /* detect 64 bit platform */ |
| 39 | #if defined(__X86_64__) || defined(__aarch64__) |
| 40 | #define __64BIT__ |
| 41 | #endif |
| 42 | |
| 43 | /* detect Linux platform */ |
| 44 | #if defined(linux) || defined(__linux__) || defined(__LINUX__) |
| 45 | # if !defined(__LINUX__) |
| 46 | # define __LINUX__ |
| 47 | # endif |
| 48 | # if !defined(__UNIX__) |
| 49 | # define __UNIX__ |
| 50 | # endif |
| 51 | #endif |
| 52 | |
| 53 | /* detect FreeBSD platform */ |
| 54 | #if defined(__FreeBSD__) || defined(__FREEBSD__) |
| 55 | # if !defined(__FREEBSD__) |
| 56 | # define __FREEBSD__ |
| 57 | # endif |
| 58 | # if !defined(__UNIX__) |
| 59 | # define __UNIX__ |
| 60 | # endif |
| 61 | #endif |
| 62 | |
| 63 | /* detect Windows 95/98/NT/2000/XP/Vista/7/8/10 platform */ |
| 64 | #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)) && !defined(__CYGWIN__) |
| 65 | # if !defined(__WIN32__) |
| 66 | # define __WIN32__ |
| 67 | # endif |
| 68 | #endif |
| 69 | |
| 70 | /* detect Cygwin platform */ |
| 71 | #if defined(__CYGWIN__) |
| 72 | # if !defined(__UNIX__) |
| 73 | # define __UNIX__ |
| 74 | # endif |
| 75 | #endif |
| 76 | |
| 77 | /* detect MAC OS X platform */ |
| 78 | #if defined(__APPLE__) || defined(MACOSX) || defined(__MACOSX__) |
| 79 | # if !defined(__MACOSX__) |
| 80 | # define __MACOSX__ |
| 81 | # endif |
| 82 | # if !defined(__UNIX__) |
| 83 | # define __UNIX__ |
| 84 | # endif |
| 85 | #endif |
| 86 | |
| 87 | /* try to detect other Unix systems */ |
| 88 | #if defined(__unix__) || defined (unix) || defined(__unix) || defined(_unix) |
| 89 | # if !defined(__UNIX__) |
| 90 | # define __UNIX__ |
| 91 | # endif |
| 92 | #endif |
| 93 | |
| 94 | //////////////////////////////////////////////////////////////////////////////// |
| 95 | /// Macros |
| 96 | //////////////////////////////////////////////////////////////////////////////// |
| 97 | |
| 98 | #ifdef __WIN32__ |
| 99 | #define dll_export __declspec(dllexport) |
| 100 | #define dll_import __declspec(dllimport) |
| 101 | #else |
| 102 | #define dll_export __attribute__ ((visibility ("default"))) |
| 103 | #define dll_import |
| 104 | #endif |
| 105 | |
| 106 | #if defined(__WIN32__) && !defined(__MINGW32__) |
| 107 | #if !defined(__noinline) |
| 108 | #define __noinline __declspec(noinline) |
| 109 | #endif |
| 110 | //#define __forceinline __forceinline |
| 111 | //#define __restrict __restrict |
| 112 | #if defined(__INTEL_COMPILER) |
| 113 | #define __restrict__ __restrict |
| 114 | #else |
| 115 | #define __restrict__ //__restrict // causes issues with MSVC |
| 116 | #endif |
| 117 | #if !defined(__thread) |
| 118 | #define __thread __declspec(thread) |
| 119 | #endif |
| 120 | #if !defined(__aligned) |
| 121 | #define __aligned(...) __declspec(align(__VA_ARGS__)) |
| 122 | #endif |
| 123 | //#define __FUNCTION__ __FUNCTION__ |
| 124 | #define debugbreak() __debugbreak() |
| 125 | |
| 126 | #else |
| 127 | #if !defined(__noinline) |
| 128 | #define __noinline __attribute__((noinline)) |
| 129 | #endif |
| 130 | #if !defined(__forceinline) |
| 131 | #define __forceinline inline __attribute__((always_inline)) |
| 132 | #endif |
| 133 | //#define __restrict __restrict |
| 134 | //#define __thread __thread |
| 135 | #if !defined(__aligned) |
| 136 | #define __aligned(...) __attribute__((aligned(__VA_ARGS__))) |
| 137 | #endif |
| 138 | #if !defined(__FUNCTION__) |
| 139 | #define __FUNCTION__ __PRETTY_FUNCTION__ |
| 140 | #endif |
| 141 | #define debugbreak() asm ("int $3") |
| 142 | #endif |
| 143 | |
| 144 | #if defined(__clang__) || defined(__GNUC__) |
| 145 | #define MAYBE_UNUSED __attribute__((unused)) |
| 146 | #else |
| 147 | #define MAYBE_UNUSED |
| 148 | #endif |
| 149 | |
| 150 | #if defined(_MSC_VER) && (_MSC_VER < 1900) // before VS2015 deleted functions are not supported properly |
| 151 | #define DELETED |
| 152 | #else |
| 153 | #define DELETED = delete |
| 154 | #endif |
| 155 | |
| 156 | #if !defined(likely) |
| 157 | #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) |
| 158 | #define likely(expr) (expr) |
| 159 | #define unlikely(expr) (expr) |
| 160 | #else |
| 161 | #define likely(expr) __builtin_expect((bool)(expr),true ) |
| 162 | #define unlikely(expr) __builtin_expect((bool)(expr),false) |
| 163 | #endif |
| 164 | #endif |
| 165 | |
| 166 | //////////////////////////////////////////////////////////////////////////////// |
| 167 | /// Error handling and debugging |
| 168 | //////////////////////////////////////////////////////////////////////////////// |
| 169 | |
| 170 | /* debug printing macros */ |
| 171 | #define STRING(x) #x |
| 172 | #define TOSTRING(x) STRING(x) |
| 173 | #define PING embree_cout << __FILE__ << " (" << __LINE__ << "): " << __FUNCTION__ << embree_endl |
| 174 | #define PRINT(x) embree_cout << STRING(x) << " = " << (x) << embree_endl |
| 175 | #define PRINT2(x,y) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << embree_endl |
| 176 | #define PRINT3(x,y,z) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << embree_endl |
| 177 | #define PRINT4(x,y,z,w) embree_cout << STRING(x) << " = " << (x) << ", " << STRING(y) << " = " << (y) << ", " << STRING(z) << " = " << (z) << ", " << STRING(w) << " = " << (w) << embree_endl |
| 178 | |
| 179 | #if defined(DEBUG) // only report file and line in debug mode |
| 180 | #define THROW_RUNTIME_ERROR(str) \ |
| 181 | throw std::runtime_error(std::string(__FILE__) + " (" + toString(__LINE__) + "): " + std::string(str)); |
| 182 | #else |
| 183 | #define THROW_RUNTIME_ERROR(str) \ |
| 184 | throw std::runtime_error(str); |
| 185 | #endif |
| 186 | |
| 187 | #define FATAL(x) THROW_RUNTIME_ERROR(x) |
| 188 | #define WARNING(x) { std::cerr << "Warning: " << x << embree_endl << std::flush; } |
| 189 | |
| 190 | #define NOT_IMPLEMENTED FATAL(std::string(__FUNCTION__) + " not implemented") |
| 191 | |
| 192 | //////////////////////////////////////////////////////////////////////////////// |
| 193 | /// Basic types |
| 194 | //////////////////////////////////////////////////////////////////////////////// |
| 195 | |
| 196 | /* default floating-point type */ |
| 197 | namespace embree { |
| 198 | typedef float real; |
| 199 | } |
| 200 | |
| 201 | /* windows does not have ssize_t */ |
| 202 | #if defined(__WIN32__) |
| 203 | #if defined(__64BIT__) |
| 204 | typedef int64_t ssize_t; |
| 205 | #else |
| 206 | typedef int32_t ssize_t; |
| 207 | #endif |
| 208 | #endif |
| 209 | |
| 210 | //////////////////////////////////////////////////////////////////////////////// |
| 211 | /// Basic utility functions |
| 212 | //////////////////////////////////////////////////////////////////////////////// |
| 213 | |
| 214 | __forceinline std::string toString(long long value) { |
| 215 | return std::to_string(val: value); |
| 216 | } |
| 217 | |
| 218 | //////////////////////////////////////////////////////////////////////////////// |
| 219 | /// Disable some compiler warnings |
| 220 | //////////////////////////////////////////////////////////////////////////////// |
| 221 | |
| 222 | #if defined(__INTEL_COMPILER) |
| 223 | //#pragma warning(disable:265 ) // floating-point operation result is out of range |
| 224 | //#pragma warning(disable:383 ) // value copied to temporary, reference to temporary used |
| 225 | //#pragma warning(disable:869 ) // parameter was never referenced |
| 226 | //#pragma warning(disable:981 ) // operands are evaluated in unspecified order |
| 227 | //#pragma warning(disable:1418) // external function definition with no prior declaration |
| 228 | //#pragma warning(disable:1419) // external declaration in primary source file |
| 229 | //#pragma warning(disable:1572) // floating-point equality and inequality comparisons are unreliable |
| 230 | //#pragma warning(disable:94 ) // the size of an array must be greater than zero |
| 231 | //#pragma warning(disable:1599) // declaration hides parameter |
| 232 | //#pragma warning(disable:424 ) // extra ";" ignored |
| 233 | #pragma warning(disable:2196) // routine is both "inline" and "noinline" |
| 234 | //#pragma warning(disable:177 ) // label was declared but never referenced |
| 235 | //#pragma warning(disable:114 ) // function was referenced but not defined |
| 236 | //#pragma warning(disable:819 ) // template nesting depth does not match the previous declaration of function |
| 237 | #pragma warning(disable:15335) // was not vectorized: vectorization possible but seems inefficient |
| 238 | #endif |
| 239 | |
| 240 | #if defined(_MSC_VER) |
| 241 | //#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union |
| 242 | #pragma warning(disable:4800) // forcing value to bool 'true' or 'false' (performance warning) |
| 243 | //#pragma warning(disable:4267) // '=' : conversion from 'size_t' to 'unsigned long', possible loss of data |
| 244 | #pragma warning(disable:4244) // 'argument' : conversion from 'ssize_t' to 'unsigned int', possible loss of data |
| 245 | //#pragma warning(disable:4355) // 'this' : used in base member initializer list |
| 246 | //#pragma warning(disable:391 ) // '<=' : signed / unsigned mismatch |
| 247 | //#pragma warning(disable:4018) // '<' : signed / unsigned mismatch |
| 248 | //#pragma warning(disable:4305) // 'initializing' : truncation from 'double' to 'float' |
| 249 | //#pragma warning(disable:4068) // unknown pragma |
| 250 | //#pragma warning(disable:4146) // unary minus operator applied to unsigned type, result still unsigned |
| 251 | //#pragma warning(disable:4838) // conversion from 'unsigned int' to 'const int' requires a narrowing conversion) |
| 252 | //#pragma warning(disable:4227) // anachronism used : qualifiers on reference are ignored |
| 253 | #pragma warning(disable:4503) // decorated name length exceeded, name was truncated |
| 254 | #pragma warning(disable:4180) // qualifier applied to function type has no meaning; ignored |
| 255 | #pragma warning(disable:4258) // definition from the for loop is ignored; the definition from the enclosing scope is used |
| 256 | |
| 257 | # if _MSC_VER < 1910 // prior to Visual studio 2017 (V141) |
| 258 | # pragma warning(disable:4101) // warning C4101: 'x': unreferenced local variable // a compiler bug issues wrong warnings |
| 259 | # pragma warning(disable:4789) // buffer '' of size 8 bytes will be overrun; 32 bytes will be written starting at offset 0 |
| 260 | # endif |
| 261 | |
| 262 | #endif |
| 263 | |
| 264 | #if defined(__clang__) && !defined(__INTEL_COMPILER) |
| 265 | //#pragma clang diagnostic ignored "-Wunknown-pragmas" |
| 266 | //#pragma clang diagnostic ignored "-Wunused-variable" |
| 267 | //#pragma clang diagnostic ignored "-Wreorder" |
| 268 | //#pragma clang diagnostic ignored "-Wmicrosoft" |
| 269 | //#pragma clang diagnostic ignored "-Wunused-private-field" |
| 270 | //#pragma clang diagnostic ignored "-Wunused-local-typedef" |
| 271 | //#pragma clang diagnostic ignored "-Wunused-function" |
| 272 | //#pragma clang diagnostic ignored "-Wnarrowing" |
| 273 | //#pragma clang diagnostic ignored "-Wc++11-narrowing" |
| 274 | //#pragma clang diagnostic ignored "-Wdeprecated-register" |
| 275 | //#pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| 276 | #endif |
| 277 | |
| 278 | #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) |
| 279 | #pragma GCC diagnostic ignored "-Wpragmas" |
| 280 | //#pragma GCC diagnostic ignored "-Wnarrowing" |
| 281 | #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" |
| 282 | //#pragma GCC diagnostic ignored "-Wdeprecated-declarations" |
| 283 | //#pragma GCC diagnostic ignored "-Warray-bounds" |
| 284 | #pragma GCC diagnostic ignored "-Wattributes" |
| 285 | #pragma GCC diagnostic ignored "-Wmisleading-indentation" |
| 286 | #pragma GCC diagnostic ignored "-Wsign-compare" |
| 287 | #pragma GCC diagnostic ignored "-Wparentheses" |
| 288 | #endif |
| 289 | |
| 290 | #if defined(__clang__) && defined(__WIN32__) |
| 291 | #pragma clang diagnostic ignored "-Wunused-parameter" |
| 292 | #pragma clang diagnostic ignored "-Wmicrosoft-cast" |
| 293 | #pragma clang diagnostic ignored "-Wmicrosoft-enum-value" |
| 294 | #pragma clang diagnostic ignored "-Wmicrosoft-include" |
| 295 | #pragma clang diagnostic ignored "-Wunused-function" |
| 296 | #pragma clang diagnostic ignored "-Wunknown-pragmas" |
| 297 | #endif |
| 298 | |
| 299 | /* disabling deprecated warning, please use only where use of deprecated Embree API functions is desired */ |
| 300 | #if defined(__WIN32__) && defined(__INTEL_COMPILER) |
| 301 | #define DISABLE_DEPRECATED_WARNING __pragma(warning (disable: 1478)) // warning: function was declared deprecated |
| 302 | #define ENABLE_DEPRECATED_WARNING __pragma(warning (enable: 1478)) // warning: function was declared deprecated |
| 303 | #elif defined(__INTEL_COMPILER) |
| 304 | #define DISABLE_DEPRECATED_WARNING _Pragma("warning (disable: 1478)") // warning: function was declared deprecated |
| 305 | #define ENABLE_DEPRECATED_WARNING _Pragma("warning (enable : 1478)") // warning: function was declared deprecated |
| 306 | #elif defined(__clang__) |
| 307 | #define DISABLE_DEPRECATED_WARNING _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") // warning: xxx is deprecated |
| 308 | #define ENABLE_DEPRECATED_WARNING _Pragma("clang diagnostic warning \"-Wdeprecated-declarations\"") // warning: xxx is deprecated |
| 309 | #elif defined(__GNUC__) |
| 310 | #define DISABLE_DEPRECATED_WARNING _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") // warning: xxx is deprecated |
| 311 | #define ENABLE_DEPRECATED_WARNING _Pragma("GCC diagnostic warning \"-Wdeprecated-declarations\"") // warning: xxx is deprecated |
| 312 | #elif defined(_MSC_VER) |
| 313 | #define DISABLE_DEPRECATED_WARNING __pragma(warning (disable: 4996)) // warning: function was declared deprecated |
| 314 | #define ENABLE_DEPRECATED_WARNING __pragma(warning (enable : 4996)) // warning: function was declared deprecated |
| 315 | #endif |
| 316 | |
| 317 | /* embree output stream */ |
| 318 | #define embree_ostream std::ostream& |
| 319 | #define embree_cout std::cout |
| 320 | #define embree_cout_uniform std::cout |
| 321 | #define embree_endl std::endl |
| 322 | |
| 323 | //////////////////////////////////////////////////////////////////////////////// |
| 324 | /// Some macros for static profiling |
| 325 | //////////////////////////////////////////////////////////////////////////////// |
| 326 | |
| 327 | #if defined (__GNUC__) |
| 328 | #define IACA_SSC_MARK( MARK_ID ) \ |
| 329 | __asm__ __volatile__ ( \ |
| 330 | "\n\t movl $"#MARK_ID", %%ebx" \ |
| 331 | "\n\t .byte 0x64, 0x67, 0x90" \ |
| 332 | : : : "memory" ); |
| 333 | |
| 334 | #define IACA_UD_BYTES __asm__ __volatile__ ("\n\t .byte 0x0F, 0x0B"); |
| 335 | |
| 336 | #else |
| 337 | #define IACA_UD_BYTES {__asm _emit 0x0F \ |
| 338 | __asm _emit 0x0B} |
| 339 | |
| 340 | #define IACA_SSC_MARK(x) {__asm mov ebx, x\ |
| 341 | __asm _emit 0x64 \ |
| 342 | __asm _emit 0x67 \ |
| 343 | __asm _emit 0x90 } |
| 344 | |
| 345 | #define IACA_VC64_START __writegsbyte(111, 111); |
| 346 | #define IACA_VC64_END __writegsbyte(222, 222); |
| 347 | |
| 348 | #endif |
| 349 | |
| 350 | #define IACA_START {IACA_UD_BYTES \ |
| 351 | IACA_SSC_MARK(111)} |
| 352 | #define IACA_END {IACA_SSC_MARK(222) \ |
| 353 | IACA_UD_BYTES} |
| 354 | |
| 355 | namespace embree |
| 356 | { |
| 357 | template<typename Closure> |
| 358 | struct OnScopeExitHelper |
| 359 | { |
| 360 | OnScopeExitHelper (const Closure f) : active(true), f(f) {} |
| 361 | ~OnScopeExitHelper() { if (active) f(); } |
| 362 | void deactivate() { active = false; } |
| 363 | bool active; |
| 364 | const Closure f; |
| 365 | }; |
| 366 | |
| 367 | template <typename Closure> |
| 368 | OnScopeExitHelper<Closure> OnScopeExit(const Closure f) { |
| 369 | return OnScopeExitHelper<Closure>(f); |
| 370 | } |
| 371 | |
| 372 | #define STRING_JOIN2(arg1, arg2) DO_STRING_JOIN2(arg1, arg2) |
| 373 | #define DO_STRING_JOIN2(arg1, arg2) arg1 ## arg2 |
| 374 | #define ON_SCOPE_EXIT(code) \ |
| 375 | auto STRING_JOIN2(on_scope_exit_, __LINE__) = OnScopeExit([&](){code;}) |
| 376 | |
| 377 | template<typename Ty> |
| 378 | std::unique_ptr<Ty> make_unique(Ty* ptr) { |
| 379 | return std::unique_ptr<Ty>(ptr); |
| 380 | } |
| 381 | |
| 382 | } |
| 383 | |
| 384 | // Qt's bundled build enforces EMBREE_TARGET_SSE2, it must not hit the AVX code paths |
| 385 | #undef __AVX512VL__ |
| 386 | #undef __AVX512F__ |
| 387 | #undef __AVX2__ |
| 388 | #undef __AVXI__ |
| 389 | #undef __AVX__ |
| 390 | #undef __SSE4_2__ |
| 391 | #undef __SSE4_1__ |
| 392 | |