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