Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / util / util_types.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __UTIL_TYPES_H__
18 #define __UTIL_TYPES_H__
19
20 #ifndef __KERNEL_OPENCL__
21
22 #include <stdlib.h>
23
24 #endif
25
26 /* Bitness */
27
28 #if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
29 #define __KERNEL_64_BIT__
30 #endif
31
32 /* Qualifiers for kernel code shared by CPU and GPU */
33
34 #ifndef __KERNEL_GPU__
35
36 #define ccl_device static inline
37 #define ccl_device_noinline static
38 #define ccl_global
39 #define ccl_constant
40 #define ccl_local
41 #define ccl_local_param
42 #define ccl_private
43 #define ccl_restrict __restrict
44 #define __KERNEL_WITH_SSE_ALIGN__
45
46 #if defined(_WIN32) && !defined(FREE_WINDOWS)
47 #define ccl_device_inline static __forceinline
48 #define ccl_device_forceinline static __forceinline
49 #define ccl_align(...) __declspec(align(__VA_ARGS__))
50 #ifdef __KERNEL_64_BIT__
51 #define ccl_try_align(...) __declspec(align(__VA_ARGS__))
52 #else
53 #undef __KERNEL_WITH_SSE_ALIGN__
54 #define ccl_try_align(...) /* not support for function arguments (error C2719) */
55 #endif
56 #define ccl_may_alias
57 #define ccl_always_inline __forceinline
58 #define ccl_never_inline __declspec(noinline)
59 #define ccl_maybe_unused
60
61 #else
62
63 #define ccl_device_inline static inline __attribute__((always_inline))
64 #define ccl_device_forceinline static inline __attribute__((always_inline))
65 #define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
66 #ifndef FREE_WINDOWS64
67 #define __forceinline inline __attribute__((always_inline))
68 #endif
69 #define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
70 #define ccl_may_alias __attribute__((__may_alias__))
71 #define ccl_always_inline __attribute__((always_inline))
72 #define ccl_never_inline __attribute__((noinline))
73 #define ccl_maybe_unused __attribute__((used))
74
75 #endif
76
77 #endif
78
79 /* Standard Integer Types */
80
81 #ifndef __KERNEL_GPU__
82
83 /* int8_t, uint16_t, and friends */
84 #ifndef _WIN32
85 #include <stdint.h>
86 #endif
87
88 /* SIMD Types */
89
90 #include "util/util_optimization.h"
91
92 #endif
93
94 CCL_NAMESPACE_BEGIN
95
96 /* Types
97  *
98  * Define simpler unsigned type names, and integer with defined number of bits.
99  * Also vector types, named to be compatible with OpenCL builtin types, while
100  * working for CUDA and C++ too. */
101
102 /* Shorter Unsigned Names */
103
104 #ifndef __KERNEL_OPENCL__
105
106 typedef unsigned char uchar;
107 typedef unsigned int uint;
108
109 #endif
110
111 /* Fixed Bits Types */
112
113 #ifdef __KERNEL_OPENCL__
114
115 typedef ulong uint64_t;
116
117 #endif
118
119 #ifndef __KERNEL_GPU__
120
121 #ifdef _WIN32
122
123 typedef signed char int8_t;
124 typedef unsigned char uint8_t;
125
126 typedef signed short int16_t;
127 typedef unsigned short uint16_t;
128
129 typedef signed int int32_t;
130 typedef unsigned int uint32_t;
131
132 typedef long long int64_t;
133 typedef unsigned long long uint64_t;
134
135 #ifdef __KERNEL_64_BIT__
136 typedef int64_t ssize_t;
137 #else
138 typedef int32_t ssize_t;
139 #endif
140
141 #endif
142
143 /* Generic Memory Pointer */
144
145 typedef uint64_t device_ptr;
146
147 /* Vector Types */
148
149 struct uchar2 {
150         uchar x, y;
151
152         __forceinline uchar operator[](int i) const { return *(&x + i); }
153         __forceinline uchar& operator[](int i) { return *(&x + i); }
154 };
155
156 struct uchar3 {
157         uchar x, y, z;
158
159         __forceinline uchar operator[](int i) const { return *(&x + i); }
160         __forceinline uchar& operator[](int i) { return *(&x + i); }
161 };
162
163 struct uchar4 {
164         uchar x, y, z, w;
165
166         __forceinline uchar operator[](int i) const { return *(&x + i); }
167         __forceinline uchar& operator[](int i) { return *(&x + i); }
168 };
169
170 struct int2 {
171         int x, y;
172
173         __forceinline int operator[](int i) const { return *(&x + i); }
174         __forceinline int& operator[](int i) { return *(&x + i); }
175 };
176
177 struct ccl_try_align(16) int3 {
178 #ifdef __KERNEL_SSE__
179         union {
180                 __m128i m128;
181                 struct { int x, y, z, w; };
182         };
183
184         __forceinline int3() {}
185         __forceinline explicit int3(const __m128i& a) : m128(a) {}
186         __forceinline operator const __m128i&(void) const { return m128; }
187         __forceinline operator __m128i&(void) { return m128; }
188
189         int3(const int3& a) { m128 = a.m128; }
190         int3& operator =(const int3& a) { m128 = a.m128; return *this; }
191 #else
192         int x, y, z, w;
193 #endif
194
195         __forceinline int operator[](int i) const { return *(&x + i); }
196         __forceinline int& operator[](int i) { return *(&x + i); }
197 };
198
199 struct ccl_try_align(16) int4 {
200 #ifdef __KERNEL_SSE__
201         union {
202                 __m128i m128;
203                 struct { int x, y, z, w; };
204         };
205
206         __forceinline int4() {}
207         __forceinline explicit int4(const __m128i& a) : m128(a) {}
208         __forceinline operator const __m128i&(void) const { return m128; }
209         __forceinline operator __m128i&(void) { return m128; }
210
211         int4(const int4& a) : m128(a.m128) {}
212         int4& operator=(const int4& a) { m128 = a.m128; return *this; }
213 #else
214         int x, y, z, w;
215 #endif
216
217         __forceinline int operator[](int i) const { return *(&x + i); }
218         __forceinline int& operator[](int i) { return *(&x + i); }
219 };
220
221 struct uint2 {
222         uint x, y;
223
224         __forceinline uint operator[](uint i) const { return *(&x + i); }
225         __forceinline uint& operator[](uint i) { return *(&x + i); }
226 };
227
228 struct uint3 {
229         uint x, y, z;
230
231         __forceinline uint operator[](uint i) const { return *(&x + i); }
232         __forceinline uint& operator[](uint i) { return *(&x + i); }
233 };
234
235 struct uint4 {
236         uint x, y, z, w;
237
238         __forceinline uint operator[](uint i) const { return *(&x + i); }
239         __forceinline uint& operator[](uint i) { return *(&x + i); }
240 };
241
242 struct float2 {
243         float x, y;
244
245         __forceinline float operator[](int i) const { return *(&x + i); }
246         __forceinline float& operator[](int i) { return *(&x + i); }
247 };
248
249 struct ccl_try_align(16) float3 {
250 #ifdef __KERNEL_SSE__
251         union {
252                 __m128 m128;
253                 struct { float x, y, z, w; };
254         };
255
256         __forceinline float3() {}
257         __forceinline explicit float3(const __m128& a) : m128(a) {}
258         __forceinline operator const __m128&(void) const { return m128; }
259         __forceinline operator __m128&(void) { return m128; }
260
261         __forceinline float3(const float3& a) : m128(a.m128) {}
262         __forceinline float3& operator =(const float3& a) { m128 = a.m128; return *this; }
263 #else
264         float x, y, z, w;
265 #endif
266
267         __forceinline float operator[](int i) const { return *(&x + i); }
268         __forceinline float& operator[](int i) { return *(&x + i); }
269 };
270
271 struct ccl_try_align(16) float4 {
272 #ifdef __KERNEL_SSE__
273         union {
274                 __m128 m128;
275                 struct { float x, y, z, w; };
276         };
277
278         __forceinline float4() {}
279         __forceinline explicit float4(const __m128& a) : m128(a) {}
280         __forceinline operator const __m128&(void) const { return m128; }
281         __forceinline operator __m128&(void) { return m128; }
282
283         __forceinline float4(const float4& a) : m128(a.m128) {}
284         __forceinline float4& operator =(const float4& a) { m128 = a.m128; return *this; }
285
286 #else
287         float x, y, z, w;
288 #endif
289
290         __forceinline float operator[](int i) const { return *(&x + i); }
291         __forceinline float& operator[](int i) { return *(&x + i); }
292 };
293
294 template<typename T>
295 class vector3
296 {
297 public:
298         T x, y, z;
299
300         ccl_always_inline vector3() {}
301         ccl_always_inline vector3(const T& a)
302           : x(a), y(a), z(a) {}
303         ccl_always_inline vector3(const T& x, const T& y, const T& z)
304           : x(x), y(y), z(z) {}
305 };
306
307 #endif
308
309 #ifndef __KERNEL_GPU__
310
311 /* Vector Type Constructors
312  * 
313  * OpenCL does not support C++ class, so we use these instead. */
314
315 ccl_device_inline uchar2 make_uchar2(uchar x, uchar y)
316 {
317         uchar2 a = {x, y};
318         return a;
319 }
320
321 ccl_device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z)
322 {
323         uchar3 a = {x, y, z};
324         return a;
325 }
326
327 ccl_device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w)
328 {
329         uchar4 a = {x, y, z, w};
330         return a;
331 }
332
333 ccl_device_inline int2 make_int2(int x, int y)
334 {
335         int2 a = {x, y};
336         return a;
337 }
338
339 ccl_device_inline int3 make_int3(int x, int y, int z)
340 {
341 #ifdef __KERNEL_SSE__
342         int3 a;
343         a.m128 = _mm_set_epi32(0, z, y, x);
344 #else
345         int3 a = {x, y, z, 0};
346 #endif
347
348         return a;
349 }
350
351 ccl_device_inline int4 make_int4(int x, int y, int z, int w)
352 {
353 #ifdef __KERNEL_SSE__
354         int4 a;
355         a.m128 = _mm_set_epi32(w, z, y, x);
356 #else
357         int4 a = {x, y, z, w};
358 #endif
359
360         return a;
361 }
362
363 ccl_device_inline uint2 make_uint2(uint x, uint y)
364 {
365         uint2 a = {x, y};
366         return a;
367 }
368
369 ccl_device_inline uint3 make_uint3(uint x, uint y, uint z)
370 {
371         uint3 a = {x, y, z};
372         return a;
373 }
374
375 ccl_device_inline uint4 make_uint4(uint x, uint y, uint z, uint w)
376 {
377         uint4 a = {x, y, z, w};
378         return a;
379 }
380
381 ccl_device_inline float2 make_float2(float x, float y)
382 {
383         float2 a = {x, y};
384         return a;
385 }
386
387 ccl_device_inline float3 make_float3(float x, float y, float z)
388 {
389 #ifdef __KERNEL_SSE__
390         float3 a;
391         a.m128 = _mm_set_ps(0.0f, z, y, x);
392 #else
393         float3 a = {x, y, z, 0.0f};
394 #endif
395
396         return a;
397 }
398
399 ccl_device_inline float4 make_float4(float x, float y, float z, float w)
400 {
401 #ifdef __KERNEL_SSE__
402         float4 a;
403         a.m128 = _mm_set_ps(w, z, y, x);
404 #else
405         float4 a = {x, y, z, w};
406 #endif
407
408         return a;
409 }
410
411 ccl_device_inline int3 make_int3(int i)
412 {
413 #ifdef __KERNEL_SSE__
414         int3 a;
415         a.m128 = _mm_set1_epi32(i);
416 #else
417         int3 a = {i, i, i, i};
418 #endif
419
420         return a;
421 }
422
423 ccl_device_inline int4 make_int4(int i)
424 {
425 #ifdef __KERNEL_SSE__
426         int4 a;
427         a.m128 = _mm_set1_epi32(i);
428 #else
429         int4 a = {i, i, i, i};
430 #endif
431
432         return a;
433 }
434
435 ccl_device_inline float3 make_float3(float f)
436 {
437 #ifdef __KERNEL_SSE__
438         float3 a;
439         a.m128 = _mm_set1_ps(f);
440 #else
441         float3 a = {f, f, f, f};
442 #endif
443
444         return a;
445 }
446
447 ccl_device_inline float4 make_float4(float f)
448 {
449 #ifdef __KERNEL_SSE__
450         float4 a;
451         a.m128 = _mm_set1_ps(f);
452 #else
453         float4 a = {f, f, f, f};
454 #endif
455
456         return a;
457 }
458
459 ccl_device_inline float4 make_float4(const int4& i)
460 {
461 #ifdef __KERNEL_SSE__
462         float4 a;
463         a.m128 = _mm_cvtepi32_ps(i.m128);
464 #else
465         float4 a = {(float)i.x, (float)i.y, (float)i.z, (float)i.w};
466 #endif
467
468         return a;
469 }
470
471 ccl_device_inline int4 make_int4(const float3& f)
472 {
473 #ifdef __KERNEL_SSE__
474         int4 a;
475         a.m128 = _mm_cvtps_epi32(f.m128);
476 #else
477         int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w};
478 #endif
479
480         return a;
481 }
482
483 #endif
484
485 ccl_device_inline size_t align_up(size_t offset, size_t alignment)
486 {
487         return (offset + alignment - 1) & ~(alignment - 1);
488 }
489
490 ccl_device_inline size_t round_up(size_t x, size_t multiple)
491 {
492         return ((x + multiple - 1) / multiple) * multiple;
493 }
494
495 ccl_device_inline size_t round_down(size_t x, size_t multiple)
496 {
497         return (x / multiple) * multiple;
498 }
499
500 /* Interpolation types for textures
501  * cuda also use texture space to store other objects */
502 enum InterpolationType {
503         INTERPOLATION_NONE = -1,
504         INTERPOLATION_LINEAR = 0,
505         INTERPOLATION_CLOSEST = 1,
506         INTERPOLATION_CUBIC = 2,
507         INTERPOLATION_SMART = 3,
508
509         INTERPOLATION_NUM_TYPES,
510 };
511
512 /* Extension types for textures.
513  *
514  * Defines how the image is extrapolated past its original bounds.
515  */
516 enum ExtensionType {
517         /* Cause the image to repeat horizontally and vertically. */
518         EXTENSION_REPEAT = 0,
519         /* Extend by repeating edge pixels of the image. */
520         EXTENSION_EXTEND = 1,
521         /* Clip to image size and set exterior pixels as transparent. */
522         EXTENSION_CLIP = 2,
523
524         EXTENSION_NUM_TYPES,
525 };
526
527 /* macros */
528
529 /* hints for branch prediction, only use in code that runs a _lot_ */
530 #if defined(__GNUC__) && defined(__KERNEL_CPU__)
531 #  define LIKELY(x)       __builtin_expect(!!(x), 1)
532 #  define UNLIKELY(x)     __builtin_expect(!!(x), 0)
533 #else
534 #  define LIKELY(x)       (x)
535 #  define UNLIKELY(x)     (x)
536 #endif
537
538 #if defined(__cplusplus) && ((__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800))
539 #  define HAS_CPP11_FEATURES
540 #endif
541
542 #if defined(__GNUC__) || defined(__clang__)
543 #  if defined(HAS_CPP11_FEATURES)
544 /* Some magic to be sure we don't have reference in the type. */
545 template<typename T> static inline T decltype_helper(T x) { return x; }
546 #    define TYPEOF(x) decltype(decltype_helper(x))
547 #  else
548 #    define TYPEOF(x) typeof(x)
549 #  endif
550 #endif
551
552 /* Causes warning:
553  * incompatible types when assigning to type 'Foo' from type 'Bar'
554  * ... the compiler optimizes away the temp var */
555 #ifdef __GNUC__
556 #define CHECK_TYPE(var, type)  {  \
557         TYPEOF(var) *__tmp;         \
558         __tmp = (type *)NULL;         \
559         (void)__tmp;                  \
560 } (void)0
561
562 #define CHECK_TYPE_PAIR(var_a, var_b)  {  \
563         TYPEOF(var_a) *__tmp;                 \
564         __tmp = (typeof(var_b) *)NULL;        \
565         (void)__tmp;                          \
566 } (void)0
567 #else
568 #  define CHECK_TYPE(var, type)
569 #  define CHECK_TYPE_PAIR(var_a, var_b)
570 #endif
571
572 /* can be used in simple macros */
573 #define CHECK_TYPE_INLINE(val, type) \
574         ((void)(((type)0) != (val)))
575
576
577 CCL_NAMESPACE_END
578
579 #endif /* __UTIL_TYPES_H__ */
580