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