Line data Source code
1 : //
2 : // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
3 : // Use of this source code is governed by a BSD-style license that can be
4 : // found in the LICENSE file.
5 : //
6 :
7 : #include "angle_gl.h"
8 : #include "compiler/translator/BuiltInFunctionEmulator.h"
9 : #include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
10 : #include "compiler/translator/SymbolTable.h"
11 : #include "compiler/translator/VersionGLSL.h"
12 :
13 : namespace sh
14 : {
15 :
16 0 : void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
17 : int targetGLSLVersion)
18 : {
19 0 : if (targetGLSLVersion < GLSL_VERSION_130)
20 0 : return;
21 :
22 0 : TType *float1 = new TType(EbtFloat);
23 0 : TType *float2 = new TType(EbtFloat, 2);
24 0 : TType *float3 = new TType(EbtFloat, 3);
25 0 : TType *float4 = new TType(EbtFloat, 4);
26 :
27 : emu->addEmulatedFunction(EOpIsNan, float1,
28 : "bool webgl_isnan_emu(float x)\n"
29 : "{\n"
30 : " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
31 : "}\n"
32 0 : "\n");
33 :
34 : emu->addEmulatedFunction(EOpIsNan, float2,
35 : "bool2 webgl_isnan_emu(float2 x)\n"
36 : "{\n"
37 : " bool2 isnan;\n"
38 : " for (int i = 0; i < 2; i++)\n"
39 : " {\n"
40 : " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
41 : " }\n"
42 : " return isnan;\n"
43 0 : "}\n");
44 :
45 : emu->addEmulatedFunction(EOpIsNan, float3,
46 : "bool3 webgl_isnan_emu(float3 x)\n"
47 : "{\n"
48 : " bool3 isnan;\n"
49 : " for (int i = 0; i < 3; i++)\n"
50 : " {\n"
51 : " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
52 : " }\n"
53 : " return isnan;\n"
54 0 : "}\n");
55 :
56 : emu->addEmulatedFunction(EOpIsNan, float4,
57 : "bool4 webgl_isnan_emu(float4 x)\n"
58 : "{\n"
59 : " bool4 isnan;\n"
60 : " for (int i = 0; i < 4; i++)\n"
61 : " {\n"
62 : " isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
63 : " }\n"
64 : " return isnan;\n"
65 0 : "}\n");
66 : }
67 :
68 0 : void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
69 : {
70 0 : TType *float1 = new TType(EbtFloat);
71 0 : TType *float2 = new TType(EbtFloat, 2);
72 0 : TType *float3 = new TType(EbtFloat, 3);
73 0 : TType *float4 = new TType(EbtFloat, 4);
74 :
75 : emu->addEmulatedFunction(EOpMod, float1, float1,
76 : "float webgl_mod_emu(float x, float y)\n"
77 : "{\n"
78 : " return x - y * floor(x / y);\n"
79 : "}\n"
80 0 : "\n");
81 : emu->addEmulatedFunction(EOpMod, float2, float2,
82 : "float2 webgl_mod_emu(float2 x, float2 y)\n"
83 : "{\n"
84 : " return x - y * floor(x / y);\n"
85 : "}\n"
86 0 : "\n");
87 : emu->addEmulatedFunction(EOpMod, float2, float1,
88 : "float2 webgl_mod_emu(float2 x, float y)\n"
89 : "{\n"
90 : " return x - y * floor(x / y);\n"
91 : "}\n"
92 0 : "\n");
93 : emu->addEmulatedFunction(EOpMod, float3, float3,
94 : "float3 webgl_mod_emu(float3 x, float3 y)\n"
95 : "{\n"
96 : " return x - y * floor(x / y);\n"
97 : "}\n"
98 0 : "\n");
99 : emu->addEmulatedFunction(EOpMod, float3, float1,
100 : "float3 webgl_mod_emu(float3 x, float y)\n"
101 : "{\n"
102 : " return x - y * floor(x / y);\n"
103 : "}\n"
104 0 : "\n");
105 : emu->addEmulatedFunction(EOpMod, float4, float4,
106 : "float4 webgl_mod_emu(float4 x, float4 y)\n"
107 : "{\n"
108 : " return x - y * floor(x / y);\n"
109 : "}\n"
110 0 : "\n");
111 : emu->addEmulatedFunction(EOpMod, float4, float1,
112 : "float4 webgl_mod_emu(float4 x, float y)\n"
113 : "{\n"
114 : " return x - y * floor(x / y);\n"
115 : "}\n"
116 0 : "\n");
117 :
118 : emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1,
119 : "float webgl_faceforward_emu(float N, float I, float Nref)\n"
120 : "{\n"
121 : " if(dot(Nref, I) >= 0)\n"
122 : " {\n"
123 : " return -N;\n"
124 : " }\n"
125 : " else\n"
126 : " {\n"
127 : " return N;\n"
128 : " }\n"
129 : "}\n"
130 0 : "\n");
131 : emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2,
132 : "float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n"
133 : "{\n"
134 : " if(dot(Nref, I) >= 0)\n"
135 : " {\n"
136 : " return -N;\n"
137 : " }\n"
138 : " else\n"
139 : " {\n"
140 : " return N;\n"
141 : " }\n"
142 : "}\n"
143 0 : "\n");
144 : emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3,
145 : "float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n"
146 : "{\n"
147 : " if(dot(Nref, I) >= 0)\n"
148 : " {\n"
149 : " return -N;\n"
150 : " }\n"
151 : " else\n"
152 : " {\n"
153 : " return N;\n"
154 : " }\n"
155 : "}\n"
156 0 : "\n");
157 : emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4,
158 : "float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n"
159 : "{\n"
160 : " if(dot(Nref, I) >= 0)\n"
161 : " {\n"
162 : " return -N;\n"
163 : " }\n"
164 : " else\n"
165 : " {\n"
166 : " return N;\n"
167 : " }\n"
168 : "}\n"
169 0 : "\n");
170 :
171 : emu->addEmulatedFunction(EOpAtan, float1, float1,
172 : "float webgl_atan_emu(float y, float x)\n"
173 : "{\n"
174 : " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
175 : " return atan2(y, x);\n"
176 0 : "}\n");
177 : emu->addEmulatedFunction(EOpAtan, float2, float2,
178 : "float2 webgl_atan_emu(float2 y, float2 x)\n"
179 : "{\n"
180 : " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
181 : " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
182 : " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
183 0 : "}\n");
184 : emu->addEmulatedFunction(EOpAtan, float3, float3,
185 : "float3 webgl_atan_emu(float3 y, float3 x)\n"
186 : "{\n"
187 : " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
188 : " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
189 : " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
190 : " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
191 0 : "}\n");
192 : emu->addEmulatedFunction(EOpAtan, float4, float4,
193 : "float4 webgl_atan_emu(float4 y, float4 x)\n"
194 : "{\n"
195 : " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
196 : " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
197 : " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
198 : " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
199 : " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
200 0 : "}\n");
201 :
202 : emu->addEmulatedFunction(EOpAsinh, float1,
203 : "float webgl_asinh_emu(in float x) {\n"
204 : " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
205 0 : "}\n");
206 : emu->addEmulatedFunction(EOpAsinh, float2,
207 : "float2 webgl_asinh_emu(in float2 x) {\n"
208 : " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
209 0 : "}\n");
210 : emu->addEmulatedFunction(EOpAsinh, float3,
211 : "float3 webgl_asinh_emu(in float3 x) {\n"
212 : " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
213 0 : "}\n");
214 : emu->addEmulatedFunction(EOpAsinh, float4,
215 : "float4 webgl_asinh_emu(in float4 x) {\n"
216 : " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
217 0 : "}\n");
218 :
219 : emu->addEmulatedFunction(EOpAcosh, float1,
220 : "float webgl_acosh_emu(in float x) {\n"
221 : " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
222 0 : "}\n");
223 : emu->addEmulatedFunction(EOpAcosh, float2,
224 : "float2 webgl_acosh_emu(in float2 x) {\n"
225 : " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
226 0 : "}\n");
227 : emu->addEmulatedFunction(EOpAcosh, float3,
228 : "float3 webgl_acosh_emu(in float3 x) {\n"
229 : " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
230 0 : "}\n");
231 : emu->addEmulatedFunction(EOpAcosh, float4,
232 : "float4 webgl_acosh_emu(in float4 x) {\n"
233 : " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
234 0 : "}\n");
235 :
236 : emu->addEmulatedFunction(EOpAtanh, float1,
237 : "float webgl_atanh_emu(in float x) {\n"
238 : " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
239 0 : "}\n");
240 : emu->addEmulatedFunction(EOpAtanh, float2,
241 : "float2 webgl_atanh_emu(in float2 x) {\n"
242 : " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
243 0 : "}\n");
244 : emu->addEmulatedFunction(EOpAtanh, float3,
245 : "float3 webgl_atanh_emu(in float3 x) {\n"
246 : " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
247 0 : "}\n");
248 : emu->addEmulatedFunction(EOpAtanh, float4,
249 : "float4 webgl_atanh_emu(in float4 x) {\n"
250 : " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
251 0 : "}\n");
252 :
253 : emu->addEmulatedFunction(EOpRoundEven, float1,
254 : "float webgl_roundEven_emu(in float x) {\n"
255 : " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
256 0 : "}\n");
257 : emu->addEmulatedFunction(EOpRoundEven, float2,
258 : "float2 webgl_roundEven_emu(in float2 x) {\n"
259 : " float2 v;\n"
260 : " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
261 : " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
262 : " return v;\n"
263 0 : "}\n");
264 : emu->addEmulatedFunction(EOpRoundEven, float3,
265 : "float3 webgl_roundEven_emu(in float3 x) {\n"
266 : " float3 v;\n"
267 : " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
268 : " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
269 : " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
270 : " return v;\n"
271 0 : "}\n");
272 : emu->addEmulatedFunction(EOpRoundEven, float4,
273 : "float4 webgl_roundEven_emu(in float4 x) {\n"
274 : " float4 v;\n"
275 : " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
276 : " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
277 : " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
278 : " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
279 : " return v;\n"
280 0 : "}\n");
281 :
282 : emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
283 : "int webgl_toSnorm(in float x) {\n"
284 : " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
285 : "}\n"
286 : "\n"
287 : "uint webgl_packSnorm2x16_emu(in float2 v) {\n"
288 : " int x = webgl_toSnorm(v.x);\n"
289 : " int y = webgl_toSnorm(v.y);\n"
290 : " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
291 0 : "}\n");
292 : emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
293 : "uint webgl_toUnorm(in float x) {\n"
294 : " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
295 : "}\n"
296 : "\n"
297 : "uint webgl_packUnorm2x16_emu(in float2 v) {\n"
298 : " uint x = webgl_toUnorm(v.x);\n"
299 : " uint y = webgl_toUnorm(v.y);\n"
300 : " return (y << 16) | x;\n"
301 0 : "}\n");
302 : emu->addEmulatedFunction(EOpPackHalf2x16, float2,
303 : "uint webgl_packHalf2x16_emu(in float2 v) {\n"
304 : " uint x = f32tof16(v.x);\n"
305 : " uint y = f32tof16(v.y);\n"
306 : " return (y << 16) | x;\n"
307 0 : "}\n");
308 :
309 0 : TType *uint1 = new TType(EbtUInt);
310 :
311 : emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
312 : "float webgl_fromSnorm(in uint x) {\n"
313 : " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
314 : " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
315 : "}\n"
316 : "\n"
317 : "float2 webgl_unpackSnorm2x16_emu(in uint u) {\n"
318 : " uint y = (u >> 16);\n"
319 : " uint x = u;\n"
320 : " return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
321 0 : "}\n");
322 : emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
323 : "float webgl_fromUnorm(in uint x) {\n"
324 : " return float(x) / 65535.0;\n"
325 : "}\n"
326 : "\n"
327 : "float2 webgl_unpackUnorm2x16_emu(in uint u) {\n"
328 : " uint y = (u >> 16);\n"
329 : " uint x = u & 0xffffu;\n"
330 : " return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n"
331 0 : "}\n");
332 : emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
333 : "float2 webgl_unpackHalf2x16_emu(in uint u) {\n"
334 : " uint y = (u >> 16);\n"
335 : " uint x = u & 0xffffu;\n"
336 : " return float2(f16tof32(x), f16tof32(y));\n"
337 0 : "}\n");
338 :
339 : // The matrix resulting from outer product needs to be transposed
340 : // (matrices are stored as transposed to simplify element access in HLSL).
341 : // So the function should return transpose(c * r) where c is a column vector
342 : // and r is a row vector. This can be simplified by using the following
343 : // formula:
344 : // transpose(c * r) = transpose(r) * transpose(c)
345 : // transpose(r) and transpose(c) are in a sense free, since to get the
346 : // transpose of r, we simply can build a column matrix out of the original
347 : // vector instead of a row matrix.
348 : emu->addEmulatedFunction(EOpOuterProduct, float2, float2,
349 : "float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n"
350 : " return mul(float2x1(r), float1x2(c));\n"
351 0 : "}\n");
352 : emu->addEmulatedFunction(EOpOuterProduct, float3, float3,
353 : "float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n"
354 : " return mul(float3x1(r), float1x3(c));\n"
355 0 : "}\n");
356 : emu->addEmulatedFunction(EOpOuterProduct, float4, float4,
357 : "float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n"
358 : " return mul(float4x1(r), float1x4(c));\n"
359 0 : "}\n");
360 :
361 : emu->addEmulatedFunction(EOpOuterProduct, float3, float2,
362 : "float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n"
363 : " return mul(float2x1(r), float1x3(c));\n"
364 0 : "}\n");
365 : emu->addEmulatedFunction(EOpOuterProduct, float2, float3,
366 : "float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n"
367 : " return mul(float3x1(r), float1x2(c));\n"
368 0 : "}\n");
369 : emu->addEmulatedFunction(EOpOuterProduct, float4, float2,
370 : "float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n"
371 : " return mul(float2x1(r), float1x4(c));\n"
372 0 : "}\n");
373 : emu->addEmulatedFunction(EOpOuterProduct, float2, float4,
374 : "float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n"
375 : " return mul(float4x1(r), float1x2(c));\n"
376 0 : "}\n");
377 : emu->addEmulatedFunction(EOpOuterProduct, float4, float3,
378 : "float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n"
379 : " return mul(float3x1(r), float1x4(c));\n"
380 0 : "}\n");
381 : emu->addEmulatedFunction(EOpOuterProduct, float3, float4,
382 : "float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n"
383 : " return mul(float4x1(r), float1x3(c));\n"
384 0 : "}\n");
385 :
386 0 : TType *mat2 = new TType(EbtFloat, 2, 2);
387 0 : TType *mat3 = new TType(EbtFloat, 3, 3);
388 0 : TType *mat4 = new TType(EbtFloat, 4, 4);
389 :
390 : // Remember here that the parameter matrix is actually the transpose
391 : // of the matrix that we're trying to invert, and the resulting matrix
392 : // should also be the transpose of the inverse.
393 :
394 : // When accessing the parameter matrix with m[a][b] it can be thought of so
395 : // that a is the column and b is the row of the matrix that we're inverting.
396 :
397 : // We calculate the inverse as the adjugate matrix divided by the
398 : // determinant of the matrix being inverted. However, as the result needs
399 : // to be transposed, we actually use of the transpose of the adjugate matrix
400 : // which happens to be the cofactor matrix. That's stored in "cof".
401 :
402 : // We don't need to care about divide-by-zero since results are undefined
403 : // for singular or poorly-conditioned matrices.
404 :
405 : emu->addEmulatedFunction(EOpInverse, mat2,
406 : "float2x2 webgl_inverse_emu(in float2x2 m) {\n"
407 : " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
408 : " return cof / determinant(transpose(m));\n"
409 0 : "}\n");
410 :
411 : // cofAB is the cofactor for column A and row B.
412 :
413 : emu->addEmulatedFunction(EOpInverse, mat3,
414 : "float3x3 webgl_inverse_emu(in float3x3 m) {\n"
415 : " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
416 : " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
417 : " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
418 : " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
419 : " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
420 : " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
421 : " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
422 : " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
423 : " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
424 : " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
425 : " return cof / determinant(transpose(m));\n"
426 0 : "}\n");
427 :
428 : emu->addEmulatedFunction(EOpInverse, mat4,
429 : "float4x4 webgl_inverse_emu(in float4x4 m) {\n"
430 : " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]"
431 : " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n"
432 : " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]"
433 : " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n"
434 : " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]"
435 : " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n"
436 : " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]"
437 : " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n"
438 : " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]"
439 : " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n"
440 : " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]"
441 : " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n"
442 : " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]"
443 : " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n"
444 : " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]"
445 : " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n"
446 : " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]"
447 : " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n"
448 : " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]"
449 : " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n"
450 : " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]"
451 : " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n"
452 : " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]"
453 : " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n"
454 : " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]"
455 : " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n"
456 : " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]"
457 : " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n"
458 : " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]"
459 : " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n"
460 : " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]"
461 : " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n"
462 : " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,"
463 : " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
464 : " return cof / determinant(transpose(m));\n"
465 0 : "}\n");
466 :
467 0 : TType *bool1 = new TType(EbtBool);
468 0 : TType *bool2 = new TType(EbtBool, 2);
469 0 : TType *bool3 = new TType(EbtBool, 3);
470 0 : TType *bool4 = new TType(EbtBool, 4);
471 :
472 : // Emulate ESSL3 variant of mix that takes last argument as boolean vector.
473 : // genType mix (genType x, genType y, genBType a): Selects which vector each returned component comes from.
474 : // For a component of 'a' that is false, the corresponding component of 'x' is returned.For a component of 'a' that is true,
475 : // the corresponding component of 'y' is returned.
476 : emu->addEmulatedFunction(EOpMix, float1, float1, bool1,
477 : "float webgl_mix_emu(float x, float y, bool a)\n"
478 : "{\n"
479 : " return a ? y : x;\n"
480 0 : "}\n");
481 : emu->addEmulatedFunction(EOpMix, float2, float2, bool2,
482 : "float2 webgl_mix_emu(float2 x, float2 y, bool2 a)\n"
483 : "{\n"
484 : " return a ? y : x;\n"
485 0 : "}\n");
486 : emu->addEmulatedFunction(EOpMix, float3, float3, bool3,
487 : "float3 webgl_mix_emu(float3 x, float3 y, bool3 a)\n"
488 : "{\n"
489 : " return a ? y : x;\n"
490 0 : "}\n");
491 : emu->addEmulatedFunction(EOpMix, float4, float4, bool4,
492 : "float4 webgl_mix_emu(float4 x, float4 y, bool4 a)\n"
493 : "{\n"
494 : " return a ? y : x;\n"
495 0 : "}\n");
496 :
497 0 : }
498 :
499 : } // namespace sh
|