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-2020 Google, Inc.
7 // All rights reserved.
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
13 // Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
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.
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.
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.
39 #include "localintermediate.h"
47 using namespace glslang;
54 // Some helper functions
59 // tough to find a platform independent library function, do it directly
61 int bitPatternL = u.i[0];
62 int bitPatternH = u.i[1];
63 return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
64 ((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
70 // tough to find a platform independent library function, do it directly
72 int bitPatternL = u.i[0];
73 int bitPatternH = u.i[1];
74 return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
75 (bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
78 const double pi = 3.1415926535897932384626433832795;
80 } // end anonymous namespace
86 // The fold functions see if an operation on a constant can be done in place,
87 // without generating run-time code.
89 // Returns the node to keep using, which may or may not be the node passed in.
91 // Note: As of version 1.2, all constant operations must be folded. It is
92 // not opportunistic, but rather a semantic requirement.
96 // Do folding between a pair of nodes.
97 // 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand.
99 // Returns a new node representing the result.
101 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const
103 // For most cases, the return type matches the argument type, so set that
104 // up and just code to exceptions below.
106 returnType.shallowCopy(getType());
109 // A pair of nodes is to be folded together
112 const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion();
113 TConstUnionArray leftUnionArray = getConstArray();
114 TConstUnionArray rightUnionArray = rightNode->getConstArray();
116 // Figure out the size of the result
120 case EOpMatrixTimesMatrix:
121 newComps = rightNode->getMatrixCols() * getMatrixRows();
123 case EOpMatrixTimesVector:
124 newComps = getMatrixRows();
126 case EOpVectorTimesMatrix:
127 newComps = rightNode->getMatrixCols();
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());
147 TConstUnionArray newConstArray(newComps);
148 TType constBool(EbtBool, EvqConst);
152 for (int i = 0; i < newComps; i++)
153 newConstArray[i] = leftUnionArray[i] + rightUnionArray[i];
156 for (int i = 0; i < newComps; i++)
157 newConstArray[i] = leftUnionArray[i] - rightUnionArray[i];
161 case EOpVectorTimesScalar:
162 case EOpMatrixTimesScalar:
163 for (int i = 0; i < newComps; i++)
164 newConstArray[i] = leftUnionArray[i] * rightUnionArray[i];
166 case EOpMatrixTimesMatrix:
167 for (int row = 0; row < getMatrixRows(); row++) {
168 for (int column = 0; column < rightNode->getMatrixCols(); column++) {
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);
175 returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows()));
178 for (int i = 0; i < newComps; i++) {
179 switch (getType().getBasicType()) {
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);
190 newConstArray[i].setDConst((double)NAN);
194 if (rightUnionArray[i] == 0)
195 newConstArray[i].setIConst(0x7FFFFFFF);
196 else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
197 newConstArray[i].setIConst((int)-0x80000000ll);
199 newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
203 if (rightUnionArray[i] == 0u)
204 newConstArray[i].setUConst(0xFFFFFFFFu);
206 newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
211 if (rightUnionArray[i] == (signed char)0)
212 newConstArray[i].setI8Const((signed char)0x7F);
213 else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80)
214 newConstArray[i].setI8Const((signed char)-0x80);
216 newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
220 if (rightUnionArray[i] == (unsigned char)0u)
221 newConstArray[i].setU8Const((unsigned char)0xFFu);
223 newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
227 if (rightUnionArray[i] == (signed short)0)
228 newConstArray[i].setI16Const((signed short)0x7FFF);
229 else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000)
230 newConstArray[i].setI16Const((signed short)-0x8000);
232 newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
236 if (rightUnionArray[i] == (unsigned short)0u)
237 newConstArray[i].setU16Const((unsigned short)0xFFFFu);
239 newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
243 if (rightUnionArray[i] == 0ll)
244 newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
245 else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll)
246 newConstArray[i].setI64Const((long long)-0x8000000000000000ll);
248 newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
252 if (rightUnionArray[i] == 0ull)
253 newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
255 newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
264 case EOpMatrixTimesVector:
265 for (int i = 0; i < getMatrixRows(); i++) {
267 for (int j = 0; j < rightNode->getVectorSize(); j++) {
268 sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
270 newConstArray[i].setDConst(sum);
273 returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
276 case EOpVectorTimesMatrix:
277 for (int i = 0; i < rightNode->getMatrixCols(); i++) {
279 for (int j = 0; j < getVectorSize(); j++)
280 sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
281 newConstArray[i].setDConst(sum);
284 returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
288 for (int i = 0; i < newComps; i++) {
289 if (rightUnionArray[i] == 0)
290 newConstArray[i] = leftUnionArray[i];
292 switch (getType().getBasicType()) {
294 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
295 newConstArray[i].setIConst(0);
297 } else goto modulo_default;
300 if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
301 newConstArray[i].setI64Const(0);
303 } else goto modulo_default;
305 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
306 newConstArray[i].setIConst(0);
308 } else goto modulo_default;
312 newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
319 for (int i = 0; i < newComps; i++)
320 newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
324 for (int i = 0; i < newComps; i++)
325 newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
329 for (int i = 0; i < newComps; i++)
330 newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
333 for (int i = 0; i < newComps; i++)
334 newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
337 for (int i = 0; i < newComps; i++)
338 newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
341 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
342 for (int i = 0; i < newComps; i++)
343 newConstArray[i] = leftUnionArray[i] && rightUnionArray[i];
346 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
347 for (int i = 0; i < newComps; i++)
348 newConstArray[i] = leftUnionArray[i] || rightUnionArray[i];
352 for (int i = 0; i < newComps; i++) {
353 switch (getType().getBasicType()) {
354 case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
355 default: assert(false && "Default missing");
361 newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
362 returnType.shallowCopy(constBool);
365 newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
366 returnType.shallowCopy(constBool);
368 case EOpLessThanEqual:
369 newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
370 returnType.shallowCopy(constBool);
372 case EOpGreaterThanEqual:
373 newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
374 returnType.shallowCopy(constBool);
377 newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
378 returnType.shallowCopy(constBool);
381 newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
382 returnType.shallowCopy(constBool);
389 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
390 newNode->setLoc(getLoc());
396 // Do single unary node folding
398 // Returns a new node representing the result.
400 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
402 // First, size the result, which is mostly the same as the argument's size,
403 // but not always, and classify what is componentwise.
404 // Also, eliminate cases that can't be compile-time constant.
406 bool componentWise = true;
408 int objectSize = getType().computeNumComponents();
414 componentWise = false;
418 case EOpEmitStreamVertex:
419 case EOpEndStreamPrimitive:
423 case EOpPackSnorm2x16:
424 case EOpPackUnorm2x16:
425 case EOpPackHalf2x16:
426 componentWise = false;
430 case EOpUnpackSnorm2x16:
431 case EOpUnpackUnorm2x16:
432 case EOpUnpackHalf2x16:
433 componentWise = false;
444 componentWise = false;
445 resultSize = objectSize;
449 resultSize = objectSize;
453 // Set up for processing
454 TConstUnionArray newConstArray(resultSize);
455 const TConstUnionArray& unionArray = getConstArray();
457 // Process non-component-wise operations
463 for (int i = 0; i < objectSize; i++)
464 sum += unionArray[i].getDConst() * unionArray[i].getDConst();
465 double length = sqrt(sum);
467 newConstArray[0].setDConst(length);
469 for (int i = 0; i < objectSize; i++)
470 newConstArray[i].setDConst(unionArray[i].getDConst() / length);
478 for (int i = 0; i < objectSize; i++) {
479 if (unionArray[i].getBConst())
482 newConstArray[0].setBConst(result);
488 for (int i = 0; i < objectSize; i++) {
489 if (! unionArray[i].getBConst())
492 newConstArray[0].setBConst(result);
496 case EOpPackSnorm2x16:
497 case EOpPackUnorm2x16:
498 case EOpPackHalf2x16:
506 case EOpUnpackSnorm2x16:
507 case EOpUnpackUnorm2x16:
508 case EOpUnpackHalf2x16:
511 case EOpMatrixInverse:
516 assert(componentWise);
520 // Turn off the componentwise loop
524 // Process component-wise operations
525 for (int i = 0; i < objectSize; i++) {
528 switch (getType().getBasicType()) {
531 case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
532 // Note: avoid UBSAN error regarding negating 0x80000000
533 case EbtInt: newConstArray[i].setIConst(
534 static_cast<unsigned int>(unionArray[i].getIConst()) == 0x80000000
536 : -unionArray[i].getIConst());
538 case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
540 case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
541 case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
542 case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
543 case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
544 case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
545 case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
552 case EOpVectorLogicalNot:
553 switch (getType().getBasicType()) {
554 case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
560 newConstArray[i] = ~unionArray[i];
563 newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
566 newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
569 newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
572 newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
575 newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
578 newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
581 newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
584 newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
595 case EOpFwidthCoarse:
596 // The derivatives are all mandated to create a constant 0.
597 newConstArray[i].setDConst(0.0);
601 newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
604 newConstArray[i].setDConst(log(unionArray[i].getDConst()));
607 newConstArray[i].setDConst(exp2(unionArray[i].getDConst()));
610 newConstArray[i].setDConst(log2(unionArray[i].getDConst()));
613 newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
616 newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
620 if (unionArray[i].getType() == EbtDouble)
621 newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
622 else if (unionArray[i].getType() == EbtInt)
623 newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
625 newConstArray[i] = unionArray[i];
628 #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
629 if (unionArray[i].getType() == EbtDouble)
630 newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
632 newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
635 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
638 if (unionArray[i].getDConst() > 0)
639 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
641 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
644 newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
648 double flr = floor(unionArray[i].getDConst());
649 bool even = flr / 2.0 == floor(flr / 2.0);
650 double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
651 newConstArray[i].setDConst(rounded);
655 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
659 double x = unionArray[i].getDConst();
660 newConstArray[i].setDConst(x - floor(x));
666 newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
671 newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
675 case EOpConvIntToBool:
676 newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
677 case EOpConvUintToBool:
678 newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
679 case EOpConvBoolToInt:
680 newConstArray[i].setIConst(unionArray[i].getBConst()); break;
681 case EOpConvBoolToUint:
682 newConstArray[i].setUConst(unionArray[i].getBConst()); break;
683 case EOpConvIntToUint:
684 newConstArray[i].setUConst(unionArray[i].getIConst()); break;
685 case EOpConvUintToInt:
686 newConstArray[i].setIConst(unionArray[i].getUConst()); break;
688 case EOpConvFloatToBool:
689 case EOpConvDoubleToBool:
690 newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
692 case EOpConvBoolToFloat:
693 case EOpConvBoolToDouble:
694 newConstArray[i].setDConst(unionArray[i].getBConst()); break;
696 case EOpConvIntToFloat:
697 case EOpConvIntToDouble:
698 newConstArray[i].setDConst(unionArray[i].getIConst()); break;
700 case EOpConvUintToFloat:
701 case EOpConvUintToDouble:
702 newConstArray[i].setDConst(unionArray[i].getUConst()); break;
704 case EOpConvDoubleToFloat:
705 case EOpConvFloatToDouble:
706 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
708 case EOpConvFloatToUint:
709 case EOpConvDoubleToUint:
710 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
712 case EOpConvFloatToInt:
713 case EOpConvDoubleToInt:
714 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
717 case EOpConvInt8ToBool:
718 newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
719 case EOpConvUint8ToBool:
720 newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
721 case EOpConvInt16ToBool:
722 newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
723 case EOpConvUint16ToBool:
724 newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
725 case EOpConvInt64ToBool:
726 newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
727 case EOpConvUint64ToBool:
728 newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
729 case EOpConvFloat16ToBool:
730 newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
732 case EOpConvBoolToInt8:
733 newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
734 case EOpConvBoolToUint8:
735 newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
736 case EOpConvBoolToInt16:
737 newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
738 case EOpConvBoolToUint16:
739 newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
740 case EOpConvBoolToInt64:
741 newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
742 case EOpConvBoolToUint64:
743 newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
744 case EOpConvBoolToFloat16:
745 newConstArray[i].setDConst(unionArray[i].getBConst()); break;
747 case EOpConvInt8ToInt16:
748 newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
749 case EOpConvInt8ToInt:
750 newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
751 case EOpConvInt8ToInt64:
752 newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
753 case EOpConvInt8ToUint8:
754 newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
755 case EOpConvInt8ToUint16:
756 newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
757 case EOpConvInt8ToUint:
758 newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
759 case EOpConvInt8ToUint64:
760 newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
761 case EOpConvUint8ToInt8:
762 newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
763 case EOpConvUint8ToInt16:
764 newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
765 case EOpConvUint8ToInt:
766 newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
767 case EOpConvUint8ToInt64:
768 newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
769 case EOpConvUint8ToUint16:
770 newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
771 case EOpConvUint8ToUint:
772 newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
773 case EOpConvUint8ToUint64:
774 newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
775 case EOpConvInt8ToFloat16:
776 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
777 case EOpConvInt8ToFloat:
778 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
779 case EOpConvInt8ToDouble:
780 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
781 case EOpConvUint8ToFloat16:
782 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
783 case EOpConvUint8ToFloat:
784 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
785 case EOpConvUint8ToDouble:
786 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
788 case EOpConvInt16ToInt8:
789 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
790 case EOpConvInt16ToInt:
791 newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
792 case EOpConvInt16ToInt64:
793 newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
794 case EOpConvInt16ToUint8:
795 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
796 case EOpConvInt16ToUint16:
797 newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
798 case EOpConvInt16ToUint:
799 newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
800 case EOpConvInt16ToUint64:
801 newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
802 case EOpConvUint16ToInt8:
803 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
804 case EOpConvUint16ToInt16:
805 newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
806 case EOpConvUint16ToInt:
807 newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
808 case EOpConvUint16ToInt64:
809 newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
810 case EOpConvUint16ToUint8:
811 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
813 case EOpConvUint16ToUint:
814 newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
815 case EOpConvUint16ToUint64:
816 newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
817 case EOpConvInt16ToFloat16:
818 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
819 case EOpConvInt16ToFloat:
820 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
821 case EOpConvInt16ToDouble:
822 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
823 case EOpConvUint16ToFloat16:
824 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
825 case EOpConvUint16ToFloat:
826 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
827 case EOpConvUint16ToDouble:
828 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
830 case EOpConvIntToInt8:
831 newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
832 case EOpConvIntToInt16:
833 newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
834 case EOpConvIntToInt64:
835 newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
836 case EOpConvIntToUint8:
837 newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
838 case EOpConvIntToUint16:
839 newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
840 case EOpConvIntToUint64:
841 newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
843 case EOpConvUintToInt8:
844 newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
845 case EOpConvUintToInt16:
846 newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
847 case EOpConvUintToInt64:
848 newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
849 case EOpConvUintToUint8:
850 newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
851 case EOpConvUintToUint16:
852 newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
853 case EOpConvUintToUint64:
854 newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
855 case EOpConvIntToFloat16:
856 newConstArray[i].setDConst(unionArray[i].getIConst()); break;
857 case EOpConvUintToFloat16:
858 newConstArray[i].setDConst(unionArray[i].getUConst()); break;
859 case EOpConvInt64ToInt8:
860 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
861 case EOpConvInt64ToInt16:
862 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
863 case EOpConvInt64ToInt:
864 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
865 case EOpConvInt64ToUint8:
866 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
867 case EOpConvInt64ToUint16:
868 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
869 case EOpConvInt64ToUint:
870 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
871 case EOpConvInt64ToUint64:
872 newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
873 case EOpConvUint64ToInt8:
874 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
875 case EOpConvUint64ToInt16:
876 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
877 case EOpConvUint64ToInt:
878 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
879 case EOpConvUint64ToInt64:
880 newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
881 case EOpConvUint64ToUint8:
882 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
883 case EOpConvUint64ToUint16:
884 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
885 case EOpConvUint64ToUint:
886 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
887 case EOpConvInt64ToFloat16:
888 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
889 case EOpConvInt64ToFloat:
890 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
891 case EOpConvInt64ToDouble:
892 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
893 case EOpConvUint64ToFloat16:
894 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
895 case EOpConvUint64ToFloat:
896 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
897 case EOpConvUint64ToDouble:
898 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
899 case EOpConvFloat16ToInt8:
900 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
901 case EOpConvFloat16ToInt16:
902 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
903 case EOpConvFloat16ToInt:
904 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
905 case EOpConvFloat16ToInt64:
906 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
907 case EOpConvFloat16ToUint8:
908 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
909 case EOpConvFloat16ToUint16:
910 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
911 case EOpConvFloat16ToUint:
912 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
913 case EOpConvFloat16ToUint64:
914 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
915 case EOpConvFloat16ToFloat:
916 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
917 case EOpConvFloat16ToDouble:
918 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
919 case EOpConvFloatToInt8:
920 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
921 case EOpConvFloatToInt16:
922 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
923 case EOpConvFloatToInt64:
924 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
925 case EOpConvFloatToUint8:
926 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
927 case EOpConvFloatToUint16:
928 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
929 case EOpConvFloatToUint64:
930 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
931 case EOpConvFloatToFloat16:
932 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
933 case EOpConvDoubleToInt8:
934 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
935 case EOpConvDoubleToInt16:
936 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
937 case EOpConvDoubleToInt64:
938 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
939 case EOpConvDoubleToUint8:
940 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
941 case EOpConvDoubleToUint16:
942 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
943 case EOpConvDoubleToUint64:
944 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
945 case EOpConvDoubleToFloat16:
946 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
947 case EOpConvPtrToUint64:
948 case EOpConvUint64ToPtr:
949 case EOpConstructReference:
950 newConstArray[i].setU64Const(unionArray[i].getU64Const()); break;
953 // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
962 case EOpFloatBitsToInt:
963 case EOpFloatBitsToUint:
964 case EOpIntBitsToFloat:
965 case EOpUintBitsToFloat:
966 case EOpDoubleBitsToInt64:
967 case EOpDoubleBitsToUint64:
968 case EOpInt64BitsToDouble:
969 case EOpUint64BitsToDouble:
970 case EOpFloat16BitsToInt16:
971 case EOpFloat16BitsToUint16:
972 case EOpInt16BitsToFloat16:
973 case EOpUint16BitsToFloat16:
979 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
980 newNode->getWritableType().getQualifier().storage = EvqConst;
981 newNode->setLoc(getLoc());
987 // Do constant folding for an aggregate node that has all its children
988 // as constants and an operator that requires constant folding.
990 TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
992 if (aggrNode == nullptr)
995 if (! areAllChildConst(aggrNode))
998 if (aggrNode->isConstructor())
999 return foldConstructor(aggrNode);
1001 TIntermSequence& children = aggrNode->getSequence();
1003 // First, see if this is an operation to constant fold, kick out if not,
1004 // see what size the result is if so.
1006 bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results
1008 switch (aggrNode->getOp()) {
1017 case EOpGreaterThan:
1018 case EOpLessThanEqual:
1019 case EOpGreaterThanEqual:
1020 case EOpVectorEqual:
1021 case EOpVectorNotEqual:
1022 componentwise = true;
1023 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1028 case EOpFaceForward:
1029 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1035 case EOpOuterProduct:
1036 objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
1037 children[1]->getAsTyped()->getType().getVectorSize();
1040 componentwise = true;
1041 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1042 children[1]->getAsTyped()->getType().getVectorSize());
1045 componentwise = true;
1046 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1047 children[2]->getAsTyped()->getType().getVectorSize());
1052 TConstUnionArray newConstArray(objectSize);
1054 TVector<TConstUnionArray> childConstUnions;
1055 for (unsigned int arg = 0; arg < children.size(); ++arg)
1056 childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
1058 if (componentwise) {
1059 for (int comp = 0; comp < objectSize; comp++) {
1061 // some arguments are scalars instead of matching vectors; simulate a smear
1062 int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
1064 if (children.size() > 1)
1065 arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
1067 if (children.size() > 2)
1068 arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
1070 switch (aggrNode->getOp()) {
1072 newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1075 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1079 double arg0 = childConstUnions[0][arg0comp].getDConst();
1080 double arg1 = childConstUnions[1][arg1comp].getDConst();
1081 double result = arg0 - arg1 * floor(arg0 / arg1);
1082 newConstArray[comp].setDConst(result);
1086 switch(children[0]->getAsTyped()->getBasicType()) {
1090 newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1093 newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1096 newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1100 newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1103 newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1106 newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1109 newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1112 newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1115 newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1118 default: assert(false && "Default missing");
1122 switch(children[0]->getAsTyped()->getBasicType()) {
1126 newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1129 newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1132 newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1136 newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1139 newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1142 newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1145 newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1148 newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1151 newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1154 default: assert(false && "Default missing");
1158 switch(children[0]->getAsTyped()->getBasicType()) {
1162 newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
1163 childConstUnions[2][arg2comp].getDConst()));
1166 newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()),
1167 childConstUnions[2][arg2comp].getUConst()));
1171 newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
1172 childConstUnions[2][arg2comp].getI8Const()));
1175 newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
1176 childConstUnions[2][arg2comp].getU8Const()));
1179 newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
1180 childConstUnions[2][arg2comp].getI16Const()));
1183 newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
1184 childConstUnions[2][arg2comp].getU16Const()));
1187 newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
1188 childConstUnions[2][arg2comp].getIConst()));
1191 newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
1192 childConstUnions[2][arg2comp].getI64Const()));
1195 newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
1196 childConstUnions[2][arg2comp].getU64Const()));
1199 default: assert(false && "Default missing");
1203 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
1205 case EOpGreaterThan:
1206 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
1208 case EOpLessThanEqual:
1209 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
1211 case EOpGreaterThanEqual:
1212 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
1214 case EOpVectorEqual:
1215 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
1217 case EOpVectorNotEqual:
1218 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
1221 if (!children[0]->getAsTyped()->isFloatingDomain())
1223 if (children[2]->getAsTyped()->getBasicType() == EbtBool) {
1224 newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst()
1225 ? childConstUnions[1][arg1comp].getDConst()
1226 : childConstUnions[0][arg0comp].getDConst());
1228 newConstArray[comp].setDConst(
1229 childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
1230 childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst());
1234 newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
1238 double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
1239 (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
1244 newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
1252 // Non-componentwise...
1254 int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1257 switch (aggrNode->getOp()) {
1261 for (int comp = 0; comp < numComps; ++comp) {
1262 double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
1265 newConstArray[0].setDConst(sqrt(sum));
1269 newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
1272 newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
1273 newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
1274 newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
1276 case EOpFaceForward:
1277 // If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref).
1278 dot = childConstUnions[1].dot(childConstUnions[2]);
1279 for (int comp = 0; comp < numComps; ++comp) {
1281 newConstArray[comp] = childConstUnions[0][comp];
1283 newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
1287 // I - 2 * dot(N, I) * N: Arguments are (I, N).
1288 dot = childConstUnions[0].dot(childConstUnions[1]);
1290 for (int comp = 0; comp < numComps; ++comp)
1291 newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
1295 // Arguments are (I, N, eta).
1296 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
1300 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
1301 dot = childConstUnions[0].dot(childConstUnions[1]);
1302 double eta = childConstUnions[2][0].getDConst();
1303 double k = 1.0 - eta * eta * (1.0 - dot * dot);
1305 for (int comp = 0; comp < numComps; ++comp)
1306 newConstArray[comp].setDConst(0.0);
1308 for (int comp = 0; comp < numComps; ++comp)
1309 newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
1313 case EOpOuterProduct:
1315 int numRows = numComps;
1316 int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
1317 for (int row = 0; row < numRows; ++row)
1318 for (int col = 0; col < numCols; ++col)
1319 newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
1327 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
1328 newNode->getWritableType().getQualifier().storage = EvqConst;
1329 newNode->setLoc(aggrNode->getLoc());
1334 bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
1336 bool allConstant = true;
1338 // check if all the child nodes are constants so that they can be inserted into
1341 TIntermSequence& childSequenceVector = aggrNode->getSequence();
1342 for (TIntermSequence::iterator p = childSequenceVector.begin();
1343 p != childSequenceVector.end(); p++) {
1344 if (!(*p)->getAsTyped()->getAsConstantUnion())
1352 TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
1356 TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
1357 if (aggrNode->getSequence().size() == 1)
1358 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
1360 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
1365 return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
1369 // Constant folding of a bracket (array-style) dereference or struct-like dot
1370 // dereference. Can handle anything except a multi-character swizzle, though
1371 // all swizzles may go to foldSwizzle().
1373 TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
1375 TType dereferencedType(node->getType(), index);
1376 dereferencedType.getQualifier().storage = EvqConst;
1377 TIntermTyped* result = 0;
1378 int size = dereferencedType.computeNumComponents();
1380 // arrays, vectors, matrices, all use simple multiplicative math
1381 // while structures need to add up heterogeneous members
1383 if (node->getType().isCoopMat())
1385 else if (node->isArray() || ! node->isStruct())
1386 start = size * index;
1388 // it is a structure
1389 assert(node->isStruct());
1391 for (int i = 0; i < index; ++i)
1392 start += (*node->getType().getStruct())[i].type->computeNumComponents();
1395 result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
1400 result->setType(dereferencedType);
1406 // Make a constant vector node or constant scalar node, representing a given
1407 // constant vector and constant swizzle into it.
1409 TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
1411 const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
1412 TConstUnionArray constArray(selectors.size());
1414 for (int i = 0; i < selectors.size(); i++)
1415 constArray[i] = unionArray[selectors[i]];
1417 TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
1422 result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
1427 } // end namespace glslang