blob: 195f80756668b2182c9803b2918e9a6e8a9bf86f [file] [log] [blame]
Jamie Madillb1a85f42014-08-19 15:23:24 -04001//
2// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Build the intermediate representation.
9//
10
11#include <float.h>
12#include <limits.h>
Arun Patole9dea48f2015-04-02 11:45:09 +053013#include <math.h>
Arun Patole97dc22e2015-04-06 17:35:38 +053014#include <stdlib.h>
Jamie Madillb1a85f42014-08-19 15:23:24 -040015#include <algorithm>
Arun Patole274f0702015-05-05 13:33:30 +053016#include <vector>
Jamie Madillb1a85f42014-08-19 15:23:24 -040017
Arun Patole274f0702015-05-05 13:33:30 +053018#include "common/mathutil.h"
Arun Patole7fa33552015-06-10 15:15:18 +053019#include "common/matrix_utils.h"
Olli Etuaho3fdec912016-08-18 15:08:06 +030020#include "compiler/translator/Diagnostics.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040021#include "compiler/translator/HashNames.h"
22#include "compiler/translator/IntermNode.h"
23#include "compiler/translator/SymbolTable.h"
Corentin Wallez509e4562016-08-25 14:55:44 -040024#include "compiler/translator/util.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040025
26namespace
27{
28
Arun Patole9dea48f2015-04-02 11:45:09 +053029const float kPi = 3.14159265358979323846f;
30const float kDegreesToRadiansMultiplier = kPi / 180.0f;
31const float kRadiansToDegreesMultiplier = 180.0f / kPi;
32
Jamie Madillb1a85f42014-08-19 15:23:24 -040033TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
34{
35 return left > right ? left : right;
36}
37
Arun Patole274f0702015-05-05 13:33:30 +053038TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
39{
40 TConstantUnion *constUnion = new TConstantUnion[size];
41 for (unsigned int i = 0; i < size; ++i)
42 constUnion[i] = constant;
43
44 return constUnion;
45}
46
Olli Etuahof119a262016-08-19 15:54:22 +030047void UndefinedConstantFoldingError(const TSourceLoc &loc,
48 TOperator op,
49 TBasicType basicType,
50 TDiagnostics *diagnostics,
51 TConstantUnion *result)
Arun Patolebf790422015-05-18 17:53:04 +053052{
Olli Etuahof119a262016-08-19 15:54:22 +030053 diagnostics->warning(loc, "operation result is undefined for the values passed in",
54 GetOperatorString(op), "");
Arun Patolebf790422015-05-18 17:53:04 +053055
56 switch (basicType)
57 {
58 case EbtFloat :
59 result->setFConst(0.0f);
60 break;
61 case EbtInt:
62 result->setIConst(0);
63 break;
64 case EbtUInt:
65 result->setUConst(0u);
66 break;
67 case EbtBool:
68 result->setBConst(false);
69 break;
70 default:
71 break;
72 }
73}
74
Olli Etuaho5c0e0232015-11-11 15:55:59 +020075float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053076{
77 float result = 0.0f;
78 for (size_t i = 0; i < paramArraySize; i++)
79 {
80 float f = paramArray[i].getFConst();
81 result += f * f;
82 }
83 return sqrtf(result);
84}
85
Olli Etuaho5c0e0232015-11-11 15:55:59 +020086float VectorDotProduct(const TConstantUnion *paramArray1,
87 const TConstantUnion *paramArray2,
88 size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053089{
90 float result = 0.0f;
91 for (size_t i = 0; i < paramArraySize; i++)
92 result += paramArray1[i].getFConst() * paramArray2[i].getFConst();
93 return result;
94}
95
Olli Etuaho7c3848e2015-11-04 13:19:17 +020096TIntermTyped *CreateFoldedNode(TConstantUnion *constArray,
97 const TIntermTyped *originalNode,
98 TQualifier qualifier)
Olli Etuahob43846e2015-06-02 18:18:57 +030099{
100 if (constArray == nullptr)
101 {
102 return nullptr;
103 }
104 TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200105 folded->getTypePointer()->setQualifier(qualifier);
Olli Etuahob43846e2015-06-02 18:18:57 +0300106 folded->setLine(originalNode->getLine());
107 return folded;
108}
109
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200110angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
111 const unsigned int &rows,
112 const unsigned int &cols)
Arun Patole7fa33552015-06-10 15:15:18 +0530113{
114 std::vector<float> elements;
115 for (size_t i = 0; i < rows * cols; i++)
116 elements.push_back(paramArray[i].getFConst());
117 // Transpose is used since the Matrix constructor expects arguments in row-major order,
Olli Etuahod5da5052016-08-29 13:16:55 +0300118 // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
119 // so that the created matrix will have the expected dimensions after the transpose.
120 return angle::Matrix<float>(elements, cols, rows).transpose();
Arun Patole7fa33552015-06-10 15:15:18 +0530121}
122
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200123angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
Arun Patole7fa33552015-06-10 15:15:18 +0530124{
125 std::vector<float> elements;
126 for (size_t i = 0; i < size * size; i++)
127 elements.push_back(paramArray[i].getFConst());
128 // Transpose is used since the Matrix constructor expects arguments in row-major order,
129 // whereas the paramArray is in column-major order.
130 return angle::Matrix<float>(elements, size).transpose();
131}
132
133void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray)
134{
135 // Transpose is used since the input Matrix is in row-major order,
136 // whereas the actual result should be in column-major order.
137 angle::Matrix<float> result = m.transpose();
138 std::vector<float> resultElements = result.elements();
139 for (size_t i = 0; i < resultElements.size(); i++)
140 resultArray[i].setFConst(resultElements[i]);
141}
142
Jamie Madillb1a85f42014-08-19 15:23:24 -0400143} // namespace anonymous
144
145
146////////////////////////////////////////////////////////////////
147//
148// Member functions of the nodes used for building the tree.
149//
150////////////////////////////////////////////////////////////////
151
Olli Etuahod2a67b92014-10-21 16:42:57 +0300152void TIntermTyped::setTypePreservePrecision(const TType &t)
153{
154 TPrecision precision = getPrecision();
155 mType = t;
156 ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
157 mType.setPrecision(precision);
158}
159
Jamie Madillb1a85f42014-08-19 15:23:24 -0400160#define REPLACE_IF_IS(node, type, original, replacement) \
161 if (node == original) { \
162 node = static_cast<type *>(replacement); \
163 return true; \
164 }
165
166bool TIntermLoop::replaceChildNode(
167 TIntermNode *original, TIntermNode *replacement)
168{
Olli Etuaho3cbb27a2016-07-14 11:55:48 +0300169 ASSERT(original != nullptr); // This risks replacing multiple children.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400170 REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
171 REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
172 REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
Olli Etuaho3fed4302015-11-02 12:26:02 +0200173 REPLACE_IF_IS(mBody, TIntermAggregate, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400174 return false;
175}
176
Jamie Madillb1a85f42014-08-19 15:23:24 -0400177bool TIntermBranch::replaceChildNode(
178 TIntermNode *original, TIntermNode *replacement)
179{
180 REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
181 return false;
182}
183
Jamie Madillb1a85f42014-08-19 15:23:24 -0400184bool TIntermBinary::replaceChildNode(
185 TIntermNode *original, TIntermNode *replacement)
186{
187 REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
188 REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
189 return false;
190}
191
Jamie Madillb1a85f42014-08-19 15:23:24 -0400192bool TIntermUnary::replaceChildNode(
193 TIntermNode *original, TIntermNode *replacement)
194{
195 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
196 return false;
197}
198
Jamie Madillb1a85f42014-08-19 15:23:24 -0400199bool TIntermAggregate::replaceChildNode(
200 TIntermNode *original, TIntermNode *replacement)
201{
202 for (size_t ii = 0; ii < mSequence.size(); ++ii)
203 {
204 REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement);
205 }
206 return false;
207}
208
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300209bool TIntermAggregate::replaceChildNodeWithMultiple(TIntermNode *original, TIntermSequence replacements)
210{
211 for (auto it = mSequence.begin(); it < mSequence.end(); ++it)
212 {
213 if (*it == original)
214 {
215 it = mSequence.erase(it);
Olli Etuaho8fee0ab2015-04-23 14:52:46 +0300216 mSequence.insert(it, replacements.begin(), replacements.end());
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300217 return true;
218 }
219 }
220 return false;
221}
222
Olli Etuahoa6f22092015-05-08 18:31:10 +0300223bool TIntermAggregate::insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions)
224{
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300225 if (position > mSequence.size())
Olli Etuahoa6f22092015-05-08 18:31:10 +0300226 {
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300227 return false;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300228 }
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300229 auto it = mSequence.begin() + position;
230 mSequence.insert(it, insertions.begin(), insertions.end());
231 return true;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300232}
233
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200234bool TIntermAggregate::areChildrenConstQualified()
235{
236 for (TIntermNode *&child : mSequence)
237 {
238 TIntermTyped *typed = child->getAsTyped();
239 if (typed && typed->getQualifier() != EvqConst)
240 {
241 return false;
242 }
243 }
244 return true;
245}
246
Olli Etuahod2a67b92014-10-21 16:42:57 +0300247void TIntermAggregate::setPrecisionFromChildren()
248{
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300249 mGotPrecisionFromChildren = true;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300250 if (getBasicType() == EbtBool)
251 {
252 mType.setPrecision(EbpUndefined);
253 return;
254 }
255
256 TPrecision precision = EbpUndefined;
257 TIntermSequence::iterator childIter = mSequence.begin();
258 while (childIter != mSequence.end())
259 {
260 TIntermTyped *typed = (*childIter)->getAsTyped();
261 if (typed)
262 precision = GetHigherPrecision(typed->getPrecision(), precision);
263 ++childIter;
264 }
265 mType.setPrecision(precision);
266}
267
268void TIntermAggregate::setBuiltInFunctionPrecision()
269{
270 // All built-ins returning bool should be handled as ops, not functions.
271 ASSERT(getBasicType() != EbtBool);
272
273 TPrecision precision = EbpUndefined;
274 TIntermSequence::iterator childIter = mSequence.begin();
275 while (childIter != mSequence.end())
276 {
277 TIntermTyped *typed = (*childIter)->getAsTyped();
278 // ESSL spec section 8: texture functions get their precision from the sampler.
279 if (typed && IsSampler(typed->getBasicType()))
280 {
281 precision = typed->getPrecision();
282 break;
283 }
284 ++childIter;
285 }
286 // ESSL 3.0 spec section 8: textureSize always gets highp precision.
287 // All other functions that take a sampler are assumed to be texture functions.
Olli Etuaho59f9a642015-08-06 20:38:26 +0300288 if (mName.getString().find("textureSize") == 0)
Olli Etuahod2a67b92014-10-21 16:42:57 +0300289 mType.setPrecision(EbpHigh);
290 else
291 mType.setPrecision(precision);
292}
293
Jamie Madillb1a85f42014-08-19 15:23:24 -0400294bool TIntermSelection::replaceChildNode(
295 TIntermNode *original, TIntermNode *replacement)
296{
297 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
298 REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement);
299 REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement);
300 return false;
301}
302
Olli Etuahoa3a36662015-02-17 13:46:51 +0200303bool TIntermSwitch::replaceChildNode(
304 TIntermNode *original, TIntermNode *replacement)
305{
306 REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
307 REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement);
308 return false;
309}
310
311bool TIntermCase::replaceChildNode(
312 TIntermNode *original, TIntermNode *replacement)
313{
314 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
315 return false;
316}
317
Olli Etuahod7a25242015-08-18 13:49:45 +0300318TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType)
319{
320 // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that
321 // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy.
322 // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped.
323 mLine = node.mLine;
324}
325
Olli Etuahod4f4c112016-04-15 15:11:24 +0300326bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
327{
328 TIntermAggregate *constructor = getAsAggregate();
329 if (!constructor || !constructor->isConstructor())
330 {
331 return false;
332 }
333 for (TIntermNode *&node : *constructor->getSequence())
334 {
335 if (!node->getAsConstantUnion())
336 return false;
337 }
338 return true;
339}
340
Corentin Wallez509e4562016-08-25 14:55:44 -0400341// static
342TIntermTyped *TIntermTyped::CreateIndexNode(int index)
343{
344 TConstantUnion *u = new TConstantUnion[1];
345 u[0].setIConst(index);
346
347 TType type(EbtInt, EbpUndefined, EvqConst, 1);
348 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
349 return node;
350}
351
352// static
353TIntermTyped *TIntermTyped::CreateZero(const TType &type)
354{
355 TType constType(type);
356 constType.setQualifier(EvqConst);
357
358 if (!type.isArray() && type.getBasicType() != EbtStruct)
359 {
360 ASSERT(type.isScalar() || type.isVector() || type.isMatrix());
361
362 size_t size = constType.getObjectSize();
363 TConstantUnion *u = new TConstantUnion[size];
364 for (size_t i = 0; i < size; ++i)
365 {
366 switch (type.getBasicType())
367 {
368 case EbtFloat:
369 u[i].setFConst(0.0f);
370 break;
371 case EbtInt:
372 u[i].setIConst(0);
373 break;
374 case EbtUInt:
375 u[i].setUConst(0u);
376 break;
377 case EbtBool:
378 u[i].setBConst(false);
379 break;
380 default:
381 UNREACHABLE();
382 return nullptr;
383 }
384 }
385
386 TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
387 return node;
388 }
389
390 TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type));
391 constructor->setType(constType);
392
393 if (type.isArray())
394 {
395 TType elementType(type);
396 elementType.clearArrayness();
397
398 size_t arraySize = type.getArraySize();
399 for (size_t i = 0; i < arraySize; ++i)
400 {
401 constructor->getSequence()->push_back(CreateZero(elementType));
402 }
403 }
404 else
405 {
406 ASSERT(type.getBasicType() == EbtStruct);
407
408 TStructure *structure = type.getStruct();
409 for (const auto &field : structure->fields())
410 {
411 constructor->getSequence()->push_back(CreateZero(*field->type()));
412 }
413 }
414
415 return constructor;
416}
417
Olli Etuahod7a25242015-08-18 13:49:45 +0300418TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
419{
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200420 mUnionArrayPointer = node.mUnionArrayPointer;
Olli Etuahod7a25242015-08-18 13:49:45 +0300421}
422
423TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
424 : TIntermOperator(node),
425 mName(node.mName),
426 mUserDefined(node.mUserDefined),
427 mFunctionId(node.mFunctionId),
Olli Etuahod7a25242015-08-18 13:49:45 +0300428 mUseEmulatedFunction(node.mUseEmulatedFunction),
429 mGotPrecisionFromChildren(node.mGotPrecisionFromChildren)
430{
431 for (TIntermNode *child : node.mSequence)
432 {
433 TIntermTyped *typedChild = child->getAsTyped();
434 ASSERT(typedChild != nullptr);
435 TIntermTyped *childCopy = typedChild->deepCopy();
436 mSequence.push_back(childCopy);
437 }
438}
439
440TIntermBinary::TIntermBinary(const TIntermBinary &node)
441 : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
442{
443 TIntermTyped *leftCopy = node.mLeft->deepCopy();
444 TIntermTyped *rightCopy = node.mRight->deepCopy();
445 ASSERT(leftCopy != nullptr && rightCopy != nullptr);
446 mLeft = leftCopy;
447 mRight = rightCopy;
448}
449
450TIntermUnary::TIntermUnary(const TIntermUnary &node)
451 : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
452{
453 TIntermTyped *operandCopy = node.mOperand->deepCopy();
454 ASSERT(operandCopy != nullptr);
455 mOperand = operandCopy;
456}
457
458TIntermSelection::TIntermSelection(const TIntermSelection &node) : TIntermTyped(node)
459{
460 // Only supported for ternary nodes, not if statements.
461 TIntermTyped *trueTyped = node.mTrueBlock->getAsTyped();
462 TIntermTyped *falseTyped = node.mFalseBlock->getAsTyped();
463 ASSERT(trueTyped != nullptr);
464 ASSERT(falseTyped != nullptr);
465 TIntermTyped *conditionCopy = node.mCondition->deepCopy();
466 TIntermTyped *trueCopy = trueTyped->deepCopy();
467 TIntermTyped *falseCopy = falseTyped->deepCopy();
468 ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
469 mCondition = conditionCopy;
470 mTrueBlock = trueCopy;
471 mFalseBlock = falseCopy;
472}
473
Jamie Madillb1a85f42014-08-19 15:23:24 -0400474bool TIntermOperator::isAssignment() const
475{
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300476 return IsAssignment(mOp);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400477}
478
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300479bool TIntermOperator::isMultiplication() const
480{
481 switch (mOp)
482 {
483 case EOpMul:
484 case EOpMatrixTimesMatrix:
485 case EOpMatrixTimesVector:
486 case EOpMatrixTimesScalar:
487 case EOpVectorTimesMatrix:
488 case EOpVectorTimesScalar:
489 return true;
490 default:
491 return false;
492 }
493}
494
Jamie Madillb1a85f42014-08-19 15:23:24 -0400495//
496// returns true if the operator is for one of the constructors
497//
498bool TIntermOperator::isConstructor() const
499{
500 switch (mOp)
501 {
502 case EOpConstructVec2:
503 case EOpConstructVec3:
504 case EOpConstructVec4:
505 case EOpConstructMat2:
Alexis Hetu07e57df2015-06-16 16:55:52 -0400506 case EOpConstructMat2x3:
507 case EOpConstructMat2x4:
508 case EOpConstructMat3x2:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400509 case EOpConstructMat3:
Alexis Hetu07e57df2015-06-16 16:55:52 -0400510 case EOpConstructMat3x4:
511 case EOpConstructMat4x2:
512 case EOpConstructMat4x3:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400513 case EOpConstructMat4:
514 case EOpConstructFloat:
515 case EOpConstructIVec2:
516 case EOpConstructIVec3:
517 case EOpConstructIVec4:
518 case EOpConstructInt:
519 case EOpConstructUVec2:
520 case EOpConstructUVec3:
521 case EOpConstructUVec4:
522 case EOpConstructUInt:
523 case EOpConstructBVec2:
524 case EOpConstructBVec3:
525 case EOpConstructBVec4:
526 case EOpConstructBool:
527 case EOpConstructStruct:
528 return true;
529 default:
530 return false;
531 }
532}
533
Olli Etuaho1dded802016-08-18 18:13:13 +0300534TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
535{
536 if (left.isMatrix())
537 {
538 if (right.isMatrix())
539 {
540 return EOpMatrixTimesMatrix;
541 }
542 else
543 {
544 if (right.isVector())
545 {
546 return EOpMatrixTimesVector;
547 }
548 else
549 {
550 return EOpMatrixTimesScalar;
551 }
552 }
553 }
554 else
555 {
556 if (right.isMatrix())
557 {
558 if (left.isVector())
559 {
560 return EOpVectorTimesMatrix;
561 }
562 else
563 {
564 return EOpMatrixTimesScalar;
565 }
566 }
567 else
568 {
569 // Neither operand is a matrix.
570 if (left.isVector() == right.isVector())
571 {
572 // Leave as component product.
573 return EOpMul;
574 }
575 else
576 {
577 return EOpVectorTimesScalar;
578 }
579 }
580 }
581}
582
583TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
584{
585 if (left.isMatrix())
586 {
587 if (right.isMatrix())
588 {
589 return EOpMatrixTimesMatrixAssign;
590 }
591 else
592 {
593 // right should be scalar, but this may not be validated yet.
594 return EOpMatrixTimesScalarAssign;
595 }
596 }
597 else
598 {
599 if (right.isMatrix())
600 {
601 // Left should be a vector, but this may not be validated yet.
602 return EOpVectorTimesMatrixAssign;
603 }
604 else
605 {
606 // Neither operand is a matrix.
607 if (left.isVector() == right.isVector())
608 {
609 // Leave as component product.
610 return EOpMulAssign;
611 }
612 else
613 {
614 // left should be vector and right should be scalar, but this may not be validated
615 // yet.
616 return EOpVectorTimesScalarAssign;
617 }
618 }
619 }
620}
621
Jamie Madillb1a85f42014-08-19 15:23:24 -0400622//
623// Make sure the type of a unary operator is appropriate for its
624// combination of operation and operand type.
625//
Olli Etuahof6c694b2015-03-26 14:50:53 +0200626void TIntermUnary::promote(const TType *funcReturnType)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400627{
628 switch (mOp)
629 {
Olli Etuahodca3e792015-03-26 13:24:04 +0200630 case EOpFloatBitsToInt:
631 case EOpFloatBitsToUint:
Olli Etuahoe8d2c072015-01-08 16:33:54 +0200632 case EOpIntBitsToFloat:
633 case EOpUintBitsToFloat:
Olli Etuahodca3e792015-03-26 13:24:04 +0200634 case EOpPackSnorm2x16:
635 case EOpPackUnorm2x16:
636 case EOpPackHalf2x16:
Olli Etuaho7700ff62015-01-15 12:16:29 +0200637 case EOpUnpackSnorm2x16:
638 case EOpUnpackUnorm2x16:
Olli Etuahodca3e792015-03-26 13:24:04 +0200639 mType.setPrecision(EbpHigh);
Arun Patole6b19d762015-02-19 09:40:39 +0530640 break;
Olli Etuahodca3e792015-03-26 13:24:04 +0200641 case EOpUnpackHalf2x16:
642 mType.setPrecision(EbpMedium);
643 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400644 default:
Olli Etuahodca3e792015-03-26 13:24:04 +0200645 setType(mOperand->getType());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400646 }
647
Olli Etuahof6c694b2015-03-26 14:50:53 +0200648 if (funcReturnType != nullptr)
649 {
650 if (funcReturnType->getBasicType() == EbtBool)
651 {
652 // Bool types should not have precision.
653 setType(*funcReturnType);
654 }
655 else
656 {
657 // Precision of the node has been set based on the operand.
658 setTypePreservePrecision(*funcReturnType);
659 }
660 }
661
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200662 if (mOperand->getQualifier() == EvqConst)
663 mType.setQualifier(EvqConst);
664 else
665 mType.setQualifier(EvqTemporary);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400666}
667
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300668TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
669 : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
670{
671 promote();
672}
673
Jamie Madillb1a85f42014-08-19 15:23:24 -0400674//
675// Establishes the type of the resultant operation, as well as
676// makes the operator the correct one for the operands.
677//
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200678// For lots of operations it should already be established that the operand
679// combination is valid, but returns false if operator can't work on operands.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400680//
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300681void TIntermBinary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400682{
Olli Etuahoe79904c2015-03-18 16:56:42 +0200683 ASSERT(mLeft->isArray() == mRight->isArray());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400684
Olli Etuaho1dded802016-08-18 18:13:13 +0300685 ASSERT(!isMultiplication() ||
686 mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
687
Jamie Madillb1a85f42014-08-19 15:23:24 -0400688 // Base assumption: just make the type the same as the left
689 // operand. Then only deviations from this need be coded.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400690 setType(mLeft->getType());
691
692 // The result gets promoted to the highest precision.
693 TPrecision higherPrecision = GetHigherPrecision(
694 mLeft->getPrecision(), mRight->getPrecision());
695 getTypePointer()->setPrecision(higherPrecision);
696
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200697 TQualifier resultQualifier = EvqConst;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400698 // Binary operations results in temporary variables unless both
699 // operands are const.
700 if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
701 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200702 resultQualifier = EvqTemporary;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400703 getTypePointer()->setQualifier(EvqTemporary);
704 }
705
706 const int nominalSize =
707 std::max(mLeft->getNominalSize(), mRight->getNominalSize());
708
709 //
710 // All scalars or structs. Code after this test assumes this case is removed!
711 //
712 if (nominalSize == 1)
713 {
714 switch (mOp)
715 {
716 //
717 // Promote to conditional
718 //
719 case EOpEqual:
720 case EOpNotEqual:
721 case EOpLessThan:
722 case EOpGreaterThan:
723 case EOpLessThanEqual:
724 case EOpGreaterThanEqual:
Olli Etuahoc9550582016-08-29 17:56:22 +0300725 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400726 break;
727
728 //
729 // And and Or operate on conditionals
730 //
731 case EOpLogicalAnd:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200732 case EOpLogicalXor:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400733 case EOpLogicalOr:
Olli Etuaho47fd36a2015-03-19 14:22:24 +0200734 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
Olli Etuahoc9550582016-08-29 17:56:22 +0300735 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400736 break;
737
738 default:
739 break;
740 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300741 return;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400742 }
743
744 // If we reach here, at least one of the operands is vector or matrix.
745 // The other operand could be a scalar, vector, or matrix.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400746 TBasicType basicType = mLeft->getBasicType();
Olli Etuaho1dded802016-08-18 18:13:13 +0300747
Jamie Madillb1a85f42014-08-19 15:23:24 -0400748 switch (mOp)
749 {
Olli Etuaho1dded802016-08-18 18:13:13 +0300750 case EOpMul:
751 break;
752 case EOpMatrixTimesScalar:
753 if (mRight->isMatrix())
Jamie Madillb1a85f42014-08-19 15:23:24 -0400754 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200755 setType(TType(basicType, higherPrecision, resultQualifier,
756 static_cast<unsigned char>(mRight->getCols()),
757 static_cast<unsigned char>(mRight->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400758 }
Olli Etuaho1dded802016-08-18 18:13:13 +0300759 break;
760 case EOpMatrixTimesVector:
761 setType(TType(basicType, higherPrecision, resultQualifier,
762 static_cast<unsigned char>(mLeft->getRows()), 1));
763 break;
764 case EOpMatrixTimesMatrix:
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200765 setType(TType(basicType, higherPrecision, resultQualifier,
766 static_cast<unsigned char>(mRight->getCols()),
767 static_cast<unsigned char>(mLeft->getRows())));
Olli Etuaho1dded802016-08-18 18:13:13 +0300768 break;
769 case EOpVectorTimesScalar:
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200770 setType(TType(basicType, higherPrecision, resultQualifier,
Olli Etuaho1dded802016-08-18 18:13:13 +0300771 static_cast<unsigned char>(nominalSize), 1));
772 break;
773 case EOpVectorTimesMatrix:
774 setType(TType(basicType, higherPrecision, resultQualifier,
775 static_cast<unsigned char>(mRight->getCols()), 1));
776 break;
777 case EOpMulAssign:
778 case EOpVectorTimesScalarAssign:
779 case EOpVectorTimesMatrixAssign:
780 case EOpMatrixTimesScalarAssign:
781 case EOpMatrixTimesMatrixAssign:
782 ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
783 break;
784 case EOpAssign:
785 case EOpInitialize:
Olli Etuaho1dded802016-08-18 18:13:13 +0300786 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
787 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
788 break;
789 case EOpAdd:
790 case EOpSub:
791 case EOpDiv:
792 case EOpIMod:
793 case EOpBitShiftLeft:
794 case EOpBitShiftRight:
795 case EOpBitwiseAnd:
796 case EOpBitwiseXor:
797 case EOpBitwiseOr:
798 case EOpAddAssign:
799 case EOpSubAssign:
800 case EOpDivAssign:
801 case EOpIModAssign:
802 case EOpBitShiftLeftAssign:
803 case EOpBitShiftRightAssign:
804 case EOpBitwiseAndAssign:
805 case EOpBitwiseXorAssign:
806 case EOpBitwiseOrAssign:
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300807 {
808 const int secondarySize =
809 std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
810 setType(TType(basicType, higherPrecision, resultQualifier,
811 static_cast<unsigned char>(nominalSize),
812 static_cast<unsigned char>(secondarySize)));
813 ASSERT(!mLeft->isArray() && !mRight->isArray());
Olli Etuaho1dded802016-08-18 18:13:13 +0300814 break;
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300815 }
Olli Etuaho1dded802016-08-18 18:13:13 +0300816 case EOpEqual:
817 case EOpNotEqual:
818 case EOpLessThan:
819 case EOpGreaterThan:
820 case EOpLessThanEqual:
821 case EOpGreaterThanEqual:
822 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
823 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300824 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Olli Etuaho1dded802016-08-18 18:13:13 +0300825 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400826
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300827 case EOpIndexDirect:
828 case EOpIndexIndirect:
829 case EOpIndexDirectInterfaceBlock:
830 case EOpIndexDirectStruct:
831 // TODO (oetuaho): These ops could be handled here as well (should be done closer to the
832 // top of the function).
833 UNREACHABLE();
834 break;
Olli Etuaho1dded802016-08-18 18:13:13 +0300835 default:
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300836 UNREACHABLE();
837 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400838 }
Jamie Madillb1a85f42014-08-19 15:23:24 -0400839}
840
Olli Etuaho3fdec912016-08-18 15:08:06 +0300841TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300842{
843 TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
844 TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
845 if (leftConstant == nullptr || rightConstant == nullptr)
846 {
847 return nullptr;
848 }
Olli Etuaho3fdec912016-08-18 15:08:06 +0300849 TConstantUnion *constArray = leftConstant->foldBinary(mOp, rightConstant, diagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200850
851 // Nodes may be constant folded without being qualified as constant.
Olli Etuahoc9550582016-08-29 17:56:22 +0300852 return CreateFoldedNode(constArray, this, mType.getQualifier());
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300853}
854
Olli Etuahof119a262016-08-19 15:54:22 +0300855TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
Olli Etuaho95310b02015-06-02 17:43:38 +0300856{
857 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
858 if (operandConstant == nullptr)
859 {
860 return nullptr;
861 }
Arun Patoleab2b9a22015-07-06 18:27:56 +0530862
863 TConstantUnion *constArray = nullptr;
864 switch (mOp)
865 {
866 case EOpAny:
867 case EOpAll:
868 case EOpLength:
869 case EOpTranspose:
870 case EOpDeterminant:
871 case EOpInverse:
872 case EOpPackSnorm2x16:
873 case EOpUnpackSnorm2x16:
874 case EOpPackUnorm2x16:
875 case EOpUnpackUnorm2x16:
876 case EOpPackHalf2x16:
877 case EOpUnpackHalf2x16:
Olli Etuahof119a262016-08-19 15:54:22 +0300878 constArray = operandConstant->foldUnaryNonComponentWise(mOp);
879 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +0530880 default:
Olli Etuahof119a262016-08-19 15:54:22 +0300881 constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
882 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +0530883 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200884
885 // Nodes may be constant folded without being qualified as constant.
Olli Etuahoc9550582016-08-29 17:56:22 +0300886 return CreateFoldedNode(constArray, this, mType.getQualifier());
Olli Etuahob43846e2015-06-02 18:18:57 +0300887}
888
Olli Etuahof119a262016-08-19 15:54:22 +0300889TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
Olli Etuahob43846e2015-06-02 18:18:57 +0300890{
891 // Make sure that all params are constant before actual constant folding.
892 for (auto *param : *getSequence())
Olli Etuaho95310b02015-06-02 17:43:38 +0300893 {
Olli Etuahob43846e2015-06-02 18:18:57 +0300894 if (param->getAsConstantUnion() == nullptr)
895 {
896 return nullptr;
897 }
Olli Etuaho95310b02015-06-02 17:43:38 +0300898 }
Olli Etuaho1d122782015-11-06 15:35:17 +0200899 TConstantUnion *constArray = nullptr;
900 if (isConstructor())
Olli Etuahof119a262016-08-19 15:54:22 +0300901 constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
Olli Etuaho1d122782015-11-06 15:35:17 +0200902 else
Olli Etuahof119a262016-08-19 15:54:22 +0300903 constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200904
905 // Nodes may be constant folded without being qualified as constant.
906 TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
907 return CreateFoldedNode(constArray, this, resultQualifier);
Olli Etuaho95310b02015-06-02 17:43:38 +0300908}
909
Jamie Madillb1a85f42014-08-19 15:23:24 -0400910//
911// The fold functions see if an operation on a constant can be done in place,
912// without generating run-time code.
913//
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300914// Returns the constant value to keep using or nullptr.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400915//
Olli Etuaho3fdec912016-08-18 15:08:06 +0300916TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
917 TIntermConstantUnion *rightNode,
918 TDiagnostics *diagnostics)
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300919{
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200920 const TConstantUnion *leftArray = getUnionArrayPointer();
921 const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300922
Olli Etuahof119a262016-08-19 15:54:22 +0300923 ASSERT(leftArray && rightArray);
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300924
925 size_t objectSize = getType().getObjectSize();
926
927 // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
928 if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
929 {
930 rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
931 }
932 else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
933 {
934 // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
935 leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
936 objectSize = rightNode->getType().getObjectSize();
937 }
938
939 TConstantUnion *resultArray = nullptr;
940
941 switch(op)
942 {
943 case EOpAdd:
944 resultArray = new TConstantUnion[objectSize];
945 for (size_t i = 0; i < objectSize; i++)
946 resultArray[i] = leftArray[i] + rightArray[i];
947 break;
948 case EOpSub:
949 resultArray = new TConstantUnion[objectSize];
950 for (size_t i = 0; i < objectSize; i++)
951 resultArray[i] = leftArray[i] - rightArray[i];
952 break;
953
954 case EOpMul:
955 case EOpVectorTimesScalar:
956 case EOpMatrixTimesScalar:
957 resultArray = new TConstantUnion[objectSize];
958 for (size_t i = 0; i < objectSize; i++)
959 resultArray[i] = leftArray[i] * rightArray[i];
960 break;
961
962 case EOpMatrixTimesMatrix:
963 {
Olli Etuaho3fdec912016-08-18 15:08:06 +0300964 ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +0300965
966 const int leftCols = getCols();
967 const int leftRows = getRows();
968 const int rightCols = rightNode->getType().getCols();
969 const int rightRows = rightNode->getType().getRows();
970 const int resultCols = rightCols;
971 const int resultRows = leftRows;
972
973 resultArray = new TConstantUnion[resultCols * resultRows];
974 for (int row = 0; row < resultRows; row++)
975 {
976 for (int column = 0; column < resultCols; column++)
977 {
978 resultArray[resultRows * column + row].setFConst(0.0f);
979 for (int i = 0; i < leftCols; i++)
980 {
981 resultArray[resultRows * column + row].setFConst(
982 resultArray[resultRows * column + row].getFConst() +
983 leftArray[i * leftRows + row].getFConst() *
984 rightArray[column * rightRows + i].getFConst());
985 }
986 }
987 }
988 }
989 break;
990
991 case EOpDiv:
992 case EOpIMod:
993 {
994 resultArray = new TConstantUnion[objectSize];
995 for (size_t i = 0; i < objectSize; i++)
996 {
997 switch (getType().getBasicType())
998 {
999 case EbtFloat:
1000 if (rightArray[i] == 0.0f)
1001 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001002 diagnostics->warning(
1003 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001004 resultArray[i].setFConst(leftArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
1005 }
1006 else
1007 {
1008 ASSERT(op == EOpDiv);
1009 resultArray[i].setFConst(leftArray[i].getFConst() / rightArray[i].getFConst());
1010 }
1011 break;
1012
1013 case EbtInt:
1014 if (rightArray[i] == 0)
1015 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001016 diagnostics->warning(
1017 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001018 resultArray[i].setIConst(INT_MAX);
1019 }
1020 else
1021 {
1022 if (op == EOpDiv)
1023 {
1024 resultArray[i].setIConst(leftArray[i].getIConst() / rightArray[i].getIConst());
1025 }
1026 else
1027 {
1028 ASSERT(op == EOpIMod);
1029 resultArray[i].setIConst(leftArray[i].getIConst() % rightArray[i].getIConst());
1030 }
1031 }
1032 break;
1033
1034 case EbtUInt:
1035 if (rightArray[i] == 0)
1036 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001037 diagnostics->warning(
1038 getLine(), "Divide by zero error during constant folding", "/", "");
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001039 resultArray[i].setUConst(UINT_MAX);
1040 }
1041 else
1042 {
1043 if (op == EOpDiv)
1044 {
1045 resultArray[i].setUConst(leftArray[i].getUConst() / rightArray[i].getUConst());
1046 }
1047 else
1048 {
1049 ASSERT(op == EOpIMod);
1050 resultArray[i].setUConst(leftArray[i].getUConst() % rightArray[i].getUConst());
1051 }
1052 }
1053 break;
1054
1055 default:
Olli Etuaho3fdec912016-08-18 15:08:06 +03001056 UNREACHABLE();
1057 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001058 }
1059 }
1060 }
1061 break;
1062
1063 case EOpMatrixTimesVector:
1064 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001065 ASSERT(rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001066
1067 const int matrixCols = getCols();
1068 const int matrixRows = getRows();
1069
1070 resultArray = new TConstantUnion[matrixRows];
1071
1072 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1073 {
1074 resultArray[matrixRow].setFConst(0.0f);
1075 for (int col = 0; col < matrixCols; col++)
1076 {
1077 resultArray[matrixRow].setFConst(resultArray[matrixRow].getFConst() +
1078 leftArray[col * matrixRows + matrixRow].getFConst() *
1079 rightArray[col].getFConst());
1080 }
1081 }
1082 }
1083 break;
1084
1085 case EOpVectorTimesMatrix:
1086 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001087 ASSERT(getType().getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001088
1089 const int matrixCols = rightNode->getType().getCols();
1090 const int matrixRows = rightNode->getType().getRows();
1091
1092 resultArray = new TConstantUnion[matrixCols];
1093
1094 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
1095 {
1096 resultArray[matrixCol].setFConst(0.0f);
1097 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1098 {
1099 resultArray[matrixCol].setFConst(resultArray[matrixCol].getFConst() +
1100 leftArray[matrixRow].getFConst() *
1101 rightArray[matrixCol * matrixRows + matrixRow].getFConst());
1102 }
1103 }
1104 }
1105 break;
1106
1107 case EOpLogicalAnd:
1108 {
1109 resultArray = new TConstantUnion[objectSize];
1110 for (size_t i = 0; i < objectSize; i++)
1111 {
1112 resultArray[i] = leftArray[i] && rightArray[i];
1113 }
1114 }
1115 break;
1116
1117 case EOpLogicalOr:
1118 {
1119 resultArray = new TConstantUnion[objectSize];
1120 for (size_t i = 0; i < objectSize; i++)
1121 {
1122 resultArray[i] = leftArray[i] || rightArray[i];
1123 }
1124 }
1125 break;
1126
1127 case EOpLogicalXor:
1128 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001129 ASSERT(getType().getBasicType() == EbtBool);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001130 resultArray = new TConstantUnion[objectSize];
1131 for (size_t i = 0; i < objectSize; i++)
1132 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001133 resultArray[i].setBConst(leftArray[i] != rightArray[i]);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001134 }
1135 }
1136 break;
1137
1138 case EOpBitwiseAnd:
1139 resultArray = new TConstantUnion[objectSize];
1140 for (size_t i = 0; i < objectSize; i++)
1141 resultArray[i] = leftArray[i] & rightArray[i];
1142 break;
1143 case EOpBitwiseXor:
1144 resultArray = new TConstantUnion[objectSize];
1145 for (size_t i = 0; i < objectSize; i++)
1146 resultArray[i] = leftArray[i] ^ rightArray[i];
1147 break;
1148 case EOpBitwiseOr:
1149 resultArray = new TConstantUnion[objectSize];
1150 for (size_t i = 0; i < objectSize; i++)
1151 resultArray[i] = leftArray[i] | rightArray[i];
1152 break;
1153 case EOpBitShiftLeft:
1154 resultArray = new TConstantUnion[objectSize];
1155 for (size_t i = 0; i < objectSize; i++)
1156 resultArray[i] = leftArray[i] << rightArray[i];
1157 break;
1158 case EOpBitShiftRight:
1159 resultArray = new TConstantUnion[objectSize];
1160 for (size_t i = 0; i < objectSize; i++)
1161 resultArray[i] = leftArray[i] >> rightArray[i];
1162 break;
1163
1164 case EOpLessThan:
1165 ASSERT(objectSize == 1);
1166 resultArray = new TConstantUnion[1];
1167 resultArray->setBConst(*leftArray < *rightArray);
1168 break;
1169
1170 case EOpGreaterThan:
1171 ASSERT(objectSize == 1);
1172 resultArray = new TConstantUnion[1];
1173 resultArray->setBConst(*leftArray > *rightArray);
1174 break;
1175
1176 case EOpLessThanEqual:
1177 ASSERT(objectSize == 1);
1178 resultArray = new TConstantUnion[1];
1179 resultArray->setBConst(!(*leftArray > *rightArray));
1180 break;
1181
1182 case EOpGreaterThanEqual:
1183 ASSERT(objectSize == 1);
1184 resultArray = new TConstantUnion[1];
1185 resultArray->setBConst(!(*leftArray < *rightArray));
1186 break;
1187
1188 case EOpEqual:
1189 case EOpNotEqual:
1190 {
1191 resultArray = new TConstantUnion[1];
1192 bool equal = true;
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001193 for (size_t i = 0; i < objectSize; i++)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001194 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001195 if (leftArray[i] != rightArray[i])
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001196 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001197 equal = false;
1198 break; // break out of for loop
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001199 }
1200 }
1201 if (op == EOpEqual)
1202 {
1203 resultArray->setBConst(equal);
1204 }
1205 else
1206 {
1207 resultArray->setBConst(!equal);
1208 }
1209 }
1210 break;
1211
1212 default:
Olli Etuaho3fdec912016-08-18 15:08:06 +03001213 UNREACHABLE();
1214 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001215 }
1216 return resultArray;
1217}
1218
Olli Etuahof119a262016-08-19 15:54:22 +03001219// The fold functions do operations on a constant at GLSL compile time, without generating run-time
1220// code. Returns the constant value to keep using. Nullptr should not be returned.
1221TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
Jamie Madillb1a85f42014-08-19 15:23:24 -04001222{
Olli Etuahof119a262016-08-19 15:54:22 +03001223 // Do operations where the return type may have a different number of components compared to the
1224 // operand type.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001225
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001226 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001227 ASSERT(operandArray);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301228
1229 size_t objectSize = getType().getObjectSize();
1230 TConstantUnion *resultArray = nullptr;
1231 switch (op)
1232 {
Olli Etuahof119a262016-08-19 15:54:22 +03001233 case EOpAny:
1234 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301235 resultArray = new TConstantUnion();
1236 resultArray->setBConst(false);
1237 for (size_t i = 0; i < objectSize; i++)
1238 {
1239 if (operandArray[i].getBConst())
1240 {
1241 resultArray->setBConst(true);
1242 break;
1243 }
1244 }
1245 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301246
Olli Etuahof119a262016-08-19 15:54:22 +03001247 case EOpAll:
1248 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301249 resultArray = new TConstantUnion();
1250 resultArray->setBConst(true);
1251 for (size_t i = 0; i < objectSize; i++)
1252 {
1253 if (!operandArray[i].getBConst())
1254 {
1255 resultArray->setBConst(false);
1256 break;
1257 }
1258 }
1259 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301260
Olli Etuahof119a262016-08-19 15:54:22 +03001261 case EOpLength:
1262 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301263 resultArray = new TConstantUnion();
1264 resultArray->setFConst(VectorLength(operandArray, objectSize));
1265 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301266
Olli Etuahof119a262016-08-19 15:54:22 +03001267 case EOpTranspose:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301268 {
Olli Etuahof119a262016-08-19 15:54:22 +03001269 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301270 resultArray = new TConstantUnion[objectSize];
1271 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03001272 GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301273 SetUnionArrayFromMatrix(result, resultArray);
1274 break;
1275 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301276
Olli Etuahof119a262016-08-19 15:54:22 +03001277 case EOpDeterminant:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301278 {
Olli Etuahof119a262016-08-19 15:54:22 +03001279 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301280 unsigned int size = getType().getNominalSize();
1281 ASSERT(size >= 2 && size <= 4);
1282 resultArray = new TConstantUnion();
1283 resultArray->setFConst(GetMatrix(operandArray, size).determinant());
1284 break;
1285 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301286
Olli Etuahof119a262016-08-19 15:54:22 +03001287 case EOpInverse:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301288 {
Olli Etuahof119a262016-08-19 15:54:22 +03001289 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301290 unsigned int size = getType().getNominalSize();
1291 ASSERT(size >= 2 && size <= 4);
Olli Etuahof119a262016-08-19 15:54:22 +03001292 resultArray = new TConstantUnion[objectSize];
Arun Patoleab2b9a22015-07-06 18:27:56 +05301293 angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
1294 SetUnionArrayFromMatrix(result, resultArray);
1295 break;
1296 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301297
Olli Etuahof119a262016-08-19 15:54:22 +03001298 case EOpPackSnorm2x16:
1299 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301300 ASSERT(getType().getNominalSize() == 2);
1301 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001302 resultArray->setUConst(
1303 gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301304 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301305
Olli Etuahof119a262016-08-19 15:54:22 +03001306 case EOpUnpackSnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301307 {
Olli Etuahof119a262016-08-19 15:54:22 +03001308 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301309 resultArray = new TConstantUnion[2];
1310 float f1, f2;
1311 gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1312 resultArray[0].setFConst(f1);
1313 resultArray[1].setFConst(f2);
1314 break;
1315 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301316
Olli Etuahof119a262016-08-19 15:54:22 +03001317 case EOpPackUnorm2x16:
1318 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301319 ASSERT(getType().getNominalSize() == 2);
1320 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001321 resultArray->setUConst(
1322 gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301323 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301324
Olli Etuahof119a262016-08-19 15:54:22 +03001325 case EOpUnpackUnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301326 {
Olli Etuahof119a262016-08-19 15:54:22 +03001327 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301328 resultArray = new TConstantUnion[2];
1329 float f1, f2;
1330 gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1331 resultArray[0].setFConst(f1);
1332 resultArray[1].setFConst(f2);
1333 break;
1334 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301335
Olli Etuahof119a262016-08-19 15:54:22 +03001336 case EOpPackHalf2x16:
1337 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301338 ASSERT(getType().getNominalSize() == 2);
1339 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001340 resultArray->setUConst(
1341 gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301342 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301343
Olli Etuahof119a262016-08-19 15:54:22 +03001344 case EOpUnpackHalf2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301345 {
Olli Etuahof119a262016-08-19 15:54:22 +03001346 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301347 resultArray = new TConstantUnion[2];
1348 float f1, f2;
1349 gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
1350 resultArray[0].setFConst(f1);
1351 resultArray[1].setFConst(f2);
1352 break;
1353 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301354
Olli Etuahof119a262016-08-19 15:54:22 +03001355 default:
1356 UNREACHABLE();
1357 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301358 }
1359
1360 return resultArray;
1361}
1362
Olli Etuahof119a262016-08-19 15:54:22 +03001363TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
1364 TDiagnostics *diagnostics)
Arun Patoleab2b9a22015-07-06 18:27:56 +05301365{
Olli Etuahof119a262016-08-19 15:54:22 +03001366 // Do unary operations where each component of the result is computed based on the corresponding
1367 // component of the operand. Also folds normalize, though the divisor in that case takes all
1368 // components into account.
Arun Patoleab2b9a22015-07-06 18:27:56 +05301369
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001370 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001371 ASSERT(operandArray);
Jamie Madillb1a85f42014-08-19 15:23:24 -04001372
1373 size_t objectSize = getType().getObjectSize();
1374
Arun Patoleab2b9a22015-07-06 18:27:56 +05301375 TConstantUnion *resultArray = new TConstantUnion[objectSize];
1376 for (size_t i = 0; i < objectSize; i++)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301377 {
Arun Patoleab2b9a22015-07-06 18:27:56 +05301378 switch(op)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301379 {
Olli Etuahof119a262016-08-19 15:54:22 +03001380 case EOpNegative:
1381 switch (getType().getBasicType())
1382 {
1383 case EbtFloat:
1384 resultArray[i].setFConst(-operandArray[i].getFConst());
1385 break;
1386 case EbtInt:
1387 resultArray[i].setIConst(-operandArray[i].getIConst());
1388 break;
1389 case EbtUInt:
1390 resultArray[i].setUConst(static_cast<unsigned int>(
1391 -static_cast<int>(operandArray[i].getUConst())));
1392 break;
1393 default:
1394 UNREACHABLE();
1395 return nullptr;
1396 }
Arun Patole1155ddd2015-06-05 18:04:36 +05301397 break;
Arun Patolecdfa8f52015-06-30 17:48:25 +05301398
Olli Etuahof119a262016-08-19 15:54:22 +03001399 case EOpPositive:
1400 switch (getType().getBasicType())
1401 {
1402 case EbtFloat:
1403 resultArray[i].setFConst(operandArray[i].getFConst());
1404 break;
1405 case EbtInt:
1406 resultArray[i].setIConst(operandArray[i].getIConst());
1407 break;
1408 case EbtUInt:
1409 resultArray[i].setUConst(static_cast<unsigned int>(
1410 static_cast<int>(operandArray[i].getUConst())));
1411 break;
1412 default:
1413 UNREACHABLE();
1414 return nullptr;
1415 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301416 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301417
Olli Etuahof119a262016-08-19 15:54:22 +03001418 case EOpLogicalNot:
1419 switch (getType().getBasicType())
1420 {
1421 case EbtBool:
1422 resultArray[i].setBConst(!operandArray[i].getBConst());
1423 break;
1424 default:
1425 UNREACHABLE();
1426 return nullptr;
1427 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301428 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301429
Olli Etuahof119a262016-08-19 15:54:22 +03001430 case EOpBitwiseNot:
1431 switch (getType().getBasicType())
1432 {
1433 case EbtInt:
1434 resultArray[i].setIConst(~operandArray[i].getIConst());
1435 break;
1436 case EbtUInt:
1437 resultArray[i].setUConst(~operandArray[i].getUConst());
1438 break;
1439 default:
1440 UNREACHABLE();
1441 return nullptr;
1442 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301443 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301444
Olli Etuahof119a262016-08-19 15:54:22 +03001445 case EOpRadians:
1446 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301447 resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
1448 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301449
Olli Etuahof119a262016-08-19 15:54:22 +03001450 case EOpDegrees:
1451 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301452 resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
1453 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301454
Olli Etuahof119a262016-08-19 15:54:22 +03001455 case EOpSin:
1456 foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301457 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301458
Olli Etuahof119a262016-08-19 15:54:22 +03001459 case EOpCos:
1460 foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
1461 break;
1462
1463 case EOpTan:
1464 foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
1465 break;
1466
1467 case EOpAsin:
1468 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
1469 // 0.
1470 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1471 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1472 diagnostics, &resultArray[i]);
1473 else
1474 foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
1475 break;
1476
1477 case EOpAcos:
1478 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
1479 // 0.
1480 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1481 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1482 diagnostics, &resultArray[i]);
1483 else
1484 foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
1485 break;
1486
1487 case EOpAtan:
1488 foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
1489 break;
1490
1491 case EOpSinh:
1492 foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
1493 break;
1494
1495 case EOpCosh:
1496 foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
1497 break;
1498
1499 case EOpTanh:
1500 foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
1501 break;
1502
1503 case EOpAsinh:
1504 foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
1505 break;
1506
1507 case EOpAcosh:
1508 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
1509 if (operandArray[i].getFConst() < 1.0f)
1510 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1511 diagnostics, &resultArray[i]);
1512 else
1513 foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
1514 break;
1515
1516 case EOpAtanh:
1517 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
1518 // 0.
1519 if (fabsf(operandArray[i].getFConst()) >= 1.0f)
1520 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1521 diagnostics, &resultArray[i]);
1522 else
1523 foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
1524 break;
1525
1526 case EOpAbs:
1527 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301528 {
Olli Etuahof119a262016-08-19 15:54:22 +03001529 case EbtFloat:
1530 resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
1531 break;
1532 case EbtInt:
1533 resultArray[i].setIConst(abs(operandArray[i].getIConst()));
1534 break;
1535 default:
1536 UNREACHABLE();
1537 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301538 }
1539 break;
Olli Etuahof119a262016-08-19 15:54:22 +03001540
1541 case EOpSign:
1542 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301543 {
Olli Etuahof119a262016-08-19 15:54:22 +03001544 case EbtFloat:
1545 {
1546 float fConst = operandArray[i].getFConst();
1547 float fResult = 0.0f;
1548 if (fConst > 0.0f)
1549 fResult = 1.0f;
1550 else if (fConst < 0.0f)
1551 fResult = -1.0f;
1552 resultArray[i].setFConst(fResult);
1553 break;
1554 }
1555 case EbtInt:
1556 {
1557 int iConst = operandArray[i].getIConst();
1558 int iResult = 0;
1559 if (iConst > 0)
1560 iResult = 1;
1561 else if (iConst < 0)
1562 iResult = -1;
1563 resultArray[i].setIConst(iResult);
1564 break;
1565 }
1566 default:
1567 UNREACHABLE();
1568 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301569 }
1570 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301571
Olli Etuahof119a262016-08-19 15:54:22 +03001572 case EOpFloor:
1573 foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
1574 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301575
Olli Etuahof119a262016-08-19 15:54:22 +03001576 case EOpTrunc:
1577 foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
1578 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301579
Olli Etuahof119a262016-08-19 15:54:22 +03001580 case EOpRound:
1581 foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
1582 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301583
Olli Etuahof119a262016-08-19 15:54:22 +03001584 case EOpRoundEven:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301585 {
Olli Etuahof119a262016-08-19 15:54:22 +03001586 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301587 float x = operandArray[i].getFConst();
1588 float result;
1589 float fractPart = modff(x, &result);
1590 if (fabsf(fractPart) == 0.5f)
1591 result = 2.0f * roundf(x / 2.0f);
1592 else
1593 result = roundf(x);
1594 resultArray[i].setFConst(result);
1595 break;
1596 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301597
Olli Etuahof119a262016-08-19 15:54:22 +03001598 case EOpCeil:
1599 foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
1600 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301601
Olli Etuahof119a262016-08-19 15:54:22 +03001602 case EOpFract:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301603 {
Olli Etuahof119a262016-08-19 15:54:22 +03001604 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301605 float x = operandArray[i].getFConst();
1606 resultArray[i].setFConst(x - floorf(x));
1607 break;
1608 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301609
Olli Etuahof119a262016-08-19 15:54:22 +03001610 case EOpIsNan:
1611 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301612 resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
1613 break;
Arun Patole551279e2015-07-07 18:18:23 +05301614
Olli Etuahof119a262016-08-19 15:54:22 +03001615 case EOpIsInf:
1616 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301617 resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
1618 break;
Arun Patole551279e2015-07-07 18:18:23 +05301619
Olli Etuahof119a262016-08-19 15:54:22 +03001620 case EOpFloatBitsToInt:
1621 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301622 resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
1623 break;
Arun Patole551279e2015-07-07 18:18:23 +05301624
Olli Etuahof119a262016-08-19 15:54:22 +03001625 case EOpFloatBitsToUint:
1626 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05301627 resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
1628 break;
Arun Patole551279e2015-07-07 18:18:23 +05301629
Olli Etuahof119a262016-08-19 15:54:22 +03001630 case EOpIntBitsToFloat:
1631 ASSERT(getType().getBasicType() == EbtInt);
Arun Patole551279e2015-07-07 18:18:23 +05301632 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
1633 break;
Arun Patole551279e2015-07-07 18:18:23 +05301634
Olli Etuahof119a262016-08-19 15:54:22 +03001635 case EOpUintBitsToFloat:
1636 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patole551279e2015-07-07 18:18:23 +05301637 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
1638 break;
Arun Patole551279e2015-07-07 18:18:23 +05301639
Olli Etuahof119a262016-08-19 15:54:22 +03001640 case EOpExp:
1641 foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
1642 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301643
Olli Etuahof119a262016-08-19 15:54:22 +03001644 case EOpLog:
1645 // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
1646 if (operandArray[i].getFConst() <= 0.0f)
1647 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1648 diagnostics, &resultArray[i]);
1649 else
1650 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
1651 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301652
Olli Etuahof119a262016-08-19 15:54:22 +03001653 case EOpExp2:
1654 foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
1655 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301656
Olli Etuahof119a262016-08-19 15:54:22 +03001657 case EOpLog2:
1658 // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
1659 // And log2f is not available on some plarforms like old android, so just using
1660 // log(x)/log(2) here.
1661 if (operandArray[i].getFConst() <= 0.0f)
1662 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1663 diagnostics, &resultArray[i]);
1664 else
1665 {
1666 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
1667 resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
1668 }
1669 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301670
Olli Etuahof119a262016-08-19 15:54:22 +03001671 case EOpSqrt:
1672 // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
1673 if (operandArray[i].getFConst() < 0.0f)
1674 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1675 diagnostics, &resultArray[i]);
1676 else
1677 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
1678 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301679
Olli Etuahof119a262016-08-19 15:54:22 +03001680 case EOpInverseSqrt:
1681 // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
1682 // so getting the square root first using builtin function sqrt() and then taking
1683 // its inverse.
1684 // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
1685 // result to 0.
1686 if (operandArray[i].getFConst() <= 0.0f)
1687 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1688 diagnostics, &resultArray[i]);
1689 else
1690 {
1691 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
1692 resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
1693 }
1694 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301695
Olli Etuahof119a262016-08-19 15:54:22 +03001696 case EOpVectorLogicalNot:
1697 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301698 resultArray[i].setBConst(!operandArray[i].getBConst());
1699 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301700
Olli Etuahof119a262016-08-19 15:54:22 +03001701 case EOpNormalize:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301702 {
Olli Etuahof119a262016-08-19 15:54:22 +03001703 ASSERT(getType().getBasicType() == EbtFloat);
1704 float x = operandArray[i].getFConst();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301705 float length = VectorLength(operandArray, objectSize);
1706 if (length)
1707 resultArray[i].setFConst(x / length);
1708 else
Olli Etuahof119a262016-08-19 15:54:22 +03001709 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1710 diagnostics, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301711 break;
1712 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301713
Olli Etuahof119a262016-08-19 15:54:22 +03001714 case EOpDFdx:
1715 case EOpDFdy:
1716 case EOpFwidth:
1717 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole0c5409f2015-07-08 15:17:53 +05301718 // Derivatives of constant arguments should be 0.
1719 resultArray[i].setFConst(0.0f);
1720 break;
Arun Patole0c5409f2015-07-08 15:17:53 +05301721
Olli Etuahof119a262016-08-19 15:54:22 +03001722 default:
1723 return nullptr;
Arun Patole9d0b1f92015-05-20 14:27:17 +05301724 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05301725 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04001726
Arun Patoleab2b9a22015-07-06 18:27:56 +05301727 return resultArray;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001728}
1729
Olli Etuahof119a262016-08-19 15:54:22 +03001730void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
1731 FloatTypeUnaryFunc builtinFunc,
1732 TConstantUnion *result) const
Arun Patole9dea48f2015-04-02 11:45:09 +05301733{
1734 ASSERT(builtinFunc);
1735
Olli Etuahof119a262016-08-19 15:54:22 +03001736 ASSERT(getType().getBasicType() == EbtFloat);
1737 result->setFConst(builtinFunc(parameter.getFConst()));
Arun Patole9dea48f2015-04-02 11:45:09 +05301738}
1739
Jamie Madillb1a85f42014-08-19 15:23:24 -04001740// static
Olli Etuahof119a262016-08-19 15:54:22 +03001741TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
Olli Etuaho1d122782015-11-06 15:35:17 +02001742{
1743 ASSERT(aggregate->getSequence()->size() > 0u);
1744 size_t resultSize = aggregate->getType().getObjectSize();
1745 TConstantUnion *resultArray = new TConstantUnion[resultSize];
1746 TBasicType basicType = aggregate->getBasicType();
1747
1748 size_t resultIndex = 0u;
1749
1750 if (aggregate->getSequence()->size() == 1u)
1751 {
1752 TIntermNode *argument = aggregate->getSequence()->front();
1753 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
1754 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
1755 // Check the special case of constructing a matrix diagonal from a single scalar,
1756 // or a vector from a single scalar.
1757 if (argumentConstant->getType().getObjectSize() == 1u)
1758 {
1759 if (aggregate->isMatrix())
1760 {
1761 int resultCols = aggregate->getType().getCols();
1762 int resultRows = aggregate->getType().getRows();
1763 for (int col = 0; col < resultCols; ++col)
1764 {
1765 for (int row = 0; row < resultRows; ++row)
1766 {
1767 if (col == row)
1768 {
1769 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
1770 }
1771 else
1772 {
1773 resultArray[resultIndex].setFConst(0.0f);
1774 }
1775 ++resultIndex;
1776 }
1777 }
1778 }
1779 else
1780 {
1781 while (resultIndex < resultSize)
1782 {
1783 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
1784 ++resultIndex;
1785 }
1786 }
1787 ASSERT(resultIndex == resultSize);
1788 return resultArray;
1789 }
1790 else if (aggregate->isMatrix() && argumentConstant->isMatrix())
1791 {
1792 // The special case of constructing a matrix from a matrix.
1793 int argumentCols = argumentConstant->getType().getCols();
1794 int argumentRows = argumentConstant->getType().getRows();
1795 int resultCols = aggregate->getType().getCols();
1796 int resultRows = aggregate->getType().getRows();
1797 for (int col = 0; col < resultCols; ++col)
1798 {
1799 for (int row = 0; row < resultRows; ++row)
1800 {
1801 if (col < argumentCols && row < argumentRows)
1802 {
1803 resultArray[resultIndex].cast(basicType,
1804 argumentUnionArray[col * argumentRows + row]);
1805 }
1806 else if (col == row)
1807 {
1808 resultArray[resultIndex].setFConst(1.0f);
1809 }
1810 else
1811 {
1812 resultArray[resultIndex].setFConst(0.0f);
1813 }
1814 ++resultIndex;
1815 }
1816 }
1817 ASSERT(resultIndex == resultSize);
1818 return resultArray;
1819 }
1820 }
1821
1822 for (TIntermNode *&argument : *aggregate->getSequence())
1823 {
1824 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
1825 size_t argumentSize = argumentConstant->getType().getObjectSize();
1826 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
1827 for (size_t i = 0u; i < argumentSize; ++i)
1828 {
1829 if (resultIndex >= resultSize)
1830 break;
1831 resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
1832 ++resultIndex;
1833 }
1834 }
1835 ASSERT(resultIndex == resultSize);
1836 return resultArray;
1837}
1838
1839// static
Olli Etuahof119a262016-08-19 15:54:22 +03001840TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
1841 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +05301842{
Olli Etuahob43846e2015-06-02 18:18:57 +03001843 TOperator op = aggregate->getOp();
Arun Patole274f0702015-05-05 13:33:30 +05301844 TIntermSequence *sequence = aggregate->getSequence();
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001845 unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001846 std::vector<const TConstantUnion *> unionArrays(paramsCount);
Arun Patole274f0702015-05-05 13:33:30 +05301847 std::vector<size_t> objectSizes(paramsCount);
Olli Etuahob43846e2015-06-02 18:18:57 +03001848 size_t maxObjectSize = 0;
Arun Patole274f0702015-05-05 13:33:30 +05301849 TBasicType basicType = EbtVoid;
1850 TSourceLoc loc;
1851 for (unsigned int i = 0; i < paramsCount; i++)
1852 {
1853 TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
Olli Etuahob43846e2015-06-02 18:18:57 +03001854 ASSERT(paramConstant != nullptr); // Should be checked already.
Arun Patole274f0702015-05-05 13:33:30 +05301855
1856 if (i == 0)
1857 {
1858 basicType = paramConstant->getType().getBasicType();
1859 loc = paramConstant->getLine();
1860 }
1861 unionArrays[i] = paramConstant->getUnionArrayPointer();
1862 objectSizes[i] = paramConstant->getType().getObjectSize();
Olli Etuahob43846e2015-06-02 18:18:57 +03001863 if (objectSizes[i] > maxObjectSize)
1864 maxObjectSize = objectSizes[i];
Arun Patole274f0702015-05-05 13:33:30 +05301865 }
1866
Olli Etuahod5da5052016-08-29 13:16:55 +03001867 if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
Arun Patole7fa33552015-06-10 15:15:18 +05301868 {
1869 for (unsigned int i = 0; i < paramsCount; i++)
1870 if (objectSizes[i] != maxObjectSize)
1871 unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
1872 }
Arun Patole274f0702015-05-05 13:33:30 +05301873
Olli Etuahob43846e2015-06-02 18:18:57 +03001874 TConstantUnion *resultArray = nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05301875 if (paramsCount == 2)
1876 {
1877 //
1878 // Binary built-in
1879 //
1880 switch (op)
1881 {
Olli Etuahof119a262016-08-19 15:54:22 +03001882 case EOpAtan:
Arun Patolebf790422015-05-18 17:53:04 +05301883 {
Olli Etuahof119a262016-08-19 15:54:22 +03001884 ASSERT(basicType == EbtFloat);
1885 resultArray = new TConstantUnion[maxObjectSize];
1886 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05301887 {
Olli Etuahof119a262016-08-19 15:54:22 +03001888 float y = unionArrays[0][i].getFConst();
1889 float x = unionArrays[1][i].getFConst();
1890 // Results are undefined if x and y are both 0.
1891 if (x == 0.0f && y == 0.0f)
1892 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
1893 &resultArray[i]);
1894 else
1895 resultArray[i].setFConst(atan2f(y, x));
Arun Patolebf790422015-05-18 17:53:04 +05301896 }
Olli Etuahof119a262016-08-19 15:54:22 +03001897 break;
Arun Patolebf790422015-05-18 17:53:04 +05301898 }
Arun Patolebf790422015-05-18 17:53:04 +05301899
Olli Etuahof119a262016-08-19 15:54:22 +03001900 case EOpPow:
Arun Patolebf790422015-05-18 17:53:04 +05301901 {
Olli Etuahof119a262016-08-19 15:54:22 +03001902 ASSERT(basicType == EbtFloat);
1903 resultArray = new TConstantUnion[maxObjectSize];
1904 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05301905 {
Olli Etuahof119a262016-08-19 15:54:22 +03001906 float x = unionArrays[0][i].getFConst();
1907 float y = unionArrays[1][i].getFConst();
1908 // Results are undefined if x < 0.
1909 // Results are undefined if x = 0 and y <= 0.
1910 if (x < 0.0f)
1911 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
1912 &resultArray[i]);
1913 else if (x == 0.0f && y <= 0.0f)
1914 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
1915 &resultArray[i]);
1916 else
1917 resultArray[i].setFConst(powf(x, y));
Arun Patolebf790422015-05-18 17:53:04 +05301918 }
Olli Etuahof119a262016-08-19 15:54:22 +03001919 break;
Arun Patolebf790422015-05-18 17:53:04 +05301920 }
Arun Patolebf790422015-05-18 17:53:04 +05301921
Olli Etuahof119a262016-08-19 15:54:22 +03001922 case EOpMod:
Arun Patolebf790422015-05-18 17:53:04 +05301923 {
Olli Etuahof119a262016-08-19 15:54:22 +03001924 ASSERT(basicType == EbtFloat);
1925 resultArray = new TConstantUnion[maxObjectSize];
1926 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05301927 {
Olli Etuahof119a262016-08-19 15:54:22 +03001928 float x = unionArrays[0][i].getFConst();
1929 float y = unionArrays[1][i].getFConst();
1930 resultArray[i].setFConst(x - y * floorf(x / y));
Arun Patolebf790422015-05-18 17:53:04 +05301931 }
Olli Etuahof119a262016-08-19 15:54:22 +03001932 break;
Arun Patolebf790422015-05-18 17:53:04 +05301933 }
Arun Patolebf790422015-05-18 17:53:04 +05301934
Olli Etuahof119a262016-08-19 15:54:22 +03001935 case EOpMin:
Arun Patole274f0702015-05-05 13:33:30 +05301936 {
Olli Etuahob43846e2015-06-02 18:18:57 +03001937 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05301938 for (size_t i = 0; i < maxObjectSize; i++)
1939 {
1940 switch (basicType)
1941 {
Olli Etuahof119a262016-08-19 15:54:22 +03001942 case EbtFloat:
1943 resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(),
1944 unionArrays[1][i].getFConst()));
1945 break;
1946 case EbtInt:
1947 resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(),
1948 unionArrays[1][i].getIConst()));
1949 break;
1950 case EbtUInt:
1951 resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(),
1952 unionArrays[1][i].getUConst()));
1953 break;
1954 default:
1955 UNREACHABLE();
1956 break;
Arun Patole274f0702015-05-05 13:33:30 +05301957 }
1958 }
Olli Etuahof119a262016-08-19 15:54:22 +03001959 break;
Arun Patole274f0702015-05-05 13:33:30 +05301960 }
Arun Patole274f0702015-05-05 13:33:30 +05301961
Olli Etuahof119a262016-08-19 15:54:22 +03001962 case EOpMax:
Arun Patole274f0702015-05-05 13:33:30 +05301963 {
Olli Etuahob43846e2015-06-02 18:18:57 +03001964 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05301965 for (size_t i = 0; i < maxObjectSize; i++)
1966 {
1967 switch (basicType)
1968 {
Olli Etuahof119a262016-08-19 15:54:22 +03001969 case EbtFloat:
1970 resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(),
1971 unionArrays[1][i].getFConst()));
1972 break;
1973 case EbtInt:
1974 resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(),
1975 unionArrays[1][i].getIConst()));
1976 break;
1977 case EbtUInt:
1978 resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(),
1979 unionArrays[1][i].getUConst()));
1980 break;
1981 default:
1982 UNREACHABLE();
1983 break;
Arun Patole274f0702015-05-05 13:33:30 +05301984 }
1985 }
Olli Etuahof119a262016-08-19 15:54:22 +03001986 break;
Arun Patole274f0702015-05-05 13:33:30 +05301987 }
Arun Patole274f0702015-05-05 13:33:30 +05301988
Olli Etuahof119a262016-08-19 15:54:22 +03001989 case EOpStep:
Arun Patolebf790422015-05-18 17:53:04 +05301990 {
Olli Etuahof119a262016-08-19 15:54:22 +03001991 ASSERT(basicType == EbtFloat);
1992 resultArray = new TConstantUnion[maxObjectSize];
1993 for (size_t i = 0; i < maxObjectSize; i++)
1994 resultArray[i].setFConst(
1995 unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f
1996 : 1.0f);
1997 break;
Arun Patolebf790422015-05-18 17:53:04 +05301998 }
Arun Patolebf790422015-05-18 17:53:04 +05301999
Olli Etuahof119a262016-08-19 15:54:22 +03002000 case EOpLessThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302001 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002002 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302003 for (size_t i = 0; i < maxObjectSize; i++)
2004 {
2005 switch (basicType)
2006 {
Olli Etuahof119a262016-08-19 15:54:22 +03002007 case EbtFloat:
2008 resultArray[i].setBConst(unionArrays[0][i].getFConst() <
2009 unionArrays[1][i].getFConst());
2010 break;
2011 case EbtInt:
2012 resultArray[i].setBConst(unionArrays[0][i].getIConst() <
2013 unionArrays[1][i].getIConst());
2014 break;
2015 case EbtUInt:
2016 resultArray[i].setBConst(unionArrays[0][i].getUConst() <
2017 unionArrays[1][i].getUConst());
2018 break;
2019 default:
2020 UNREACHABLE();
2021 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302022 }
2023 }
Olli Etuahof119a262016-08-19 15:54:22 +03002024 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302025 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302026
Olli Etuahof119a262016-08-19 15:54:22 +03002027 case EOpLessThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302028 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002029 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302030 for (size_t i = 0; i < maxObjectSize; i++)
2031 {
2032 switch (basicType)
2033 {
Olli Etuahof119a262016-08-19 15:54:22 +03002034 case EbtFloat:
2035 resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
2036 unionArrays[1][i].getFConst());
2037 break;
2038 case EbtInt:
2039 resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
2040 unionArrays[1][i].getIConst());
2041 break;
2042 case EbtUInt:
2043 resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
2044 unionArrays[1][i].getUConst());
2045 break;
2046 default:
2047 UNREACHABLE();
2048 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302049 }
2050 }
Olli Etuahof119a262016-08-19 15:54:22 +03002051 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302052 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302053
Olli Etuahof119a262016-08-19 15:54:22 +03002054 case EOpGreaterThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302055 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002056 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302057 for (size_t i = 0; i < maxObjectSize; i++)
2058 {
2059 switch (basicType)
2060 {
Olli Etuahof119a262016-08-19 15:54:22 +03002061 case EbtFloat:
2062 resultArray[i].setBConst(unionArrays[0][i].getFConst() >
2063 unionArrays[1][i].getFConst());
2064 break;
2065 case EbtInt:
2066 resultArray[i].setBConst(unionArrays[0][i].getIConst() >
2067 unionArrays[1][i].getIConst());
2068 break;
2069 case EbtUInt:
2070 resultArray[i].setBConst(unionArrays[0][i].getUConst() >
2071 unionArrays[1][i].getUConst());
2072 break;
2073 default:
2074 UNREACHABLE();
2075 break;
Olli Etuahob43846e2015-06-02 18:18:57 +03002076 }
2077 }
Olli Etuahof119a262016-08-19 15:54:22 +03002078 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302079 }
Olli Etuahof119a262016-08-19 15:54:22 +03002080 case EOpGreaterThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302081 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002082 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302083 for (size_t i = 0; i < maxObjectSize; i++)
2084 {
2085 switch (basicType)
2086 {
Olli Etuahof119a262016-08-19 15:54:22 +03002087 case EbtFloat:
2088 resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
2089 unionArrays[1][i].getFConst());
2090 break;
2091 case EbtInt:
2092 resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
2093 unionArrays[1][i].getIConst());
2094 break;
2095 case EbtUInt:
2096 resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
2097 unionArrays[1][i].getUConst());
2098 break;
2099 default:
2100 UNREACHABLE();
2101 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302102 }
2103 }
2104 }
2105 break;
2106
Olli Etuahof119a262016-08-19 15:54:22 +03002107 case EOpVectorEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302108 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002109 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302110 for (size_t i = 0; i < maxObjectSize; i++)
2111 {
2112 switch (basicType)
2113 {
Olli Etuahof119a262016-08-19 15:54:22 +03002114 case EbtFloat:
2115 resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
2116 unionArrays[1][i].getFConst());
2117 break;
2118 case EbtInt:
2119 resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
2120 unionArrays[1][i].getIConst());
2121 break;
2122 case EbtUInt:
2123 resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
2124 unionArrays[1][i].getUConst());
2125 break;
2126 case EbtBool:
2127 resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
2128 unionArrays[1][i].getBConst());
2129 break;
2130 default:
2131 UNREACHABLE();
2132 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302133 }
2134 }
Olli Etuahof119a262016-08-19 15:54:22 +03002135 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302136 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302137
Olli Etuahof119a262016-08-19 15:54:22 +03002138 case EOpVectorNotEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302139 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002140 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302141 for (size_t i = 0; i < maxObjectSize; i++)
2142 {
2143 switch (basicType)
2144 {
Olli Etuahof119a262016-08-19 15:54:22 +03002145 case EbtFloat:
2146 resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
2147 unionArrays[1][i].getFConst());
2148 break;
2149 case EbtInt:
2150 resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
2151 unionArrays[1][i].getIConst());
2152 break;
2153 case EbtUInt:
2154 resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
2155 unionArrays[1][i].getUConst());
2156 break;
2157 case EbtBool:
2158 resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
2159 unionArrays[1][i].getBConst());
2160 break;
2161 default:
2162 UNREACHABLE();
2163 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302164 }
2165 }
Olli Etuahof119a262016-08-19 15:54:22 +03002166 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302167 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302168
Olli Etuahof119a262016-08-19 15:54:22 +03002169 case EOpDistance:
Arun Patole1155ddd2015-06-05 18:04:36 +05302170 {
Olli Etuahof119a262016-08-19 15:54:22 +03002171 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302172 TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002173 resultArray = new TConstantUnion();
Arun Patole1155ddd2015-06-05 18:04:36 +05302174 for (size_t i = 0; i < maxObjectSize; i++)
2175 {
2176 float x = unionArrays[0][i].getFConst();
2177 float y = unionArrays[1][i].getFConst();
2178 distanceArray[i].setFConst(x - y);
2179 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002180 resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
Olli Etuahof119a262016-08-19 15:54:22 +03002181 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302182 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302183
Olli Etuahof119a262016-08-19 15:54:22 +03002184 case EOpDot:
2185 ASSERT(basicType == EbtFloat);
Olli Etuahob43846e2015-06-02 18:18:57 +03002186 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03002187 resultArray->setFConst(
2188 VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
2189 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302190
Olli Etuahof119a262016-08-19 15:54:22 +03002191 case EOpCross:
Arun Patole1155ddd2015-06-05 18:04:36 +05302192 {
Olli Etuahof119a262016-08-19 15:54:22 +03002193 ASSERT(basicType == EbtFloat && maxObjectSize == 3);
Olli Etuahob43846e2015-06-02 18:18:57 +03002194 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002195 float x0 = unionArrays[0][0].getFConst();
2196 float x1 = unionArrays[0][1].getFConst();
2197 float x2 = unionArrays[0][2].getFConst();
2198 float y0 = unionArrays[1][0].getFConst();
2199 float y1 = unionArrays[1][1].getFConst();
2200 float y2 = unionArrays[1][2].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002201 resultArray[0].setFConst(x1 * y2 - y1 * x2);
2202 resultArray[1].setFConst(x2 * y0 - y2 * x0);
2203 resultArray[2].setFConst(x0 * y1 - y0 * x1);
Olli Etuahof119a262016-08-19 15:54:22 +03002204 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302205 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302206
Olli Etuahof119a262016-08-19 15:54:22 +03002207 case EOpReflect:
Arun Patole1155ddd2015-06-05 18:04:36 +05302208 {
Olli Etuahof119a262016-08-19 15:54:22 +03002209 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302210 // genType reflect (genType I, genType N) :
Olli Etuahof119a262016-08-19 15:54:22 +03002211 // For the incident vector I and surface orientation N, returns the reflection
2212 // direction:
Arun Patole1155ddd2015-06-05 18:04:36 +05302213 // I - 2 * dot(N, I) * N.
Olli Etuahof119a262016-08-19 15:54:22 +03002214 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302215 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2216 for (size_t i = 0; i < maxObjectSize; i++)
2217 {
2218 float result = unionArrays[0][i].getFConst() -
2219 2.0f * dotProduct * unionArrays[1][i].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002220 resultArray[i].setFConst(result);
Arun Patole1155ddd2015-06-05 18:04:36 +05302221 }
Olli Etuahof119a262016-08-19 15:54:22 +03002222 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302223 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302224
Olli Etuahof119a262016-08-19 15:54:22 +03002225 case EOpMul:
Arun Patole7fa33552015-06-10 15:15:18 +05302226 {
Olli Etuahof119a262016-08-19 15:54:22 +03002227 ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
2228 (*sequence)[1]->getAsTyped()->isMatrix());
Arun Patole7fa33552015-06-10 15:15:18 +05302229 // Perform component-wise matrix multiplication.
2230 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002231 int size = (*sequence)[0]->getAsTyped()->getNominalSize();
Arun Patole7fa33552015-06-10 15:15:18 +05302232 angle::Matrix<float> result =
2233 GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
2234 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002235 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302236 }
Arun Patole7fa33552015-06-10 15:15:18 +05302237
Olli Etuahof119a262016-08-19 15:54:22 +03002238 case EOpOuterProduct:
Arun Patole7fa33552015-06-10 15:15:18 +05302239 {
Olli Etuahof119a262016-08-19 15:54:22 +03002240 ASSERT(basicType == EbtFloat);
Arun Patole7fa33552015-06-10 15:15:18 +05302241 size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
2242 size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
Olli Etuahof119a262016-08-19 15:54:22 +03002243 resultArray = new TConstantUnion[numRows * numCols];
Arun Patole7fa33552015-06-10 15:15:18 +05302244 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03002245 GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
2246 .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
Arun Patole7fa33552015-06-10 15:15:18 +05302247 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002248 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302249 }
Arun Patole7fa33552015-06-10 15:15:18 +05302250
Olli Etuahof119a262016-08-19 15:54:22 +03002251 default:
2252 UNREACHABLE();
2253 // TODO: Add constant folding support for other built-in operations that take 2
2254 // parameters and not handled above.
2255 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302256 }
2257 }
2258 else if (paramsCount == 3)
2259 {
2260 //
2261 // Ternary built-in
2262 //
2263 switch (op)
2264 {
Olli Etuahof119a262016-08-19 15:54:22 +03002265 case EOpClamp:
Arun Patole274f0702015-05-05 13:33:30 +05302266 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002267 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302268 for (size_t i = 0; i < maxObjectSize; i++)
2269 {
2270 switch (basicType)
2271 {
Olli Etuahof119a262016-08-19 15:54:22 +03002272 case EbtFloat:
Arun Patole274f0702015-05-05 13:33:30 +05302273 {
Olli Etuahof119a262016-08-19 15:54:22 +03002274 float x = unionArrays[0][i].getFConst();
Arun Patole274f0702015-05-05 13:33:30 +05302275 float min = unionArrays[1][i].getFConst();
2276 float max = unionArrays[2][i].getFConst();
2277 // Results are undefined if min > max.
2278 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002279 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2280 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302281 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002282 resultArray[i].setFConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002283 break;
Arun Patole274f0702015-05-05 13:33:30 +05302284 }
Olli Etuahof119a262016-08-19 15:54:22 +03002285
2286 case EbtInt:
Arun Patole274f0702015-05-05 13:33:30 +05302287 {
Olli Etuahof119a262016-08-19 15:54:22 +03002288 int x = unionArrays[0][i].getIConst();
Arun Patole274f0702015-05-05 13:33:30 +05302289 int min = unionArrays[1][i].getIConst();
2290 int max = unionArrays[2][i].getIConst();
2291 // Results are undefined if min > max.
2292 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002293 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2294 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302295 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002296 resultArray[i].setIConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002297 break;
Arun Patole274f0702015-05-05 13:33:30 +05302298 }
Olli Etuahof119a262016-08-19 15:54:22 +03002299 case EbtUInt:
Arun Patole274f0702015-05-05 13:33:30 +05302300 {
Olli Etuahof119a262016-08-19 15:54:22 +03002301 unsigned int x = unionArrays[0][i].getUConst();
Arun Patole274f0702015-05-05 13:33:30 +05302302 unsigned int min = unionArrays[1][i].getUConst();
2303 unsigned int max = unionArrays[2][i].getUConst();
2304 // Results are undefined if min > max.
2305 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002306 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2307 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302308 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002309 resultArray[i].setUConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002310 break;
Arun Patole274f0702015-05-05 13:33:30 +05302311 }
Olli Etuahof119a262016-08-19 15:54:22 +03002312 default:
2313 UNREACHABLE();
2314 break;
Arun Patole274f0702015-05-05 13:33:30 +05302315 }
2316 }
Olli Etuahof119a262016-08-19 15:54:22 +03002317 break;
Arun Patole274f0702015-05-05 13:33:30 +05302318 }
Arun Patole274f0702015-05-05 13:33:30 +05302319
Olli Etuahof119a262016-08-19 15:54:22 +03002320 case EOpMix:
Arun Patolebf790422015-05-18 17:53:04 +05302321 {
Olli Etuahof119a262016-08-19 15:54:22 +03002322 ASSERT(basicType == EbtFloat);
2323 resultArray = new TConstantUnion[maxObjectSize];
2324 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302325 {
Olli Etuahof119a262016-08-19 15:54:22 +03002326 float x = unionArrays[0][i].getFConst();
2327 float y = unionArrays[1][i].getFConst();
2328 TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
2329 if (type == EbtFloat)
Arun Patolebf790422015-05-18 17:53:04 +05302330 {
Olli Etuahof119a262016-08-19 15:54:22 +03002331 // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
2332 float a = unionArrays[2][i].getFConst();
2333 resultArray[i].setFConst(x * (1.0f - a) + y * a);
2334 }
2335 else // 3rd parameter is EbtBool
2336 {
2337 ASSERT(type == EbtBool);
2338 // Selects which vector each returned component comes from.
2339 // For a component of a that is false, the corresponding component of x is
2340 // returned.
2341 // For a component of a that is true, the corresponding component of y is
2342 // returned.
2343 bool a = unionArrays[2][i].getBConst();
2344 resultArray[i].setFConst(a ? y : x);
Arun Patolebf790422015-05-18 17:53:04 +05302345 }
2346 }
Olli Etuahof119a262016-08-19 15:54:22 +03002347 break;
Arun Patolebf790422015-05-18 17:53:04 +05302348 }
Arun Patolebf790422015-05-18 17:53:04 +05302349
Olli Etuahof119a262016-08-19 15:54:22 +03002350 case EOpSmoothStep:
Arun Patolebf790422015-05-18 17:53:04 +05302351 {
Olli Etuahof119a262016-08-19 15:54:22 +03002352 ASSERT(basicType == EbtFloat);
2353 resultArray = new TConstantUnion[maxObjectSize];
2354 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302355 {
Olli Etuahof119a262016-08-19 15:54:22 +03002356 float edge0 = unionArrays[0][i].getFConst();
2357 float edge1 = unionArrays[1][i].getFConst();
2358 float x = unionArrays[2][i].getFConst();
2359 // Results are undefined if edge0 >= edge1.
2360 if (edge0 >= edge1)
Arun Patolebf790422015-05-18 17:53:04 +05302361 {
Olli Etuahof119a262016-08-19 15:54:22 +03002362 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2363 &resultArray[i]);
2364 }
2365 else
2366 {
2367 // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
2368 // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
2369 float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
2370 resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
Arun Patolebf790422015-05-18 17:53:04 +05302371 }
2372 }
Olli Etuahof119a262016-08-19 15:54:22 +03002373 break;
Arun Patolebf790422015-05-18 17:53:04 +05302374 }
Arun Patolebf790422015-05-18 17:53:04 +05302375
Olli Etuahof119a262016-08-19 15:54:22 +03002376 case EOpFaceForward:
Arun Patole1155ddd2015-06-05 18:04:36 +05302377 {
Olli Etuahof119a262016-08-19 15:54:22 +03002378 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302379 // genType faceforward(genType N, genType I, genType Nref) :
2380 // If dot(Nref, I) < 0 return N, otherwise return -N.
Olli Etuahof119a262016-08-19 15:54:22 +03002381 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302382 float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
2383 for (size_t i = 0; i < maxObjectSize; i++)
2384 {
2385 if (dotProduct < 0)
Olli Etuahob43846e2015-06-02 18:18:57 +03002386 resultArray[i].setFConst(unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302387 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002388 resultArray[i].setFConst(-unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302389 }
Olli Etuahof119a262016-08-19 15:54:22 +03002390 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302391 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302392
Olli Etuahof119a262016-08-19 15:54:22 +03002393 case EOpRefract:
Arun Patole1155ddd2015-06-05 18:04:36 +05302394 {
Olli Etuahof119a262016-08-19 15:54:22 +03002395 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302396 // genType refract(genType I, genType N, float eta) :
Olli Etuahof119a262016-08-19 15:54:22 +03002397 // For the incident vector I and surface normal N, and the ratio of indices of
2398 // refraction eta,
Arun Patole1155ddd2015-06-05 18:04:36 +05302399 // return the refraction vector. The result is computed by
2400 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
2401 // if (k < 0.0)
2402 // return genType(0.0)
2403 // else
2404 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
Olli Etuahof119a262016-08-19 15:54:22 +03002405 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302406 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2407 for (size_t i = 0; i < maxObjectSize; i++)
2408 {
2409 float eta = unionArrays[2][i].getFConst();
Olli Etuahof119a262016-08-19 15:54:22 +03002410 float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
Arun Patole1155ddd2015-06-05 18:04:36 +05302411 if (k < 0.0f)
Olli Etuahob43846e2015-06-02 18:18:57 +03002412 resultArray[i].setFConst(0.0f);
Arun Patole1155ddd2015-06-05 18:04:36 +05302413 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002414 resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
Olli Etuahof119a262016-08-19 15:54:22 +03002415 (eta * dotProduct + sqrtf(k)) *
2416 unionArrays[1][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302417 }
Olli Etuahof119a262016-08-19 15:54:22 +03002418 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302419 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302420
Olli Etuahof119a262016-08-19 15:54:22 +03002421 default:
2422 UNREACHABLE();
2423 // TODO: Add constant folding support for other built-in operations that take 3
2424 // parameters and not handled above.
2425 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302426 }
2427 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002428 return resultArray;
Arun Patole274f0702015-05-05 13:33:30 +05302429}
2430
2431// static
Jamie Madillb1a85f42014-08-19 15:23:24 -04002432TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
2433{
2434 if (hashFunction == NULL || name.empty())
2435 return name;
2436 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
2437 TStringStream stream;
2438 stream << HASHED_NAME_PREFIX << std::hex << number;
2439 TString hashedName = stream.str();
2440 return hashedName;
2441}
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002442
2443void TIntermTraverser::updateTree()
2444{
Olli Etuahoa6f22092015-05-08 18:31:10 +03002445 for (size_t ii = 0; ii < mInsertions.size(); ++ii)
2446 {
2447 const NodeInsertMultipleEntry &insertion = mInsertions[ii];
2448 ASSERT(insertion.parent);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002449 if (!insertion.insertionsAfter.empty())
2450 {
2451 bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
2452 insertion.insertionsAfter);
2453 ASSERT(inserted);
2454 UNUSED_ASSERTION_VARIABLE(inserted);
2455 }
2456 if (!insertion.insertionsBefore.empty())
2457 {
2458 bool inserted =
2459 insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
2460 ASSERT(inserted);
2461 UNUSED_ASSERTION_VARIABLE(inserted);
2462 }
Olli Etuahoa6f22092015-05-08 18:31:10 +03002463 }
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002464 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
2465 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002466 const NodeUpdateEntry &replacement = mReplacements[ii];
2467 ASSERT(replacement.parent);
2468 bool replaced = replacement.parent->replaceChildNode(
2469 replacement.original, replacement.replacement);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002470 ASSERT(replaced);
Olli Etuahod57e0db2015-04-24 15:05:08 +03002471 UNUSED_ASSERTION_VARIABLE(replaced);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002472
Olli Etuahocd94ef92015-04-16 19:18:10 +03002473 if (!replacement.originalBecomesChildOfReplacement)
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002474 {
2475 // In AST traversing, a parent is visited before its children.
Olli Etuahocd94ef92015-04-16 19:18:10 +03002476 // After we replace a node, if its immediate child is to
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002477 // be replaced, we need to make sure we don't update the replaced
2478 // node; instead, we update the replacement node.
2479 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
2480 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002481 NodeUpdateEntry &replacement2 = mReplacements[jj];
2482 if (replacement2.parent == replacement.original)
2483 replacement2.parent = replacement.replacement;
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002484 }
2485 }
2486 }
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03002487 for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
2488 {
2489 const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
2490 ASSERT(replacement.parent);
2491 bool replaced = replacement.parent->replaceChildNodeWithMultiple(
2492 replacement.original, replacement.replacements);
2493 ASSERT(replaced);
Olli Etuahod57e0db2015-04-24 15:05:08 +03002494 UNUSED_ASSERTION_VARIABLE(replaced);
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03002495 }
Olli Etuahod4f303e2015-05-20 17:09:06 +03002496
Jamie Madill03d863c2016-07-27 18:15:53 -04002497 clearReplacementQueue();
2498}
2499
2500void TIntermTraverser::clearReplacementQueue()
2501{
Olli Etuahod4f303e2015-05-20 17:09:06 +03002502 mReplacements.clear();
2503 mMultiReplacements.clear();
Jamie Madill03d863c2016-07-27 18:15:53 -04002504 mInsertions.clear();
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002505}
Jamie Madill1048e432016-07-23 18:51:28 -04002506
Jamie Madill03d863c2016-07-27 18:15:53 -04002507void TIntermTraverser::queueReplacement(TIntermNode *original,
2508 TIntermNode *replacement,
2509 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002510{
Jamie Madill03d863c2016-07-27 18:15:53 -04002511 queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
Jamie Madill1048e432016-07-23 18:51:28 -04002512}
2513
Jamie Madill03d863c2016-07-27 18:15:53 -04002514void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
2515 TIntermNode *original,
2516 TIntermNode *replacement,
2517 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002518{
Jamie Madill03d863c2016-07-27 18:15:53 -04002519 bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
2520 mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
Jamie Madill1048e432016-07-23 18:51:28 -04002521}