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