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-2020 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
193 case EbtInt:
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);
198 else
199 newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
200 break;
201
202 case EbtUint:
203 if (rightUnionArray[i] == 0u)
204 newConstArray[i].setUConst(0xFFFFFFFFu);
205 else
206 newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst());
207 break;
208
209 #ifndef GLSLANG_WEB
210 case EbtInt8:
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);
215 else
216 newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const());
217 break;
218
219 case EbtUint8:
220 if (rightUnionArray[i] == (unsigned char)0u)
221 newConstArray[i].setU8Const((unsigned char)0xFFu);
222 else
223 newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const());
224 break;
225
226 case EbtInt16:
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);
231 else
232 newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const());
233 break;
234
235 case EbtUint16:
236 if (rightUnionArray[i] == (unsigned short)0u)
237 newConstArray[i].setU16Const((unsigned short)0xFFFFu);
238 else
239 newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const());
240 break;
241
242 case EbtInt64:
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);
247 else
248 newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
249 break;
250
251 case EbtUint64:
252 if (rightUnionArray[i] == 0ull)
253 newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull);
254 else
255 newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const());
256 break;
257 default:
258 return 0;
259 #endif
260 }
261 }
262 break;
263
264 case EOpMatrixTimesVector:
265 for (int i = 0; i < getMatrixRows(); i++) {
266 double sum = 0.0f;
267 for (int j = 0; j < rightNode->getVectorSize(); j++) {
268 sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
269 }
270 newConstArray[i].setDConst(sum);
271 }
272
273 returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
274 break;
275
276 case EOpVectorTimesMatrix:
277 for (int i = 0; i < rightNode->getMatrixCols(); i++) {
278 double sum = 0.0f;
279 for (int j = 0; j < getVectorSize(); j++)
280 sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst();
281 newConstArray[i].setDConst(sum);
282 }
283
284 returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols()));
285 break;
286
287 case EOpMod:
288 for (int i = 0; i < newComps; i++) {
289 if (rightUnionArray[i] == 0)
290 newConstArray[i] = leftUnionArray[i];
291 else {
292 switch (getType().getBasicType()) {
293 case EbtInt:
294 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) {
295 newConstArray[i].setIConst(0);
296 break;
297 } else goto modulo_default;
298 #ifndef GLSLANG_WEB
299 case EbtInt64:
300 if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) {
301 newConstArray[i].setI64Const(0);
302 break;
303 } else goto modulo_default;
304 case EbtInt16:
305 if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) {
306 newConstArray[i].setIConst(0);
307 break;
308 } else goto modulo_default;
309 #endif
310 default:
311 modulo_default:
312 newConstArray[i] = leftUnionArray[i] % rightUnionArray[i];
313 }
314 }
315 }
316 break;
317
318 case EOpRightShift:
319 for (int i = 0; i < newComps; i++)
320 newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i];
321 break;
322
323 case EOpLeftShift:
324 for (int i = 0; i < newComps; i++)
325 newConstArray[i] = leftUnionArray[i] << rightUnionArray[i];
326 break;
327
328 case EOpAnd:
329 for (int i = 0; i < newComps; i++)
330 newConstArray[i] = leftUnionArray[i] & rightUnionArray[i];
331 break;
332 case EOpInclusiveOr:
333 for (int i = 0; i < newComps; i++)
334 newConstArray[i] = leftUnionArray[i] | rightUnionArray[i];
335 break;
336 case EOpExclusiveOr:
337 for (int i = 0; i < newComps; i++)
338 newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i];
339 break;
340
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];
344 break;
345
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];
349 break;
350
351 case EOpLogicalXor:
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");
356 }
357 }
358 break;
359
360 case EOpLessThan:
361 newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]);
362 returnType.shallowCopy(constBool);
363 break;
364 case EOpGreaterThan:
365 newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]);
366 returnType.shallowCopy(constBool);
367 break;
368 case EOpLessThanEqual:
369 newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0]));
370 returnType.shallowCopy(constBool);
371 break;
372 case EOpGreaterThanEqual:
373 newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0]));
374 returnType.shallowCopy(constBool);
375 break;
376 case EOpEqual:
377 newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray);
378 returnType.shallowCopy(constBool);
379 break;
380 case EOpNotEqual:
381 newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray);
382 returnType.shallowCopy(constBool);
383 break;
384
385 default:
386 return 0;
387 }
388
389 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
390 newNode->setLoc(getLoc());
391
392 return newNode;
393 }
394
395 //
396 // Do single unary node folding
397 //
398 // Returns a new node representing the result.
399 //
fold(TOperator op,const TType & returnType) const400 TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const
401 {
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.
405 int resultSize;
406 bool componentWise = true;
407
408 int objectSize = getType().computeNumComponents();
409 switch (op) {
410 case EOpDeterminant:
411 case EOpAny:
412 case EOpAll:
413 case EOpLength:
414 componentWise = false;
415 resultSize = 1;
416 break;
417
418 case EOpEmitStreamVertex:
419 case EOpEndStreamPrimitive:
420 // These don't fold
421 return nullptr;
422
423 case EOpPackSnorm2x16:
424 case EOpPackUnorm2x16:
425 case EOpPackHalf2x16:
426 componentWise = false;
427 resultSize = 1;
428 break;
429
430 case EOpUnpackSnorm2x16:
431 case EOpUnpackUnorm2x16:
432 case EOpUnpackHalf2x16:
433 componentWise = false;
434 resultSize = 2;
435 break;
436
437 case EOpPack16:
438 case EOpPack32:
439 case EOpPack64:
440 case EOpUnpack32:
441 case EOpUnpack16:
442 case EOpUnpack8:
443 case EOpNormalize:
444 componentWise = false;
445 resultSize = objectSize;
446 break;
447
448 default:
449 resultSize = objectSize;
450 break;
451 }
452
453 // Set up for processing
454 TConstUnionArray newConstArray(resultSize);
455 const TConstUnionArray& unionArray = getConstArray();
456
457 // Process non-component-wise operations
458 switch (op) {
459 case EOpLength:
460 case EOpNormalize:
461 {
462 double sum = 0;
463 for (int i = 0; i < objectSize; i++)
464 sum += unionArray[i].getDConst() * unionArray[i].getDConst();
465 double length = sqrt(sum);
466 if (op == EOpLength)
467 newConstArray[0].setDConst(length);
468 else {
469 for (int i = 0; i < objectSize; i++)
470 newConstArray[i].setDConst(unionArray[i].getDConst() / length);
471 }
472 break;
473 }
474
475 case EOpAny:
476 {
477 bool result = false;
478 for (int i = 0; i < objectSize; i++) {
479 if (unionArray[i].getBConst())
480 result = true;
481 }
482 newConstArray[0].setBConst(result);
483 break;
484 }
485 case EOpAll:
486 {
487 bool result = true;
488 for (int i = 0; i < objectSize; i++) {
489 if (! unionArray[i].getBConst())
490 result = false;
491 }
492 newConstArray[0].setBConst(result);
493 break;
494 }
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 nullptr;
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 EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
533 case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
534 #ifndef GLSLANG_WEB
535 case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
536 case EbtUint8: newConstArray[i].setU8Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU8Const()))); break;
537 case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break;
538 case EbtUint16:newConstArray[i].setU16Const(static_cast<unsigned int>(-static_cast<signed int>(unionArray[i].getU16Const()))); break;
539 case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break;
540 case EbtUint64: newConstArray[i].setU64Const(static_cast<unsigned long long>(-static_cast<long long>(unionArray[i].getU64Const()))); break;
541 #endif
542 default:
543 return nullptr;
544 }
545 break;
546 case EOpLogicalNot:
547 case EOpVectorLogicalNot:
548 switch (getType().getBasicType()) {
549 case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
550 default:
551 return nullptr;
552 }
553 break;
554 case EOpBitwiseNot:
555 newConstArray[i] = ~unionArray[i];
556 break;
557 case EOpRadians:
558 newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
559 break;
560 case EOpDegrees:
561 newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
562 break;
563 case EOpSin:
564 newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
565 break;
566 case EOpCos:
567 newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
568 break;
569 case EOpTan:
570 newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
571 break;
572 case EOpAsin:
573 newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
574 break;
575 case EOpAcos:
576 newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
577 break;
578 case EOpAtan:
579 newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
580 break;
581
582 case EOpDPdx:
583 case EOpDPdy:
584 case EOpFwidth:
585 case EOpDPdxFine:
586 case EOpDPdyFine:
587 case EOpFwidthFine:
588 case EOpDPdxCoarse:
589 case EOpDPdyCoarse:
590 case EOpFwidthCoarse:
591 // The derivatives are all mandated to create a constant 0.
592 newConstArray[i].setDConst(0.0);
593 break;
594
595 case EOpExp:
596 newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
597 break;
598 case EOpLog:
599 newConstArray[i].setDConst(log(unionArray[i].getDConst()));
600 break;
601 case EOpExp2:
602 {
603 const double inv_log2_e = 0.69314718055994530941723212145818;
604 newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
605 break;
606 }
607 case EOpLog2:
608 {
609 const double log2_e = 1.4426950408889634073599246810019;
610 newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
611 break;
612 }
613 case EOpSqrt:
614 newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
615 break;
616 case EOpInverseSqrt:
617 newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
618 break;
619
620 case EOpAbs:
621 if (unionArray[i].getType() == EbtDouble)
622 newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
623 else if (unionArray[i].getType() == EbtInt)
624 newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
625 else
626 newConstArray[i] = unionArray[i];
627 break;
628 case EOpSign:
629 #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
630 if (unionArray[i].getType() == EbtDouble)
631 newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
632 else
633 newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
634 break;
635 case EOpFloor:
636 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
637 break;
638 case EOpTrunc:
639 if (unionArray[i].getDConst() > 0)
640 newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
641 else
642 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
643 break;
644 case EOpRound:
645 newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
646 break;
647 case EOpRoundEven:
648 {
649 double flr = floor(unionArray[i].getDConst());
650 bool even = flr / 2.0 == floor(flr / 2.0);
651 double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
652 newConstArray[i].setDConst(rounded);
653 break;
654 }
655 case EOpCeil:
656 newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
657 break;
658 case EOpFract:
659 {
660 double x = unionArray[i].getDConst();
661 newConstArray[i].setDConst(x - floor(x));
662 break;
663 }
664
665 case EOpIsNan:
666 {
667 newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
668 break;
669 }
670 case EOpIsInf:
671 {
672 newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
673 break;
674 }
675
676 case EOpConvIntToBool:
677 newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
678 case EOpConvUintToBool:
679 newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
680 case EOpConvBoolToInt:
681 newConstArray[i].setIConst(unionArray[i].getBConst()); break;
682 case EOpConvBoolToUint:
683 newConstArray[i].setUConst(unionArray[i].getBConst()); break;
684 case EOpConvIntToUint:
685 newConstArray[i].setUConst(unionArray[i].getIConst()); break;
686 case EOpConvUintToInt:
687 newConstArray[i].setIConst(unionArray[i].getUConst()); break;
688
689 case EOpConvFloatToBool:
690 case EOpConvDoubleToBool:
691 newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
692
693 case EOpConvBoolToFloat:
694 case EOpConvBoolToDouble:
695 newConstArray[i].setDConst(unionArray[i].getBConst()); break;
696
697 case EOpConvIntToFloat:
698 case EOpConvIntToDouble:
699 newConstArray[i].setDConst(unionArray[i].getIConst()); break;
700
701 case EOpConvUintToFloat:
702 case EOpConvUintToDouble:
703 newConstArray[i].setDConst(unionArray[i].getUConst()); break;
704
705 case EOpConvDoubleToFloat:
706 case EOpConvFloatToDouble:
707 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
708
709 case EOpConvFloatToUint:
710 case EOpConvDoubleToUint:
711 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
712
713 case EOpConvFloatToInt:
714 case EOpConvDoubleToInt:
715 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
716
717 #ifndef GLSLANG_WEB
718 case EOpConvInt8ToBool:
719 newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
720 case EOpConvUint8ToBool:
721 newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
722 case EOpConvInt16ToBool:
723 newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
724 case EOpConvUint16ToBool:
725 newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
726 case EOpConvInt64ToBool:
727 newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
728 case EOpConvUint64ToBool:
729 newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
730 case EOpConvFloat16ToBool:
731 newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
732
733 case EOpConvBoolToInt8:
734 newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
735 case EOpConvBoolToUint8:
736 newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
737 case EOpConvBoolToInt16:
738 newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
739 case EOpConvBoolToUint16:
740 newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
741 case EOpConvBoolToInt64:
742 newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
743 case EOpConvBoolToUint64:
744 newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
745 case EOpConvBoolToFloat16:
746 newConstArray[i].setDConst(unionArray[i].getBConst()); break;
747
748 case EOpConvInt8ToInt16:
749 newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
750 case EOpConvInt8ToInt:
751 newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
752 case EOpConvInt8ToInt64:
753 newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
754 case EOpConvInt8ToUint8:
755 newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
756 case EOpConvInt8ToUint16:
757 newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
758 case EOpConvInt8ToUint:
759 newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
760 case EOpConvInt8ToUint64:
761 newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
762 case EOpConvUint8ToInt8:
763 newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
764 case EOpConvUint8ToInt16:
765 newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
766 case EOpConvUint8ToInt:
767 newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
768 case EOpConvUint8ToInt64:
769 newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
770 case EOpConvUint8ToUint16:
771 newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
772 case EOpConvUint8ToUint:
773 newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
774 case EOpConvUint8ToUint64:
775 newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
776 case EOpConvInt8ToFloat16:
777 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
778 case EOpConvInt8ToFloat:
779 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
780 case EOpConvInt8ToDouble:
781 newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
782 case EOpConvUint8ToFloat16:
783 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
784 case EOpConvUint8ToFloat:
785 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
786 case EOpConvUint8ToDouble:
787 newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
788
789 case EOpConvInt16ToInt8:
790 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
791 case EOpConvInt16ToInt:
792 newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
793 case EOpConvInt16ToInt64:
794 newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
795 case EOpConvInt16ToUint8:
796 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
797 case EOpConvInt16ToUint16:
798 newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
799 case EOpConvInt16ToUint:
800 newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
801 case EOpConvInt16ToUint64:
802 newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
803 case EOpConvUint16ToInt8:
804 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
805 case EOpConvUint16ToInt16:
806 newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
807 case EOpConvUint16ToInt:
808 newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
809 case EOpConvUint16ToInt64:
810 newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
811 case EOpConvUint16ToUint8:
812 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
813
814 case EOpConvUint16ToUint:
815 newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
816 case EOpConvUint16ToUint64:
817 newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
818 case EOpConvInt16ToFloat16:
819 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
820 case EOpConvInt16ToFloat:
821 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
822 case EOpConvInt16ToDouble:
823 newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
824 case EOpConvUint16ToFloat16:
825 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
826 case EOpConvUint16ToFloat:
827 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
828 case EOpConvUint16ToDouble:
829 newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
830
831 case EOpConvIntToInt8:
832 newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
833 case EOpConvIntToInt16:
834 newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
835 case EOpConvIntToInt64:
836 newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
837 case EOpConvIntToUint8:
838 newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
839 case EOpConvIntToUint16:
840 newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
841 case EOpConvIntToUint64:
842 newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
843
844 case EOpConvUintToInt8:
845 newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
846 case EOpConvUintToInt16:
847 newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
848 case EOpConvUintToInt64:
849 newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
850 case EOpConvUintToUint8:
851 newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
852 case EOpConvUintToUint16:
853 newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
854 case EOpConvUintToUint64:
855 newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
856 case EOpConvIntToFloat16:
857 newConstArray[i].setDConst(unionArray[i].getIConst()); break;
858 case EOpConvUintToFloat16:
859 newConstArray[i].setDConst(unionArray[i].getUConst()); break;
860 case EOpConvInt64ToInt8:
861 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
862 case EOpConvInt64ToInt16:
863 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
864 case EOpConvInt64ToInt:
865 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
866 case EOpConvInt64ToUint8:
867 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
868 case EOpConvInt64ToUint16:
869 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
870 case EOpConvInt64ToUint:
871 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
872 case EOpConvInt64ToUint64:
873 newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
874 case EOpConvUint64ToInt8:
875 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
876 case EOpConvUint64ToInt16:
877 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
878 case EOpConvUint64ToInt:
879 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
880 case EOpConvUint64ToInt64:
881 newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
882 case EOpConvUint64ToUint8:
883 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
884 case EOpConvUint64ToUint16:
885 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
886 case EOpConvUint64ToUint:
887 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
888 case EOpConvInt64ToFloat16:
889 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
890 case EOpConvInt64ToFloat:
891 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
892 case EOpConvInt64ToDouble:
893 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
894 case EOpConvUint64ToFloat16:
895 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
896 case EOpConvUint64ToFloat:
897 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
898 case EOpConvUint64ToDouble:
899 newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
900 case EOpConvFloat16ToInt8:
901 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
902 case EOpConvFloat16ToInt16:
903 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
904 case EOpConvFloat16ToInt:
905 newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
906 case EOpConvFloat16ToInt64:
907 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
908 case EOpConvFloat16ToUint8:
909 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
910 case EOpConvFloat16ToUint16:
911 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
912 case EOpConvFloat16ToUint:
913 newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
914 case EOpConvFloat16ToUint64:
915 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
916 case EOpConvFloat16ToFloat:
917 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
918 case EOpConvFloat16ToDouble:
919 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
920 case EOpConvFloatToInt8:
921 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
922 case EOpConvFloatToInt16:
923 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
924 case EOpConvFloatToInt64:
925 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
926 case EOpConvFloatToUint8:
927 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
928 case EOpConvFloatToUint16:
929 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
930 case EOpConvFloatToUint64:
931 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
932 case EOpConvFloatToFloat16:
933 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
934 case EOpConvDoubleToInt8:
935 newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
936 case EOpConvDoubleToInt16:
937 newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
938 case EOpConvDoubleToInt64:
939 newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
940 case EOpConvDoubleToUint8:
941 newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
942 case EOpConvDoubleToUint16:
943 newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
944 case EOpConvDoubleToUint64:
945 newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
946 case EOpConvDoubleToFloat16:
947 newConstArray[i].setDConst(unionArray[i].getDConst()); break;
948 case EOpConvPtrToUint64:
949 case EOpConvUint64ToPtr:
950 case EOpConstructReference:
951 newConstArray[i].setU64Const(unionArray[i].getU64Const()); break;
952 #endif
953
954 // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
955
956 case EOpSinh:
957 case EOpCosh:
958 case EOpTanh:
959 case EOpAsinh:
960 case EOpAcosh:
961 case EOpAtanh:
962
963 case EOpFloatBitsToInt:
964 case EOpFloatBitsToUint:
965 case EOpIntBitsToFloat:
966 case EOpUintBitsToFloat:
967 case EOpDoubleBitsToInt64:
968 case EOpDoubleBitsToUint64:
969 case EOpInt64BitsToDouble:
970 case EOpUint64BitsToDouble:
971 case EOpFloat16BitsToInt16:
972 case EOpFloat16BitsToUint16:
973 case EOpInt16BitsToFloat16:
974 case EOpUint16BitsToFloat16:
975 default:
976 return nullptr;
977 }
978 }
979
980 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
981 newNode->getWritableType().getQualifier().storage = EvqConst;
982 newNode->setLoc(getLoc());
983
984 return newNode;
985 }
986
987 //
988 // Do constant folding for an aggregate node that has all its children
989 // as constants and an operator that requires constant folding.
990 //
fold(TIntermAggregate * aggrNode)991 TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
992 {
993 if (aggrNode == nullptr)
994 return aggrNode;
995
996 if (! areAllChildConst(aggrNode))
997 return aggrNode;
998
999 if (aggrNode->isConstructor())
1000 return foldConstructor(aggrNode);
1001
1002 TIntermSequence& children = aggrNode->getSequence();
1003
1004 // First, see if this is an operation to constant fold, kick out if not,
1005 // see what size the result is if so.
1006
1007 bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results
1008 int objectSize;
1009 switch (aggrNode->getOp()) {
1010 case EOpAtan:
1011 case EOpPow:
1012 case EOpMin:
1013 case EOpMax:
1014 case EOpMix:
1015 case EOpMod:
1016 case EOpClamp:
1017 case EOpLessThan:
1018 case EOpGreaterThan:
1019 case EOpLessThanEqual:
1020 case EOpGreaterThanEqual:
1021 case EOpVectorEqual:
1022 case EOpVectorNotEqual:
1023 componentwise = true;
1024 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1025 break;
1026 case EOpCross:
1027 case EOpReflect:
1028 case EOpRefract:
1029 case EOpFaceForward:
1030 objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1031 break;
1032 case EOpDistance:
1033 case EOpDot:
1034 objectSize = 1;
1035 break;
1036 case EOpOuterProduct:
1037 objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
1038 children[1]->getAsTyped()->getType().getVectorSize();
1039 break;
1040 case EOpStep:
1041 componentwise = true;
1042 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1043 children[1]->getAsTyped()->getType().getVectorSize());
1044 break;
1045 case EOpSmoothStep:
1046 componentwise = true;
1047 objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
1048 children[2]->getAsTyped()->getType().getVectorSize());
1049 break;
1050 default:
1051 return aggrNode;
1052 }
1053 TConstUnionArray newConstArray(objectSize);
1054
1055 TVector<TConstUnionArray> childConstUnions;
1056 for (unsigned int arg = 0; arg < children.size(); ++arg)
1057 childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());
1058
1059 if (componentwise) {
1060 for (int comp = 0; comp < objectSize; comp++) {
1061
1062 // some arguments are scalars instead of matching vectors; simulate a smear
1063 int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
1064 int arg1comp = 0;
1065 if (children.size() > 1)
1066 arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
1067 int arg2comp = 0;
1068 if (children.size() > 2)
1069 arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);
1070
1071 switch (aggrNode->getOp()) {
1072 case EOpAtan:
1073 newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1074 break;
1075 case EOpPow:
1076 newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1077 break;
1078 case EOpMod:
1079 {
1080 double arg0 = childConstUnions[0][arg0comp].getDConst();
1081 double arg1 = childConstUnions[1][arg1comp].getDConst();
1082 double result = arg0 - arg1 * floor(arg0 / arg1);
1083 newConstArray[comp].setDConst(result);
1084 break;
1085 }
1086 case EOpMin:
1087 switch(children[0]->getAsTyped()->getBasicType()) {
1088 case EbtFloat16:
1089 case EbtFloat:
1090 case EbtDouble:
1091 newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1092 break;
1093 case EbtInt:
1094 newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1095 break;
1096 case EbtUint:
1097 newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1098 break;
1099 #ifndef GLSLANG_WEB
1100 case EbtInt8:
1101 newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1102 break;
1103 case EbtUint8:
1104 newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1105 break;
1106 case EbtInt16:
1107 newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1108 break;
1109 case EbtUint16:
1110 newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1111 break;
1112 case EbtInt64:
1113 newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1114 break;
1115 case EbtUint64:
1116 newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1117 break;
1118 #endif
1119 default: assert(false && "Default missing");
1120 }
1121 break;
1122 case EOpMax:
1123 switch(children[0]->getAsTyped()->getBasicType()) {
1124 case EbtFloat16:
1125 case EbtFloat:
1126 case EbtDouble:
1127 newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
1128 break;
1129 case EbtInt:
1130 newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
1131 break;
1132 case EbtUint:
1133 newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
1134 break;
1135 #ifndef GLSLANG_WEB
1136 case EbtInt8:
1137 newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()));
1138 break;
1139 case EbtUint8:
1140 newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()));
1141 break;
1142 case EbtInt16:
1143 newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()));
1144 break;
1145 case EbtUint16:
1146 newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()));
1147 break;
1148 case EbtInt64:
1149 newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()));
1150 break;
1151 case EbtUint64:
1152 newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
1153 break;
1154 #endif
1155 default: assert(false && "Default missing");
1156 }
1157 break;
1158 case EOpClamp:
1159 switch(children[0]->getAsTyped()->getBasicType()) {
1160 case EbtFloat16:
1161 case EbtFloat:
1162 case EbtDouble:
1163 newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()),
1164 childConstUnions[2][arg2comp].getDConst()));
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 #ifndef GLSLANG_WEB
1171 case EbtInt8:
1172 newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()),
1173 childConstUnions[2][arg2comp].getI8Const()));
1174 break;
1175 case EbtUint8:
1176 newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()),
1177 childConstUnions[2][arg2comp].getU8Const()));
1178 break;
1179 case EbtInt16:
1180 newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()),
1181 childConstUnions[2][arg2comp].getI16Const()));
1182 break;
1183 case EbtUint16:
1184 newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()),
1185 childConstUnions[2][arg2comp].getU16Const()));
1186 break;
1187 case EbtInt:
1188 newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()),
1189 childConstUnions[2][arg2comp].getIConst()));
1190 break;
1191 case EbtInt64:
1192 newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()),
1193 childConstUnions[2][arg2comp].getI64Const()));
1194 break;
1195 case EbtUint64:
1196 newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
1197 childConstUnions[2][arg2comp].getU64Const()));
1198 break;
1199 #endif
1200 default: assert(false && "Default missing");
1201 }
1202 break;
1203 case EOpLessThan:
1204 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
1205 break;
1206 case EOpGreaterThan:
1207 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
1208 break;
1209 case EOpLessThanEqual:
1210 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
1211 break;
1212 case EOpGreaterThanEqual:
1213 newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
1214 break;
1215 case EOpVectorEqual:
1216 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
1217 break;
1218 case EOpVectorNotEqual:
1219 newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
1220 break;
1221 case EOpMix:
1222 if (!children[0]->getAsTyped()->isFloatingDomain())
1223 return aggrNode;
1224 if (children[2]->getAsTyped()->getBasicType() == EbtBool) {
1225 newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst()
1226 ? childConstUnions[1][arg1comp].getDConst()
1227 : childConstUnions[0][arg0comp].getDConst());
1228 } else {
1229 newConstArray[comp].setDConst(
1230 childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
1231 childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst());
1232 }
1233 break;
1234 case EOpStep:
1235 newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
1236 break;
1237 case EOpSmoothStep:
1238 {
1239 double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) /
1240 (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
1241 if (t < 0.0)
1242 t = 0.0;
1243 if (t > 1.0)
1244 t = 1.0;
1245 newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
1246 break;
1247 }
1248 default:
1249 return aggrNode;
1250 }
1251 }
1252 } else {
1253 // Non-componentwise...
1254
1255 int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
1256 double dot;
1257
1258 switch (aggrNode->getOp()) {
1259 case EOpDistance:
1260 {
1261 double sum = 0.0;
1262 for (int comp = 0; comp < numComps; ++comp) {
1263 double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
1264 sum += diff * diff;
1265 }
1266 newConstArray[0].setDConst(sqrt(sum));
1267 break;
1268 }
1269 case EOpDot:
1270 newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
1271 break;
1272 case EOpCross:
1273 newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
1274 newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
1275 newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
1276 break;
1277 case EOpFaceForward:
1278 // If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref).
1279 dot = childConstUnions[1].dot(childConstUnions[2]);
1280 for (int comp = 0; comp < numComps; ++comp) {
1281 if (dot < 0.0)
1282 newConstArray[comp] = childConstUnions[0][comp];
1283 else
1284 newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
1285 }
1286 break;
1287 case EOpReflect:
1288 // I - 2 * dot(N, I) * N: Arguments are (I, N).
1289 dot = childConstUnions[0].dot(childConstUnions[1]);
1290 dot *= 2.0;
1291 for (int comp = 0; comp < numComps; ++comp)
1292 newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
1293 break;
1294 case EOpRefract:
1295 {
1296 // Arguments are (I, N, eta).
1297 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
1298 // if (k < 0.0)
1299 // return dvec(0.0)
1300 // else
1301 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
1302 dot = childConstUnions[0].dot(childConstUnions[1]);
1303 double eta = childConstUnions[2][0].getDConst();
1304 double k = 1.0 - eta * eta * (1.0 - dot * dot);
1305 if (k < 0.0) {
1306 for (int comp = 0; comp < numComps; ++comp)
1307 newConstArray[comp].setDConst(0.0);
1308 } else {
1309 for (int comp = 0; comp < numComps; ++comp)
1310 newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
1311 }
1312 break;
1313 }
1314 case EOpOuterProduct:
1315 {
1316 int numRows = numComps;
1317 int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
1318 for (int row = 0; row < numRows; ++row)
1319 for (int col = 0; col < numCols; ++col)
1320 newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
1321 break;
1322 }
1323 default:
1324 return aggrNode;
1325 }
1326 }
1327
1328 TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
1329 newNode->getWritableType().getQualifier().storage = EvqConst;
1330 newNode->setLoc(aggrNode->getLoc());
1331
1332 return newNode;
1333 }
1334
areAllChildConst(TIntermAggregate * aggrNode)1335 bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode)
1336 {
1337 bool allConstant = true;
1338
1339 // check if all the child nodes are constants so that they can be inserted into
1340 // the parent node
1341 if (aggrNode) {
1342 TIntermSequence& childSequenceVector = aggrNode->getSequence();
1343 for (TIntermSequence::iterator p = childSequenceVector.begin();
1344 p != childSequenceVector.end(); p++) {
1345 if (!(*p)->getAsTyped()->getAsConstantUnion())
1346 return false;
1347 }
1348 }
1349
1350 return allConstant;
1351 }
1352
foldConstructor(TIntermAggregate * aggrNode)1353 TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
1354 {
1355 bool error = false;
1356
1357 TConstUnionArray unionArray(aggrNode->getType().computeNumComponents());
1358 if (aggrNode->getSequence().size() == 1)
1359 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
1360 else
1361 error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
1362
1363 if (error)
1364 return aggrNode;
1365
1366 return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc());
1367 }
1368
1369 //
1370 // Constant folding of a bracket (array-style) dereference or struct-like dot
1371 // dereference. Can handle anything except a multi-character swizzle, though
1372 // all swizzles may go to foldSwizzle().
1373 //
foldDereference(TIntermTyped * node,int index,const TSourceLoc & loc)1374 TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc)
1375 {
1376 TType dereferencedType(node->getType(), index);
1377 dereferencedType.getQualifier().storage = EvqConst;
1378 TIntermTyped* result = 0;
1379 int size = dereferencedType.computeNumComponents();
1380
1381 // arrays, vectors, matrices, all use simple multiplicative math
1382 // while structures need to add up heterogeneous members
1383 int start;
1384 if (node->getType().isCoopMat())
1385 start = 0;
1386 else if (node->isArray() || ! node->isStruct())
1387 start = size * index;
1388 else {
1389 // it is a structure
1390 assert(node->isStruct());
1391 start = 0;
1392 for (int i = 0; i < index; ++i)
1393 start += (*node->getType().getStruct())[i].type->computeNumComponents();
1394 }
1395
1396 result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc);
1397
1398 if (result == 0)
1399 result = node;
1400 else
1401 result->setType(dereferencedType);
1402
1403 return result;
1404 }
1405
1406 //
1407 // Make a constant vector node or constant scalar node, representing a given
1408 // constant vector and constant swizzle into it.
1409 //
foldSwizzle(TIntermTyped * node,TSwizzleSelectors<TVectorSelector> & selectors,const TSourceLoc & loc)1410 TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors<TVectorSelector>& selectors, const TSourceLoc& loc)
1411 {
1412 const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
1413 TConstUnionArray constArray(selectors.size());
1414
1415 for (int i = 0; i < selectors.size(); i++)
1416 constArray[i] = unionArray[selectors[i]];
1417
1418 TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);
1419
1420 if (result == 0)
1421 result = node;
1422 else
1423 result->setType(TType(node->getBasicType(), EvqConst, selectors.size()));
1424
1425 return result;
1426 }
1427
1428 } // end namespace glslang
1429