1 //
2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2013 LunarG, Inc.
4 // Copyright (C) 2017 ARM Limited.
5 // Copyright (C) 2018 Google, Inc.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // Redistributions in binary form must reproduce the above
17 // copyright notice, this list of conditions and the following
18 // disclaimer in the documentation and/or other materials provided
19 // with the distribution.
20 //
21 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
22 // contributors may be used to endorse or promote products derived
23 // from this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 // POSSIBILITY OF SUCH DAMAGE.
37 //
38
39 #include "localintermediate.h"
40 #include <cmath>
41 #include <cfloat>
42 #include <cstdlib>
43 #include <climits>
44
45 namespace {
46
47 using namespace glslang;
48
49 typedef union {
50 double d;
51 int i[2];
52 } DoubleIntUnion;
53
54 // Some helper functions
55
isNan(double x)56 bool isNan(double x)
57 {
58 DoubleIntUnion u;
59 // tough to find a platform independent library function, do it directly
60 u.d = x;
61 int bitPatternL = u.i[0];
62 int bitPatternH = u.i[1];
63 return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
64 ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
65 }
66
isInf(double x)67 bool isInf(double x)
68 {
69 DoubleIntUnion u;
70 // tough to find a platform independent library function, do it directly
71 u.d = x;
72 int bitPatternL = u.i[0];
73 int bitPatternH = u.i[1];
74 return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
75 (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
76 }
77
78 const double pi = 3.1415926535897932384626433832795;
79
80 } // end anonymous namespace
81
82
83 namespace glslang {
84
85 //
86 // The fold functions see if an operation on a constant can be done in place,
87 // without generating run-time code.
88 //
89 // Returns the node to keep using, which may or may not be the node passed in.
90 //
91 // Note: As of version 1.2, all constant operations must be folded. It is
92 // not opportunistic, but rather a semantic requirement.
93 //
94
95 //
96 // Do folding between a pair of nodes.
97 // 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
98 //
99 // Returns a new node representing the result.
100 //
fold(TOperator op,const TIntermTyped * rightConstantNode) const101 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
102 {
103 // For most cases, the return type matches the argument type, so set that
104 // up and just code to exceptions below.
105 TType returnType;
106 returnType.shallowCopy(getType());
107
108 //
109 // A pair of nodes is to be folded together
110 //
111
112 const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
113 TConstUnionArray leftUnionArray = getConstArray();
114 TConstUnionArray rightUnionArray = rightNode->getConstArray();
115
116 // Figure out the size of the result
117 int newComps;
118 int constComps;
119 switch(op) {
120 case EOpMatrixTimesMatrix:
121 newComps = rightNode->getMatrixCols() * getMatrixRows();
122 break;
123 case EOpMatrixTimesVector:
124 newComps = getMatrixRows();
125 break;
126 case EOpVectorTimesMatrix:
127 newComps = rightNode->getMatrixCols();
128 break;
129 default:
130 newComps = getType().computeNumComponents();
131 constComps = rightConstantNode->getType().computeNumComponents();
132 if (constComps == 1 && newComps > 1) {
133 // for a case like vec4 f = vec4(2,3,4,5) + 1.2;
134 TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]);
135 rightUnionArray = smearedArray;
136 } else if (constComps > 1 && newComps == 1) {
137 // for a case like vec4 f = 1.2 + vec4(2,3,4,5);
138 newComps = constComps;
139 rightUnionArray = rightNode->getConstArray();
140 TConstUnionArray smearedArray(newComps, getConstArray()[0]);
141 leftUnionArray = smearedArray;
142 returnType.shallowCopy(rightNode->getType());
143 }
144 break;
145 }
146
147 TConstUnionArray newConstArray(newComps);
148 TType constBool(EbtBool, EvqConst);
149
150 switch(op) {
151 case EOpAdd:
152 for (int i = 0; i < newComps; i++)
153 newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
154 break;
155 case EOpSub:
156 for (int i = 0; i < newComps; i++)
157 newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
158 break;
159
160 case EOpMul:
161 case EOpVectorTimesScalar:
162 case EOpMatrixTimesScalar:
163 for (int i = 0; i < newComps; i++)
164 newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
165 break;
166 case EOpMatrixTimesMatrix:
167 for (int row = 0; row < getMatrixRows(); row++) {
168 for (int column = 0; column < rightNode->getMatrixCols(); column++) {
169 double sum = 0.0f;
170 for (int i = 0; i < rightNode->getMatrixRows(); i++)
171 sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst();
172 newConstArray[column * getMatrixRows() + row].setDConst(sum);
173 }
174 }
175 returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
176 break;
177 case EOpDiv:
178 for (int i = 0; i < newComps; i++) {
179 switch (getType().getBasicType()) {
180 case EbtDouble:
181 case EbtFloat:
182 case EbtFloat16:
183 if (rightUnionArray[i].getDConst() != 0.0)
184 newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst());
185 else if (leftUnionArray[i].getDConst() > 0.0)
186 newConstArray[i].setDConst((double)INFINITY);
187 else if (leftUnionArray[i].getDConst() < 0.0)
188 newConstArray[i].setDConst(-(double)INFINITY);
189 else
190 newConstArray[i].setDConst((double)NAN);
191 break;
192 case EbtInt8:
193 if (rightUnionArray[i] == (signed char)0)
194 newConstArray[i].setI8Const((signed char)0x7F);
195 else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
196 newConstArray[i].setI8Const((signed char)-0x80);
197 else
198 newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
199 break;
200
201 case EbtUint8:
202 if (rightUnionArray[i] == (unsigned char)0u)
203 newConstArray[i].setU8Const((unsigned char)0xFFu);
204 else
205 newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
206 break;
207
208 case EbtInt16:
209 if (rightUnionArray[i] == (signed short)0)
210 newConstArray[i].setI16Const((signed short)0x7FFF);
211 else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
212 newConstArray[i].setI16Const((signed short)-0x8000);
213 else
214 newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
215 break;
216
217 case EbtUint16:
218 if (rightUnionArray[i] == (unsigned short)0u)
219 newConstArray[i].setU16Const((unsigned short)0xFFFFu);
220 else
221 newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
222 break;
223
224 case EbtInt:
225 if (rightUnionArray[i] == 0)
226 newConstArray[i].setIConst(0x7FFFFFFF);
227 else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
228 newConstArray[i].setIConst((int)-0x80000000ll);
229 else
230 newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
231 break;
232
233 case EbtUint:
234 if (rightUnionArray[i] == 0u)
235 newConstArray[i].setUConst(0xFFFFFFFFu);
236 else
237 newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
238 break;
239
240 case EbtInt64:
241 if (rightUnionArray[i] == 0ll)
242 newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
243 else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll)
244 newConstArray[i].setI64Const((long long)-0x8000000000000000ll);
245 else
246 newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
247 break;
248
249 case EbtUint64:
250 if (rightUnionArray[i] == 0ull)
251 newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
252 else
253 newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
254 break;
255 default:
256 return 0;
257 }
258 }
259 break;
260
261 case EOpMatrixTimesVector:
262 for (int i = 0; i < getMatrixRows(); i++) {
263 double sum = 0.0f;
264 for (int j = 0; j < rightNode->getVectorSize(); j++) {
265 sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
266 }
267 newConstArray[i].setDConst(sum);
268 }
269
270 returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
271 break;
272
273 case EOpVectorTimesMatrix:
274 for (int i = 0; i < rightNode->getMatrixCols(); i++) {
275 double sum = 0.0f;
276 for (int j = 0; j < getVectorSize(); j++)
277 sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
278 newConstArray[i].setDConst(sum);
279 }
280
281 returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
282 break;
283
284 case EOpMod:
285 for (int i = 0; i < newComps; i++) {
286 if (rightUnionArray[i] == 0)
287 newConstArray[i] = leftUnionArray[i];
288 else {
289 switch (getType().getBasicType()) {
290 case EbtInt:
291 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
292 newConstArray[i].setIConst(0);
293 break;
294 } else goto modulo_default;
295
296 case EbtInt64:
297 if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
298 newConstArray[i].setI64Const(0);
299 break;
300 } else goto modulo_default;
301 #ifdef AMD_EXTENSIONS
302 case EbtInt16:
303 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
304 newConstArray[i].setIConst(0);
305 break;
306 } else goto modulo_default;
307 #endif
308 default:
309 modulo_default:
310 newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
311 }
312 }
313 }
314 break;
315
316 case EOpRightShift:
317 for (int i = 0; i < newComps; i++)
318 newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
319 break;
320
321 case EOpLeftShift:
322 for (int i = 0; i < newComps; i++)
323 newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
324 break;
325
326 case EOpAnd:
327 for (int i = 0; i < newComps; i++)
328 newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
329 break;
330 case EOpInclusiveOr:
331 for (int i = 0; i < newComps; i++)
332 newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
333 break;
334 case EOpExclusiveOr:
335 for (int i = 0; i < newComps; i++)
336 newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
337 break;
338
339 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
340 for (int i = 0; i < newComps; i++)
341 newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
342 break;
343
344 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
345 for (int i = 0; i < newComps; i++)
346 newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
347 break;
348
349 case EOpLogicalXor:
350 for (int i = 0; i < newComps; i++) {
351 switch (getType().getBasicType()) {
352 case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
353 default: assert(false && "Default missing");
354 }
355 }
356 break;
357
358 case EOpLessThan:
359 newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
360 returnType.shallowCopy(constBool);
361 break;
362 case EOpGreaterThan:
363 newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
364 returnType.shallowCopy(constBool);
365 break;
366 case EOpLessThanEqual:
367 newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
368 returnType.shallowCopy(constBool);
369 break;
370 case EOpGreaterThanEqual:
371 newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
372 returnType.shallowCopy(constBool);
373 break;
374 case EOpEqual:
375 newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
376 returnType.shallowCopy(constBool);
377 break;
378 case EOpNotEqual:
379 newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
380 returnType.shallowCopy(constBool);
381 break;
382
383 default:
384 return 0;
385 }
386
387 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
388 newNode->setLoc(getLoc());
389
390 return newNode;
391 }
392
393 //
394 // Do single unary node folding
395 //
396 // Returns a new node representing the result.
397 //
fold(TOperator op,const TType & returnType) const398 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
399 {
400 // First, size the result, which is mostly the same as the argument's size,
401 // but not always, and classify what is componentwise.
402 // Also, eliminate cases that can't be compile-time constant.
403 int resultSize;
404 bool componentWise = true;
405
406 int objectSize = getType().computeNumComponents();
407 switch (op) {
408 case EOpDeterminant:
409 case EOpAny:
410 case EOpAll:
411 case EOpLength:
412 componentWise = false;
413 resultSize = 1;
414 break;
415
416 case EOpEmitStreamVertex:
417 case EOpEndStreamPrimitive:
418 // These don't actually fold
419 return 0;
420
421 case EOpPackSnorm2x16:
422 case EOpPackUnorm2x16:
423 case EOpPackHalf2x16:
424 componentWise = false;
425 resultSize = 1;
426 break;
427
428 case EOpUnpackSnorm2x16:
429 case EOpUnpackUnorm2x16:
430 case EOpUnpackHalf2x16:
431 componentWise = false;
432 resultSize = 2;
433 break;
434
435 case EOpPack16:
436 case EOpPack32:
437 case EOpPack64:
438 case EOpUnpack32:
439 case EOpUnpack16:
440 case EOpUnpack8:
441 case EOpNormalize:
442 componentWise = false;
443 resultSize = objectSize;
444 break;
445
446 default:
447 resultSize = objectSize;
448 break;
449 }
450
451 // Set up for processing
452 TConstUnionArray newConstArray(resultSize);
453 const TConstUnionArray& unionArray = getConstArray();
454
455 // Process non-component-wise operations
456 switch (op) {
457 case EOpLength:
458 case EOpNormalize:
459 {
460 double sum = 0;
461 for (int i = 0; i < objectSize; i++)
462 sum += unionArray[i].getDConst() * unionArray[i].getDConst();
463 double length = sqrt(sum);
464 if (op == EOpLength)
465 newConstArray[0].setDConst(length);
466 else {
467 for (int i = 0; i < objectSize; i++)
468 newConstArray[i].setDConst(unionArray[i].getDConst() / length);
469 }
470 break;
471 }
472
473 case EOpAny:
474 {
475 bool result = false;
476 for (int i = 0; i < objectSize; i++) {
477 if (unionArray[i].getBConst())
478 result = true;
479 }
480 newConstArray[0].setBConst(result);
481 break;
482 }
483 case EOpAll:
484 {
485 bool result = true;
486 for (int i = 0; i < objectSize; i++) {
487 if (! unionArray[i].getBConst())
488 result = false;
489 }
490 newConstArray[0].setBConst(result);
491 break;
492 }
493
494 // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
495
496 case EOpPackSnorm2x16:
497 case EOpPackUnorm2x16:
498 case EOpPackHalf2x16:
499 case EOpPack16:
500 case EOpPack32:
501 case EOpPack64:
502 case EOpUnpack32:
503 case EOpUnpack16:
504 case EOpUnpack8:
505
506 case EOpUnpackSnorm2x16:
507 case EOpUnpackUnorm2x16:
508 case EOpUnpackHalf2x16:
509
510 case EOpDeterminant:
511 case EOpMatrixInverse:
512 case EOpTranspose:
513 return 0;
514
515 default:
516 assert(componentWise);
517 break;
518 }
519
520 // Turn off the componentwise loop
521 if (! componentWise)
522 objectSize = 0;
523
524 // Process component-wise operations
525 for (int i = 0; i < objectSize; i++) {
526 switch (op) {
527 case EOpNegative:
528 switch (getType().getBasicType()) {
529 case EbtDouble:
530 case EbtFloat16:
531 case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
532 case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
533 case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
534 case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
535 case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
536 case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
537 case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
538 case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
539 case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
540 default:
541 return 0;
542 }
543 break;
544 case EOpLogicalNot:
545 case EOpVectorLogicalNot:
546 switch (getType().getBasicType()) {
547 case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
548 default:
549 return 0;
550 }
551 break;
552 case EOpBitwiseNot:
553 newConstArray[i] = ~unionArray[i];
554 break;
555 case EOpRadians:
556 newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
557 break;
558 case EOpDegrees:
559 newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
560 break;
561 case EOpSin:
562 newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
563 break;
564 case EOpCos:
565 newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
566 break;
567 case EOpTan:
568 newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
569 break;
570 case EOpAsin:
571 newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
572 break;
573 case EOpAcos:
574 newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
575 break;
576 case EOpAtan:
577 newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
578 break;
579
580 case EOpDPdx:
581 case EOpDPdy:
582 case EOpFwidth:
583 case EOpDPdxFine:
584 case EOpDPdyFine:
585 case EOpFwidthFine:
586 case EOpDPdxCoarse:
587 case EOpDPdyCoarse:
588 case EOpFwidthCoarse:
589 // The derivatives are all mandated to create a constant 0.
590 newConstArray[i].setDConst(0.0);
591 break;
592
593 case EOpExp:
594 newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
595 break;
596 case EOpLog:
597 newConstArray[i].setDConst(log(unionArray[i].getDConst()));
598 break;
599 case EOpExp2:
600 {
601 const double inv_log2_e = 0.69314718055994530941723212145818;
602 newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
603 break;
604 }
605 case EOpLog2:
606 {
607 const double log2_e = 1.4426950408889634073599246810019;
608 newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
609 break;
610 }
611 case EOpSqrt:
612 newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
613 break;
614 case EOpInverseSqrt:
615 newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
616 break;
617
618 case EOpAbs:
619 if (unionArray[i].getType() == EbtDouble)
620 newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
621 else if (unionArray[i].getType() == EbtInt)
622 newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
623 else
624 newConstArray[i] = unionArray[i];
625 break;
626 case EOpSign:
627 #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
628 if (unionArray[i].getType() == EbtDouble)
629 newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
630 else
631 newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
632 break;
633 case EOpFloor:
634 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
635 break;
636 case EOpTrunc:
637 if (unionArray[i].getDConst() > 0)
638 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
639 else
640 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
641 break;
642 case EOpRound:
643 newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
644 break;
645 case EOpRoundEven:
646 {
647 double flr = floor(unionArray[i].getDConst());
648 bool even = flr / 2.0 == floor(flr / 2.0);
649 double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
650 newConstArray[i].setDConst(rounded);
651 break;
652 }
653 case EOpCeil:
654 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
655 break;
656 case EOpFract:
657 {
658 double x = unionArray[i].getDConst();
659 newConstArray[i].setDConst(x - floor(x));
660 break;
661 }
662
663 case EOpIsNan:
664 {
665 newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
666 break;
667 }
668 case EOpIsInf:
669 {
670 newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
671 break;
672 }
673
674 case EOpConvInt8ToBool:
675 newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
676 case EOpConvUint8ToBool:
677 newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
678 case EOpConvInt16ToBool:
679 newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
680 case EOpConvUint16ToBool:
681 newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
682 case EOpConvIntToBool:
683 newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
684 case EOpConvUintToBool:
685 newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
686 case EOpConvInt64ToBool:
687 newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
688 case EOpConvUint64ToBool:
689 newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
690 case EOpConvFloat16ToBool:
691 newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
692 case EOpConvFloatToBool:
693 newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
694 case EOpConvDoubleToBool:
695 newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
696
697 case EOpConvBoolToInt8:
698 newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
699 case EOpConvBoolToUint8:
700 newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
701 case EOpConvBoolToInt16:
702 newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
703 case EOpConvBoolToUint16:
704 newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
705 case EOpConvBoolToInt:
706 newConstArray[i].setIConst(unionArray[i].getBConst()); break;
707 case EOpConvBoolToUint:
708 newConstArray[i].setUConst(unionArray[i].getBConst()); break;
709 case EOpConvBoolToInt64:
710 newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
711 case EOpConvBoolToUint64:
712 newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
713 case EOpConvBoolToFloat16:
714 newConstArray[i].setDConst(unionArray[i].getBConst()); break;
715 case EOpConvBoolToFloat:
716 newConstArray[i].setDConst(unionArray[i].getBConst()); break;
717 case EOpConvBoolToDouble:
718 newConstArray[i].setDConst(unionArray[i].getBConst()); break;
719
720 case EOpConvInt8ToInt16:
721 newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
722 case EOpConvInt8ToInt:
723 newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
724 case EOpConvInt8ToInt64:
725 newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
726 case EOpConvInt8ToUint8:
727 newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
728 case EOpConvInt8ToUint16:
729 newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
730 case EOpConvInt8ToUint:
731 newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
732 case EOpConvInt8ToUint64:
733 newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
734 case EOpConvUint8ToInt8:
735 newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
736 case EOpConvUint8ToInt16:
737 newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
738 case EOpConvUint8ToInt:
739 newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
740 case EOpConvUint8ToInt64:
741 newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
742 case EOpConvUint8ToUint16:
743 newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
744 case EOpConvUint8ToUint:
745 newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
746 case EOpConvUint8ToUint64:
747 newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
748 case EOpConvInt8ToFloat16:
749 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
750 case EOpConvInt8ToFloat:
751 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
752 case EOpConvInt8ToDouble:
753 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
754 case EOpConvUint8ToFloat16:
755 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
756 case EOpConvUint8ToFloat:
757 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
758 case EOpConvUint8ToDouble:
759 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
760
761 case EOpConvInt16ToInt8:
762 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
763 case EOpConvInt16ToInt:
764 newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
765 case EOpConvInt16ToInt64:
766 newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
767 case EOpConvInt16ToUint8:
768 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
769 case EOpConvInt16ToUint16:
770 newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
771 case EOpConvInt16ToUint:
772 newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
773 case EOpConvInt16ToUint64:
774 newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
775 case EOpConvUint16ToInt8:
776 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
777 case EOpConvUint16ToInt16:
778 newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
779 case EOpConvUint16ToInt:
780 newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
781 case EOpConvUint16ToInt64:
782 newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
783 case EOpConvUint16ToUint8:
784 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
785
786 case EOpConvUint16ToUint:
787 newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
788 case EOpConvUint16ToUint64:
789 newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
790 case EOpConvInt16ToFloat16:
791 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
792 case EOpConvInt16ToFloat:
793 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
794 case EOpConvInt16ToDouble:
795 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
796 case EOpConvUint16ToFloat16:
797 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
798 case EOpConvUint16ToFloat:
799 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
800 case EOpConvUint16ToDouble:
801 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
802
803 case EOpConvIntToInt8:
804 newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
805 case EOpConvIntToInt16:
806 newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
807 case EOpConvIntToInt64:
808 newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
809 case EOpConvIntToUint8:
810 newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
811 case EOpConvIntToUint16:
812 newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
813 case EOpConvIntToUint:
814 newConstArray[i].setUConst(unionArray[i].getIConst()); break;
815 case EOpConvIntToUint64:
816 newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
817
818 case EOpConvUintToInt8:
819 newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
820 case EOpConvUintToInt16:
821 newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
822 case EOpConvUintToInt:
823 newConstArray[i].setIConst(unionArray[i].getUConst()); break;
824 case EOpConvUintToInt64:
825 newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
826 case EOpConvUintToUint8:
827 newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
828 case EOpConvUintToUint16:
829 newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
830 case EOpConvUintToUint64:
831 newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
832 case EOpConvIntToFloat16:
833 newConstArray[i].setDConst(unionArray[i].getIConst()); break;
834 case EOpConvIntToFloat:
835 newConstArray[i].setDConst(unionArray[i].getIConst()); break;
836 case EOpConvIntToDouble:
837 newConstArray[i].setDConst(unionArray[i].getIConst()); break;
838 case EOpConvUintToFloat16:
839 newConstArray[i].setDConst(unionArray[i].getUConst()); break;
840 case EOpConvUintToFloat:
841 newConstArray[i].setDConst(unionArray[i].getUConst()); break;
842 case EOpConvUintToDouble:
843 newConstArray[i].setDConst(unionArray[i].getUConst()); break;
844 case EOpConvInt64ToInt8:
845 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
846 case EOpConvInt64ToInt16:
847 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
848 case EOpConvInt64ToInt:
849 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
850 case EOpConvInt64ToUint8:
851 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
852 case EOpConvInt64ToUint16:
853 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
854 case EOpConvInt64ToUint:
855 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
856 case EOpConvInt64ToUint64:
857 newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
858 case EOpConvUint64ToInt8:
859 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
860 case EOpConvUint64ToInt16:
861 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
862 case EOpConvUint64ToInt:
863 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
864 case EOpConvUint64ToInt64:
865 newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
866 case EOpConvUint64ToUint8:
867 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
868 case EOpConvUint64ToUint16:
869 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
870 case EOpConvUint64ToUint:
871 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
872 case EOpConvInt64ToFloat16:
873 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
874 case EOpConvInt64ToFloat:
875 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
876 case EOpConvInt64ToDouble:
877 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
878 case EOpConvUint64ToFloat16:
879 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
880 case EOpConvUint64ToFloat:
881 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
882 case EOpConvUint64ToDouble:
883 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
884 case EOpConvFloat16ToInt8:
885 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
886 case EOpConvFloat16ToInt16:
887 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
888 case EOpConvFloat16ToInt:
889 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
890 case EOpConvFloat16ToInt64:
891 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
892 case EOpConvFloat16ToUint8:
893 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
894 case EOpConvFloat16ToUint16:
895 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
896 case EOpConvFloat16ToUint:
897 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
898 case EOpConvFloat16ToUint64:
899 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
900 case EOpConvFloat16ToFloat:
901 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
902 case EOpConvFloat16ToDouble:
903 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
904 case EOpConvFloatToInt8:
905 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
906 case EOpConvFloatToInt16:
907 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
908 case EOpConvFloatToInt:
909 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
910 case EOpConvFloatToInt64:
911 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
912 case EOpConvFloatToUint8:
913 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
914 case EOpConvFloatToUint16:
915 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
916 case EOpConvFloatToUint:
917 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
918 case EOpConvFloatToUint64:
919 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
920 case EOpConvFloatToFloat16:
921 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
922 case EOpConvFloatToDouble:
923 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
924 case EOpConvDoubleToInt8:
925 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
926 case EOpConvDoubleToInt16:
927 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
928 case EOpConvDoubleToInt:
929 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
930 case EOpConvDoubleToInt64:
931 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
932 case EOpConvDoubleToUint8:
933 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
934 case EOpConvDoubleToUint16:
935 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
936 case EOpConvDoubleToUint:
937 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
938 case EOpConvDoubleToUint64:
939 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
940 case EOpConvDoubleToFloat16:
941 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
942 case EOpConvDoubleToFloat:
943 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
944
945
946
947 // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
948
949 case EOpSinh:
950 case EOpCosh:
951 case EOpTanh:
952 case EOpAsinh:
953 case EOpAcosh:
954 case EOpAtanh:
955
956 case EOpFloatBitsToInt:
957 case EOpFloatBitsToUint:
958 case EOpIntBitsToFloat:
959 case EOpUintBitsToFloat:
960 case EOpDoubleBitsToInt64:
961 case EOpDoubleBitsToUint64:
962 case EOpInt64BitsToDouble:
963 case EOpUint64BitsToDouble:
964 case EOpFloat16BitsToInt16:
965 case EOpFloat16BitsToUint16:
966 case EOpInt16BitsToFloat16:
967 case EOpUint16BitsToFloat16:
968 default:
969 return 0;
970 }
971 }
972
973 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
974 newNode->getWritableType().getQualifier().storage = EvqConst;
975 newNode->setLoc(getLoc());
976
977 return newNode;
978 }
979
980 //
981 // Do constant folding for an aggregate node that has all its children
982 // as constants and an operator that requires constant folding.
983 //
fold(TIntermAggregate * aggrNode)984 TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
985 {
986 if (aggrNode == nullptr)
987 return aggrNode;
988
989 if (! areAllChildConst(aggrNode))
990 return aggrNode;
991
992 if (aggrNode->isConstructor())
993 return foldConstructor(aggrNode);
994
995 TIntermSequence& children = aggrNode->getSequence();
996
997 // First, see if this is an operation to constant fold, kick out if not,
998 // see what size the result is if so.
999
1000 bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results
1001 int objectSize;
1002 switch (aggrNode->getOp()) {
1003 case EOpAtan:
1004 case EOpPow:
1005 case EOpMin:
1006 case EOpMax:
1007 case EOpMix:
1008 case EOpClamp:
1009 case EOpLessThan:
1010 case EOpGreaterThan:
1011 case EOpLessThanEqual:
1012 case EOpGreaterThanEqual:
1013 case EOpVectorEqual:
1014 case EOpVectorNotEqual:
1015 componentwise = true;
1016 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1017 break;
1018 case EOpCross:
1019 case EOpReflect:
1020 case EOpRefract:
1021 case EOpFaceForward:
1022 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1023 break;
1024 case EOpDistance:
1025 case EOpDot:
1026 objectSize = 1;
1027 break;
1028 case EOpOuterProduct:
1029 objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
1030 children[1]->getAsTyped()->getType().getVectorSize();
1031 break;
1032 case EOpStep:
1033 componentwise = true;
1034 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1035 children[1]->getAsTyped()->getType().getVectorSize());
1036 break;
1037 case EOpSmoothStep:
1038 componentwise = true;
1039 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1040 children[2]->getAsTyped()->getType().getVectorSize());
1041 break;
1042 default:
1043 return aggrNode;
1044 }
1045 TConstUnionArray newConstArray(objectSize);
1046
1047 TVector<TConstUnionArray> childConstUnions;
1048 for (unsigned int arg = 0; arg < children.size(); ++arg)
1049 childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
1050
1051 if (componentwise) {
1052 for (int comp = 0; comp < objectSize; comp++) {
1053
1054 // some arguments are scalars instead of matching vectors; simulate a smear
1055 int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
1056 int arg1comp = 0;
1057 if (children.size() > 1)
1058 arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
1059 int arg2comp = 0;
1060 if (children.size() > 2)
1061 arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
1062
1063 switch (aggrNode->getOp()) {
1064 case EOpAtan:
1065 newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1066 break;
1067 case EOpPow:
1068 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1069 break;
1070 case EOpMin:
1071 switch(children[0]->getAsTyped()->getBasicType()) {
1072 case EbtFloat16:
1073 case EbtFloat:
1074 case EbtDouble:
1075 newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1076 break;
1077 case EbtInt8:
1078 newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1079 break;
1080 case EbtUint8:
1081 newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1082 break;
1083 case EbtInt16:
1084 newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1085 break;
1086 case EbtUint16:
1087 newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1088 break;
1089 case EbtInt:
1090 newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1091 break;
1092 case EbtUint:
1093 newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1094 break;
1095 case EbtInt64:
1096 newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1097 break;
1098 case EbtUint64:
1099 newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1100 break;
1101 default: assert(false && "Default missing");
1102 }
1103 break;
1104 case EOpMax:
1105 switch(children[0]->getAsTyped()->getBasicType()) {
1106 case EbtFloat16:
1107 case EbtFloat:
1108 case EbtDouble:
1109 newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1110 break;
1111 case EbtInt8:
1112 newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1113 break;
1114 case EbtUint8:
1115 newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1116 break;
1117 case EbtInt16:
1118 newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1119 break;
1120 case EbtUint16:
1121 newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1122 break;
1123 case EbtInt:
1124 newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1125 break;
1126 case EbtUint:
1127 newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1128 break;
1129 case EbtInt64:
1130 newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1131 break;
1132 case EbtUint64:
1133 newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1134 break;
1135 default: assert(false && "Default missing");
1136 }
1137 break;
1138 case EOpClamp:
1139 switch(children[0]->getAsTyped()->getBasicType()) {
1140 case EbtFloat16:
1141 case EbtFloat:
1142 case EbtDouble:
1143 newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
1144 childConstUnions[2][arg2comp].getDConst()));
1145 break;
1146 case EbtInt8:
1147 newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
1148 childConstUnions[2][arg2comp].getI8Const()));
1149 break;
1150 case EbtUint8:
1151 newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
1152 childConstUnions[2][arg2comp].getU8Const()));
1153 break;
1154 case EbtInt16:
1155 newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
1156 childConstUnions[2][arg2comp].getI16Const()));
1157 break;
1158 case EbtUint16:
1159 newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
1160 childConstUnions[2][arg2comp].getU16Const()));
1161 break;
1162 case EbtInt:
1163 newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
1164 childConstUnions[2][arg2comp].getIConst()));
1165 break;
1166 case EbtUint:
1167 newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
1168 childConstUnions[2][arg2comp].getUConst()));
1169 break;
1170 case EbtInt64:
1171 newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
1172 childConstUnions[2][arg2comp].getI64Const()));
1173 break;
1174 case EbtUint64:
1175 newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
1176 childConstUnions[2][arg2comp].getU64Const()));
1177 break;
1178 default: assert(false && "Default missing");
1179 }
1180 break;
1181 case EOpLessThan:
1182 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
1183 break;
1184 case EOpGreaterThan:
1185 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
1186 break;
1187 case EOpLessThanEqual:
1188 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
1189 break;
1190 case EOpGreaterThanEqual:
1191 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
1192 break;
1193 case EOpVectorEqual:
1194 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
1195 break;
1196 case EOpVectorNotEqual:
1197 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
1198 break;
1199 case EOpMix:
1200 if (children[2]->getAsTyped()->getBasicType() == EbtBool)
1201 newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() :
1202 childConstUnions[0][arg0comp].getDConst());
1203 else
1204 newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
1205 childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst());
1206 break;
1207 case EOpStep:
1208 newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
1209 break;
1210 case EOpSmoothStep:
1211 {
1212 double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
1213 (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
1214 if (t < 0.0)
1215 t = 0.0;
1216 if (t > 1.0)
1217 t = 1.0;
1218 newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
1219 break;
1220 }
1221 default:
1222 return aggrNode;
1223 }
1224 }
1225 } else {
1226 // Non-componentwise...
1227
1228 int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1229 double dot;
1230
1231 switch (aggrNode->getOp()) {
1232 case EOpDistance:
1233 {
1234 double sum = 0.0;
1235 for (int comp = 0; comp < numComps; ++comp) {
1236 double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
1237 sum += diff * diff;
1238 }
1239 newConstArray[0].setDConst(sqrt(sum));
1240 break;
1241 }
1242 case EOpDot:
1243 newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
1244 break;
1245 case EOpCross:
1246 newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
1247 newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
1248 newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
1249 break;
1250 case EOpFaceForward:
1251 // If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref).
1252 dot = childConstUnions[1].dot(childConstUnions[2]);
1253 for (int comp = 0; comp < numComps; ++comp) {
1254 if (dot < 0.0)
1255 newConstArray[comp] = childConstUnions[0][comp];
1256 else
1257 newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
1258 }
1259 break;
1260 case EOpReflect:
1261 // I - 2 * dot(N, I) * N: Arguments are (I, N).
1262 dot = childConstUnions[0].dot(childConstUnions[1]);
1263 dot *= 2.0;
1264 for (int comp = 0; comp < numComps; ++comp)
1265 newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
1266 break;
1267 case EOpRefract:
1268 {
1269 // Arguments are (I, N, eta).
1270 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
1271 // if (k < 0.0)
1272 // return dvec(0.0)
1273 // else
1274 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
1275 dot = childConstUnions[0].dot(childConstUnions[1]);
1276 double eta = childConstUnions[2][0].getDConst();
1277 double k = 1.0 - eta * eta * (1.0 - dot * dot);
1278 if (k < 0.0) {
1279 for (int comp = 0; comp < numComps; ++comp)
1280 newConstArray[comp].setDConst(0.0);
1281 } else {
1282 for (int comp = 0; comp < numComps; ++comp)
1283 newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
1284 }
1285 break;
1286 }
1287 case EOpOuterProduct:
1288 {
1289 int numRows = numComps;
1290 int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
1291 for (int row = 0; row < numRows; ++row)
1292 for (int col = 0; col < numCols; ++col)
1293 newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
1294 break;
1295 }
1296 default:
1297 return aggrNode;
1298 }
1299 }
1300
1301 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
1302 newNode->getWritableType().getQualifier().storage = EvqConst;
1303 newNode->setLoc(aggrNode->getLoc());
1304
1305 return newNode;
1306 }
1307
areAllChildConst(TIntermAggregate * aggrNode)1308 bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
1309 {
1310 bool allConstant = true;
1311
1312 // check if all the child nodes are constants so that they can be inserted into
1313 // the parent node
1314 if (aggrNode) {
1315 TIntermSequence& childSequenceVector = aggrNode->getSequence();
1316 for (TIntermSequence::iterator p = childSequenceVector.begin();
1317 p != childSequenceVector.end(); p++) {
1318 if (!(*p)->getAsTyped()->getAsConstantUnion())
1319 return false;
1320 }
1321 }
1322
1323 return allConstant;
1324 }
1325
foldConstructor(TIntermAggregate * aggrNode)1326 TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
1327 {
1328 bool error = false;
1329
1330 TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
1331 if (aggrNode->getSequence().size() == 1)
1332 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
1333 else
1334 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
1335
1336 if (error)
1337 return aggrNode;
1338
1339 return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
1340 }
1341
1342 //
1343 // Constant folding of a bracket (array-style) dereference or struct-like dot
1344 // dereference. Can handle anything except a multi-character swizzle, though
1345 // all swizzles may go to foldSwizzle().
1346 //
foldDereference(TIntermTyped * node,int index,const TSourceLoc & loc)1347 TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
1348 {
1349 TType dereferencedType(node->getType(), index);
1350 dereferencedType.getQualifier().storage = EvqConst;
1351 TIntermTyped* result = 0;
1352 int size = dereferencedType.computeNumComponents();
1353
1354 // arrays, vectors, matrices, all use simple multiplicative math
1355 // while structures need to add up heterogeneous members
1356 int start;
1357 if (node->isArray() || ! node->isStruct())
1358 start = size * index;
1359 else {
1360 // it is a structure
1361 assert(node->isStruct());
1362 start = 0;
1363 for (int i = 0; i < index; ++i)
1364 start += (*node->getType().getStruct())[i].type->computeNumComponents();
1365 }
1366
1367 result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
1368
1369 if (result == 0)
1370 result = node;
1371 else
1372 result->setType(dereferencedType);
1373
1374 return result;
1375 }
1376
1377 //
1378 // Make a constant vector node or constant scalar node, representing a given
1379 // constant vector and constant swizzle into it.
1380 //
foldSwizzle(TIntermTyped * node,TSwizzleSelectors<TVectorSelector> & selectors,const TSourceLoc & loc)1381 TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
1382 {
1383 const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
1384 TConstUnionArray constArray(selectors.size());
1385
1386 for (int i = 0; i < selectors.size(); i++)
1387 constArray[i] = unionArray[selectors[i]];
1388
1389 TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
1390
1391 if (result == 0)
1392 result = node;
1393 else
1394 result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
1395
1396 return result;
1397 }
1398
1399 } // end namespace glslang
1400