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