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