865549be2833ef94ded5b8dfd1ef8e63e2865f27
[blender.git] / intern / cycles / util / util_avxb.h
1 /*
2  * Copyright 2011-2013 Intel Corporation
3  * Modifications Copyright 2014, Blender Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0(the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #ifndef __UTIL_AVXB_H__
19 #define __UTIL_AVXB_H__
20
21 CCL_NAMESPACE_BEGIN
22
23 struct avxf;
24
25 /*! 4-wide SSE bool type. */
26 struct avxb
27 {
28         typedef avxb Mask;                    // mask type
29         typedef avxf Float;                   // float type
30
31         enum   { size = 8 };                  // number of SIMD elements
32         union  { __m256 m256; int32_t v[8]; };  // data
33
34         ////////////////////////////////////////////////////////////////////////////////
35         /// Constructors, Assignment & Cast Operators
36         ////////////////////////////////////////////////////////////////////////////////
37         
38         __forceinline avxb           ( ) {}
39         __forceinline avxb           ( const avxb& other ) { m256 = other.m256; }
40         __forceinline avxb& operator=( const avxb& other ) { m256 = other.m256; return *this; }
41
42         __forceinline avxb( const __m256  input ) : m256(input) {}
43         __forceinline operator const __m256&( void ) const { return m256; }
44         __forceinline operator const __m256i( void ) const { return _mm256_castps_si256(m256); }
45         __forceinline operator const __m256d( void ) const { return _mm256_castps_pd(m256); }
46         
47         //__forceinline avxb           ( bool  a )
48         //      : m256(_mm_lookupmask_ps[(size_t(a) << 3) | (size_t(a) << 2) | (size_t(a) << 1) | size_t(a)]) {}
49         //__forceinline avxb           ( bool  a, bool  b) 
50         //      : m256(_mm_lookupmask_ps[(size_t(b) << 3) | (size_t(a) << 2) | (size_t(b) << 1) | size_t(a)]) {}
51         //__forceinline avxb           ( bool  a, bool  b, bool  c, bool  d)
52         //      : m256(_mm_lookupmask_ps[(size_t(d) << 3) | (size_t(c) << 2) | (size_t(b) << 1) | size_t(a)]) {}
53         //__forceinline avxb(int mask) {
54         //      assert(mask >= 0 && mask < 16);
55         //      m128 = _mm_lookupmask_ps[mask];
56         //}
57
58         ////////////////////////////////////////////////////////////////////////////////
59         /// Constants
60         ////////////////////////////////////////////////////////////////////////////////
61
62         __forceinline avxb( FalseTy ) : m256(_mm256_setzero_ps()) {}
63         __forceinline avxb( TrueTy  ) : m256(_mm256_castsi256_ps(_mm256_cmpeq_epi32(_mm256_setzero_si256(), _mm256_setzero_si256()))) {}
64
65         ////////////////////////////////////////////////////////////////////////////////
66         /// Array Access
67         ////////////////////////////////////////////////////////////////////////////////
68
69         __forceinline bool   operator []( const size_t i ) const { assert(i < 8); return (_mm256_movemask_ps(m256) >> i) & 1; }
70         __forceinline int32_t& operator []( const size_t i )       { assert(i < 8); return v[i]; }
71 };
72
73 ////////////////////////////////////////////////////////////////////////////////
74 /// Unary Operators
75 ////////////////////////////////////////////////////////////////////////////////
76
77 __forceinline const avxb operator !( const avxb& a ) { return _mm256_xor_ps(a, avxb(True)); }
78
79 ////////////////////////////////////////////////////////////////////////////////
80 /// Binary Operators
81 ////////////////////////////////////////////////////////////////////////////////
82
83 __forceinline const avxb operator &( const avxb& a, const avxb& b ) { return _mm256_and_ps(a, b); }
84 __forceinline const avxb operator |( const avxb& a, const avxb& b ) { return _mm256_or_ps (a, b); }
85 __forceinline const avxb operator ^( const avxb& a, const avxb& b ) { return _mm256_xor_ps(a, b); }
86
87 ////////////////////////////////////////////////////////////////////////////////
88 /// Assignment Operators
89 ////////////////////////////////////////////////////////////////////////////////
90
91 __forceinline const avxb operator &=( avxb& a, const avxb& b ) { return a = a & b; }
92 __forceinline const avxb operator |=( avxb& a, const avxb& b ) { return a = a | b; }
93 __forceinline const avxb operator ^=( avxb& a, const avxb& b ) { return a = a ^ b; }
94
95 ////////////////////////////////////////////////////////////////////////////////
96 /// Comparison Operators + Select
97 ////////////////////////////////////////////////////////////////////////////////
98
99 __forceinline const avxb operator !=( const avxb& a, const avxb& b ) { return _mm256_xor_ps(a, b); }
100 __forceinline const avxb operator ==( const avxb& a, const avxb& b ) { return _mm256_castsi256_ps(_mm256_cmpeq_epi32(a, b)); }
101
102 __forceinline const avxb select( const avxb& m, const avxb& t, const avxb& f ) {
103 #if defined(__KERNEL_SSE41__)
104         return _mm256_blendv_ps(f, t, m); 
105 #else
106         return _mm256_or_ps(_mm256_and_ps(m, t), _mm256_andnot_ps(m, f)); 
107 #endif
108 }
109
110 ////////////////////////////////////////////////////////////////////////////////
111 /// Movement/Shifting/Shuffling Functions
112 ////////////////////////////////////////////////////////////////////////////////
113
114 __forceinline const avxb unpacklo( const avxb& a, const avxb& b ) { return _mm256_unpacklo_ps(a, b); }
115 __forceinline const avxb unpackhi( const avxb& a, const avxb& b ) { return _mm256_unpackhi_ps(a, b); }
116
117 #define _MM256_SHUFFLE(fp7,fp6,fp5,fp4,fp3,fp2,fp1,fp0) (((fp7) << 14) | ((fp6) << 12) | ((fp5) << 10) | ((fp4) << 8) | \
118                                                       ((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | ((fp0)))
119
120 template<size_t i0, size_t i1, size_t i2, size_t i3, size_t i4, size_t i5, size_t i6, size_t i7>
121 __forceinline const avxb shuffle( const avxb& a ) {
122         return _mm256_cvtepi32_ps(_mm256_shuffle_epi32(a, _MM256_SHUFFLE(i7, i6, i5, i4, i3, i2, i1, i0)));
123 }
124
125 /*
126 template<> __forceinline const avxb shuffle<0, 1, 0, 1, 0, 1, 0, 1>( const avxb& a ) {
127         return _mm_movelh_ps(a, a);
128 }
129
130 template<> __forceinline const sseb shuffle<2, 3, 2, 3>( const sseb& a ) {
131         return _mm_movehl_ps(a, a);
132 }
133
134 template<size_t i0, size_t i1, size_t i2, size_t i3> __forceinline const sseb shuffle( const sseb& a, const sseb& b ) {
135         return _mm_shuffle_ps(a, b, _MM_SHUFFLE(i3, i2, i1, i0));
136 }
137
138 template<> __forceinline const sseb shuffle<0, 1, 0, 1>( const sseb& a, const sseb& b ) {
139         return _mm_movelh_ps(a, b);
140 }
141
142 template<> __forceinline const sseb shuffle<2, 3, 2, 3>( const sseb& a, const sseb& b ) {
143         return _mm_movehl_ps(b, a);
144 }
145
146 #if defined(__KERNEL_SSE3__)
147 template<> __forceinline const sseb shuffle<0, 0, 2, 2>( const sseb& a ) { return _mm_moveldup_ps(a); }
148 template<> __forceinline const sseb shuffle<1, 1, 3, 3>( const sseb& a ) { return _mm_movehdup_ps(a); }
149 #endif
150
151 #if defined(__KERNEL_SSE41__)
152 template<size_t dst, size_t src, size_t clr> __forceinline const sseb insert( const sseb& a, const sseb& b ) { return _mm_insert_ps(a, b, (dst << 4) | (src << 6) | clr); }
153 template<size_t dst, size_t src> __forceinline const sseb insert( const sseb& a, const sseb& b ) { return insert<dst, src, 0>(a, b); }
154 template<size_t dst>             __forceinline const sseb insert( const sseb& a, const bool b ) { return insert<dst,0>(a, sseb(b)); }
155 #endif
156 */
157
158 ////////////////////////////////////////////////////////////////////////////////
159 /// Reduction Operations
160 ////////////////////////////////////////////////////////////////////////////////
161
162 #if defined(__KERNEL_SSE41__)
163 __forceinline size_t popcnt( const avxb& a ) { return __popcnt(_mm256_movemask_ps(a)); }
164 #else
165 __forceinline size_t popcnt( const avxb& a ) { return bool(a[0])+bool(a[1])+bool(a[2])+bool(a[3])+bool(a[4])+
166                                                       bool(a[5])+bool(a[6])+bool(a[7]); }
167 #endif
168
169 __forceinline bool reduce_and( const avxb& a ) { return _mm256_movemask_ps(a) == 0xf; }
170 __forceinline bool reduce_or ( const avxb& a ) { return _mm256_movemask_ps(a) != 0x0; }
171 __forceinline bool all       ( const avxb& b ) { return _mm256_movemask_ps(b) == 0xf; }
172 __forceinline bool any       ( const avxb& b ) { return _mm256_movemask_ps(b) != 0x0; }
173 __forceinline bool none      ( const avxb& b ) { return _mm256_movemask_ps(b) == 0x0; }
174
175 __forceinline size_t movemask( const avxb& a ) { return _mm256_movemask_ps(a); }
176
177 ////////////////////////////////////////////////////////////////////////////////
178 /// Debug Functions
179 ////////////////////////////////////////////////////////////////////////////////
180
181 ccl_device_inline void print_avxb(const char *label, const avxb &a)
182 {
183         printf("%s: %df %df %df %df %df %df %df %d\n",
184                label, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
185 }
186
187 #endif
188
189 CCL_NAMESPACE_END
190
191 //#endif
192