1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2013 Academy of Motion Picture Arts and Sciences
3 // ("A.M.P.A.S."). Portions contributed by others as indicated.
4 // All rights reserved.
5 //
6 // A worldwide, royalty-free, non-exclusive right to copy, modify, create
7 // derivatives, and use, in source and binary forms, is hereby granted,
8 // subject to acceptance of this license. Performance of any of the
9 // aforementioned acts indicates acceptance to be bound by the following
10 // terms and conditions:
11 //
12 // * Copies of source code, in whole or in part, must retain the
13 // above copyright notice, this list of conditions and the
14 // Disclaimer of Warranty.
15 //
16 // * Use in binary form must retain the above copyright notice,
17 // this list of conditions and the Disclaimer of Warranty in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // * Nothing in this license shall be deemed to grant any rights to
21 // trademarks, copyrights, patents, trade secrets or any other
22 // intellectual property of A.M.P.A.S. or any contributors, except
23 // as expressly stated herein.
24 //
25 // * Neither the name "A.M.P.A.S." nor the name of any other
26 // contributors to this software may be used to endorse or promote
27 // products derivative of or based on this software without express
28 // prior written permission of A.M.P.A.S. or the contributors, as
29 // appropriate.
30 //
31 // This license shall be construed pursuant to the laws of the State of
32 // California, and any disputes related thereto shall be subject to the
33 // jurisdiction of the courts therein.
34 //
35 // Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND
36 // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
37 // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
38 // FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO
39 // EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE
40 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY,
41 // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
46 // THE POSSIBILITY OF SUCH DAMAGE.
47 //
48 // WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY
49 // SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER
50 // RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY
51 // COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER
52 // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED.
53 ///////////////////////////////////////////////////////////////////////////
54
55 #ifndef INCLUDED_CTL_SIMD_STD_LIB_TEMPLATES_H
56 #define INCLUDED_CTL_SIMD_STD_LIB_TEMPLATES_H
57
58 //-----------------------------------------------------------------------------
59 //
60 // Templates an macros that are useful for the implementation of the
61 // Standard Library of C++ functions that can be called from CTL.
62 //
63 //-----------------------------------------------------------------------------
64
65 #include <CtlSimdStdTypes.h>
66 #include <CtlSimdCFunc.h>
67 #include <CtlSimdReg.h>
68 #include <CtlSimdXContext.h>
69
70 namespace Ctl {
71
72 //
73 // Templated functions with one, two or more arguments that can be called
74 // from CTL. The functions will operate on uniform or varying data. The
75 // actual operation performed depends on the Func template parameter.
76 //
77
78 template <class Func>
79 void
simdFunc1Arg(const SimdBoolMask & mask,SimdXContext & xcontext)80 simdFunc1Arg (const SimdBoolMask &mask, SimdXContext &xcontext)
81 {
82 const SimdReg &a1 = xcontext.stack().regFpRelative(-1);
83 SimdReg &returnValue = xcontext.stack().regFpRelative (-2);
84
85 if (a1.isVarying())
86 {
87 if (!mask.isVarying() &&
88 !a1.isReference() &&
89 !returnValue.isReference())
90 {
91 //
92 // Mask is uniform and a1 and the return value
93 // are contiguous in memory.
94 //
95
96 returnValue.setVaryingDiscardData (true);
97
98 const typename Func::Arg1T *a1Ptr =
99 (typename Func::Arg1T *)(a1[0]);
100
101 typename Func::ReturnT *returnPtr =
102 (typename Func::ReturnT *)(returnValue[0]);
103
104 typename Func::ReturnT *returnEnd =
105 returnPtr + xcontext.regSize();
106
107 while (returnPtr < returnEnd)
108 *(returnPtr++) = Func::call (*(a1Ptr++));
109 }
110 else
111 {
112 //
113 // Mask is varying, or a1 or the return value
114 // may not be contiguous in memory.
115 //
116
117 returnValue.setVarying (true);
118
119 for (int i = xcontext.regSize(); --i >= 0;)
120 if (mask[i])
121 *(typename Func::ReturnT *)(returnValue[i]) =
122 Func::call (*(typename Func::Arg1T *)(a1[i]));
123 }
124 }
125 else
126 {
127 returnValue.setVarying (false);
128
129 *(typename Func::ReturnT *)(returnValue[0]) =
130 Func::call (*(typename Func::Arg1T *)(a1[0]));
131 }
132 }
133
134
135 template <class Func>
136 void
simdFunc2Arg(const SimdBoolMask & mask,SimdXContext & xcontext)137 simdFunc2Arg (const SimdBoolMask &mask, SimdXContext &xcontext)
138 {
139 const SimdReg &a1 = xcontext.stack().regFpRelative (-1);
140 const SimdReg &a2 = xcontext.stack().regFpRelative (-2);
141 SimdReg &returnValue = xcontext.stack().regFpRelative (-3);
142
143 if (a1.isVarying() || a2.isVarying())
144 {
145 if (!mask.isVarying() &&
146 !a1.isReference() &&
147 !a2.isReference() &&
148 !returnValue.isReference())
149 {
150 //
151 // Mask is uniform and a1, a2 and the return value are
152 // contiguous in memory. A1, a2 or both are varying.
153 //
154
155 returnValue.setVaryingDiscardData (true);
156
157 const typename Func::Arg1T *a1Ptr =
158 (typename Func::Arg1T *)(a1[0]);
159
160 const typename Func::Arg2T *a2Ptr =
161 (typename Func::Arg2T *)(a2[0]);
162
163 typename Func::ReturnT *returnPtr =
164 (typename Func::ReturnT *)(returnValue[0]);
165
166 typename Func::ReturnT *returnEnd =
167 returnPtr + xcontext.regSize();
168
169 if (a1.isVarying() && a2.isVarying())
170 {
171 while (returnPtr < returnEnd)
172 *(returnPtr++) = Func::call (*(a1Ptr++), *(a2Ptr++));
173 }
174 else if (a1.isVarying())
175 {
176 while (returnPtr < returnEnd)
177 *(returnPtr++) = Func::call (*(a1Ptr++), *(a2Ptr));
178 }
179 else
180 {
181 while (returnPtr < returnEnd)
182 *(returnPtr++) = Func::call (*(a1Ptr), *(a2Ptr++));
183 }
184 }
185 else
186 {
187 //
188 // Mask is varying, or a1, a2 or the return value
189 // may not be contiguous in memory.
190 //
191
192 returnValue.setVarying (true);
193
194 for (int i = xcontext.regSize(); --i >= 0;)
195 if (mask[i])
196 *(typename Func::ReturnT *)(returnValue[i]) =
197 Func::call (*(typename Func::Arg1T *)(a1[i]),
198 *(typename Func::Arg2T *)(a2[i]));
199 }
200 }
201 else
202 {
203 returnValue.setVarying (false);
204
205 *(typename Func::ReturnT *)(returnValue[0]) =
206 Func::call (*(typename Func::Arg1T *)(a1[0]),
207 *(typename Func::Arg2T *)(a2[0]));
208 }
209 }
210
211
212 //
213 // Function objects that can be passed to the templates above.
214 //
215
216 #define DEFINE_SIMD_FUNC_1_ARG(className, op, rT, a1T) \
217 \
218 struct className \
219 { \
220 typedef rT ReturnT; \
221 typedef a1T Arg1T; \
222 \
223 static ReturnT \
224 call (const Arg1T &a1) \
225 { \
226 return op; \
227 } \
228 };
229
230
231 #define DEFINE_SIMD_FUNC_2_ARG(className, op, rT, a1T, a2T) \
232 \
233 struct className \
234 { \
235 typedef rT ReturnT; \
236 typedef a1T Arg1T; \
237 typedef a2T Arg2T; \
238 \
239 static ReturnT \
240 call (const Arg1T &a1, \
241 const Arg2T &a2) \
242 { \
243 return op; \
244 } \
245 };
246
247
248 } // namespace Ctl
249
250 #endif
251