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 | |