blob: 1299048c699f4832dac867ac28e355727da23b04 [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
Jamie Madill45bcc782016-11-07 13:58:48 -050026namespace sh
27{
28
Jamie Madillb1a85f42014-08-19 15:23:24 -040029namespace
30{
31
Jamie Madilld7b1ab52016-12-12 14:42:19 -050032const float kPi = 3.14159265358979323846f;
Arun Patole9dea48f2015-04-02 11:45:09 +053033const float kDegreesToRadiansMultiplier = kPi / 180.0f;
34const float kRadiansToDegreesMultiplier = 180.0f / kPi;
35
Jamie Madillb1a85f42014-08-19 15:23:24 -040036TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
37{
38 return left > right ? left : right;
39}
40
Arun Patole274f0702015-05-05 13:33:30 +053041TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
42{
43 TConstantUnion *constUnion = new TConstantUnion[size];
44 for (unsigned int i = 0; i < size; ++i)
Jamie Madilld7b1ab52016-12-12 14:42:19 -050045 constUnion[i] = constant;
Arun Patole274f0702015-05-05 13:33:30 +053046
47 return constUnion;
48}
49
Olli Etuahof119a262016-08-19 15:54:22 +030050void UndefinedConstantFoldingError(const TSourceLoc &loc,
51 TOperator op,
52 TBasicType basicType,
53 TDiagnostics *diagnostics,
54 TConstantUnion *result)
Arun Patolebf790422015-05-18 17:53:04 +053055{
Olli Etuahof119a262016-08-19 15:54:22 +030056 diagnostics->warning(loc, "operation result is undefined for the values passed in",
57 GetOperatorString(op), "");
Arun Patolebf790422015-05-18 17:53:04 +053058
59 switch (basicType)
60 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050061 case EbtFloat:
62 result->setFConst(0.0f);
63 break;
64 case EbtInt:
65 result->setIConst(0);
66 break;
67 case EbtUInt:
68 result->setUConst(0u);
69 break;
70 case EbtBool:
71 result->setBConst(false);
72 break;
73 default:
74 break;
Arun Patolebf790422015-05-18 17:53:04 +053075 }
76}
77
Olli Etuaho5c0e0232015-11-11 15:55:59 +020078float VectorLength(const TConstantUnion *paramArray, size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053079{
80 float result = 0.0f;
81 for (size_t i = 0; i < paramArraySize; i++)
82 {
83 float f = paramArray[i].getFConst();
84 result += f * f;
85 }
86 return sqrtf(result);
87}
88
Olli Etuaho5c0e0232015-11-11 15:55:59 +020089float VectorDotProduct(const TConstantUnion *paramArray1,
90 const TConstantUnion *paramArray2,
91 size_t paramArraySize)
Arun Patole1155ddd2015-06-05 18:04:36 +053092{
93 float result = 0.0f;
94 for (size_t i = 0; i < paramArraySize; i++)
95 result += paramArray1[i].getFConst() * paramArray2[i].getFConst();
96 return result;
97}
98
Olli Etuaho3272a6d2016-08-29 17:54:50 +030099TIntermTyped *CreateFoldedNode(const TConstantUnion *constArray,
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200100 const TIntermTyped *originalNode,
101 TQualifier qualifier)
Olli Etuahob43846e2015-06-02 18:18:57 +0300102{
103 if (constArray == nullptr)
104 {
105 return nullptr;
106 }
107 TIntermTyped *folded = new TIntermConstantUnion(constArray, originalNode->getType());
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200108 folded->getTypePointer()->setQualifier(qualifier);
Olli Etuahob43846e2015-06-02 18:18:57 +0300109 folded->setLine(originalNode->getLine());
110 return folded;
111}
112
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200113angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray,
114 const unsigned int &rows,
115 const unsigned int &cols)
Arun Patole7fa33552015-06-10 15:15:18 +0530116{
117 std::vector<float> elements;
118 for (size_t i = 0; i < rows * cols; i++)
119 elements.push_back(paramArray[i].getFConst());
120 // Transpose is used since the Matrix constructor expects arguments in row-major order,
Olli Etuahod5da5052016-08-29 13:16:55 +0300121 // whereas the paramArray is in column-major order. Rows/cols parameters are also flipped below
122 // so that the created matrix will have the expected dimensions after the transpose.
123 return angle::Matrix<float>(elements, cols, rows).transpose();
Arun Patole7fa33552015-06-10 15:15:18 +0530124}
125
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200126angle::Matrix<float> GetMatrix(const TConstantUnion *paramArray, const unsigned int &size)
Arun Patole7fa33552015-06-10 15:15:18 +0530127{
128 std::vector<float> elements;
129 for (size_t i = 0; i < size * size; i++)
130 elements.push_back(paramArray[i].getFConst());
131 // Transpose is used since the Matrix constructor expects arguments in row-major order,
132 // whereas the paramArray is in column-major order.
133 return angle::Matrix<float>(elements, size).transpose();
134}
135
136void SetUnionArrayFromMatrix(const angle::Matrix<float> &m, TConstantUnion *resultArray)
137{
138 // Transpose is used since the input Matrix is in row-major order,
139 // whereas the actual result should be in column-major order.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500140 angle::Matrix<float> result = m.transpose();
Arun Patole7fa33552015-06-10 15:15:18 +0530141 std::vector<float> resultElements = result.elements();
142 for (size_t i = 0; i < resultElements.size(); i++)
143 resultArray[i].setFConst(resultElements[i]);
144}
145
Jamie Madillb1a85f42014-08-19 15:23:24 -0400146} // namespace anonymous
147
Jamie Madillb1a85f42014-08-19 15:23:24 -0400148////////////////////////////////////////////////////////////////
149//
150// Member functions of the nodes used for building the tree.
151//
152////////////////////////////////////////////////////////////////
153
Olli Etuahod2a67b92014-10-21 16:42:57 +0300154void TIntermTyped::setTypePreservePrecision(const TType &t)
155{
156 TPrecision precision = getPrecision();
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500157 mType = t;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300158 ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
159 mType.setPrecision(precision);
160}
161
Jamie Madillb1a85f42014-08-19 15:23:24 -0400162#define REPLACE_IF_IS(node, type, original, replacement) \
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500163 if (node == original) \
164 { \
165 node = static_cast<type *>(replacement); \
166 return true; \
Jamie Madillb1a85f42014-08-19 15:23:24 -0400167 }
168
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500169bool TIntermLoop::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400170{
Olli Etuaho3cbb27a2016-07-14 11:55:48 +0300171 ASSERT(original != nullptr); // This risks replacing multiple children.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400172 REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
173 REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
174 REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100175 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400176 return false;
177}
178
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500179bool TIntermBranch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400180{
181 REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement);
182 return false;
183}
184
Olli Etuahob6fa0432016-09-28 16:28:05 +0100185bool TIntermSwizzle::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
186{
187 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
188 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
189 return false;
190}
191
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500192bool TIntermBinary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400193{
194 REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement);
195 REPLACE_IF_IS(mRight, TIntermTyped, original, replacement);
196 return false;
197}
198
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500199bool TIntermUnary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400200{
Olli Etuahoa2234302016-08-31 12:05:39 +0300201 ASSERT(original->getAsTyped()->getType() == replacement->getAsTyped()->getType());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400202 REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement);
203 return false;
204}
205
Olli Etuaho336b1472016-10-05 16:37:55 +0100206bool TIntermFunctionDefinition::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
207{
208 REPLACE_IF_IS(mParameters, TIntermAggregate, original, replacement);
209 REPLACE_IF_IS(mBody, TIntermBlock, original, replacement);
210 return false;
211}
212
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500213bool TIntermAggregate::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400214{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100215 return replaceChildNodeInternal(original, replacement);
216}
217
218bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
219{
220 return replaceChildNodeInternal(original, replacement);
221}
222
Olli Etuaho13389b62016-10-16 11:48:18 +0100223bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
224{
225 return replaceChildNodeInternal(original, replacement);
226}
227
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100228bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
229{
230 for (size_t ii = 0; ii < getSequence()->size(); ++ii)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400231 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100232 REPLACE_IF_IS((*getSequence())[ii], TIntermNode, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400233 }
234 return false;
235}
236
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100237bool TIntermAggregateBase::replaceChildNodeWithMultiple(TIntermNode *original,
238 const TIntermSequence &replacements)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300239{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100240 for (auto it = getSequence()->begin(); it < getSequence()->end(); ++it)
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300241 {
242 if (*it == original)
243 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100244 it = getSequence()->erase(it);
245 getSequence()->insert(it, replacements.begin(), replacements.end());
Olli Etuahofc0e2bc2015-04-16 13:39:56 +0300246 return true;
247 }
248 }
249 return false;
250}
251
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100252bool TIntermAggregateBase::insertChildNodes(TIntermSequence::size_type position,
253 const TIntermSequence &insertions)
Olli Etuahoa6f22092015-05-08 18:31:10 +0300254{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100255 if (position > getSequence()->size())
Olli Etuahoa6f22092015-05-08 18:31:10 +0300256 {
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300257 return false;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300258 }
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100259 auto it = getSequence()->begin() + position;
260 getSequence()->insert(it, insertions.begin(), insertions.end());
Olli Etuaho5d91dda2015-06-18 15:47:46 +0300261 return true;
Olli Etuahoa6f22092015-05-08 18:31:10 +0300262}
263
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200264bool TIntermAggregate::areChildrenConstQualified()
265{
266 for (TIntermNode *&child : mSequence)
267 {
268 TIntermTyped *typed = child->getAsTyped();
269 if (typed && typed->getQualifier() != EvqConst)
270 {
271 return false;
272 }
273 }
274 return true;
275}
276
Olli Etuahod2a67b92014-10-21 16:42:57 +0300277void TIntermAggregate::setPrecisionFromChildren()
278{
Olli Etuahoa4aa4e32015-06-04 15:54:30 +0300279 mGotPrecisionFromChildren = true;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300280 if (getBasicType() == EbtBool)
281 {
282 mType.setPrecision(EbpUndefined);
283 return;
284 }
285
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500286 TPrecision precision = EbpUndefined;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300287 TIntermSequence::iterator childIter = mSequence.begin();
288 while (childIter != mSequence.end())
289 {
290 TIntermTyped *typed = (*childIter)->getAsTyped();
291 if (typed)
292 precision = GetHigherPrecision(typed->getPrecision(), precision);
293 ++childIter;
294 }
295 mType.setPrecision(precision);
296}
297
298void TIntermAggregate::setBuiltInFunctionPrecision()
299{
300 // All built-ins returning bool should be handled as ops, not functions.
301 ASSERT(getBasicType() != EbtBool);
302
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500303 TPrecision precision = EbpUndefined;
Olli Etuahod2a67b92014-10-21 16:42:57 +0300304 TIntermSequence::iterator childIter = mSequence.begin();
305 while (childIter != mSequence.end())
306 {
307 TIntermTyped *typed = (*childIter)->getAsTyped();
308 // ESSL spec section 8: texture functions get their precision from the sampler.
309 if (typed && IsSampler(typed->getBasicType()))
310 {
311 precision = typed->getPrecision();
312 break;
313 }
314 ++childIter;
315 }
316 // ESSL 3.0 spec section 8: textureSize always gets highp precision.
317 // All other functions that take a sampler are assumed to be texture functions.
Olli Etuahobd674552016-10-06 13:28:42 +0100318 if (mFunctionInfo.getName().find("textureSize") == 0)
Olli Etuahod2a67b92014-10-21 16:42:57 +0300319 mType.setPrecision(EbpHigh);
320 else
321 mType.setPrecision(precision);
322}
323
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100324void TIntermBlock::appendStatement(TIntermNode *statement)
325{
Olli Etuaho13389b62016-10-16 11:48:18 +0100326 // Declaration nodes with no children can appear if all the declarators just added constants to
327 // the symbol table instead of generating code. They're no-ops so they aren't added to blocks.
328 if (statement != nullptr && (statement->getAsDeclarationNode() == nullptr ||
329 !statement->getAsDeclarationNode()->getSequence()->empty()))
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100330 {
331 mStatements.push_back(statement);
332 }
333}
334
Olli Etuaho13389b62016-10-16 11:48:18 +0100335void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
336{
337 ASSERT(declarator != nullptr);
338 ASSERT(declarator->getAsSymbolNode() != nullptr ||
339 (declarator->getAsBinaryNode() != nullptr &&
340 declarator->getAsBinaryNode()->getOp() == EOpInitialize));
341 ASSERT(mDeclarators.empty() ||
342 declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType()));
343 mDeclarators.push_back(declarator);
344}
345
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300346bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
347{
348 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
349 REPLACE_IF_IS(mTrueExpression, TIntermTyped, original, replacement);
350 REPLACE_IF_IS(mFalseExpression, TIntermTyped, original, replacement);
351 return false;
352}
353
Olli Etuaho57961272016-09-14 13:57:46 +0300354bool TIntermIfElse::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Jamie Madillb1a85f42014-08-19 15:23:24 -0400355{
356 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100357 REPLACE_IF_IS(mTrueBlock, TIntermBlock, original, replacement);
358 REPLACE_IF_IS(mFalseBlock, TIntermBlock, original, replacement);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400359 return false;
360}
361
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500362bool TIntermSwitch::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200363{
364 REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100365 REPLACE_IF_IS(mStatementList, TIntermBlock, original, replacement);
Olli Etuahoa3a36662015-02-17 13:46:51 +0200366 return false;
367}
368
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500369bool TIntermCase::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200370{
371 REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
372 return false;
373}
374
Olli Etuahod7a25242015-08-18 13:49:45 +0300375TIntermTyped::TIntermTyped(const TIntermTyped &node) : TIntermNode(), mType(node.mType)
376{
377 // Copy constructor is disallowed for TIntermNode in order to disallow it for subclasses that
378 // don't explicitly allow it, so normal TIntermNode constructor is used to construct the copy.
379 // We need to manually copy any fields of TIntermNode besides handling fields in TIntermTyped.
380 mLine = node.mLine;
381}
382
Olli Etuahod4f4c112016-04-15 15:11:24 +0300383bool TIntermTyped::isConstructorWithOnlyConstantUnionParameters()
384{
385 TIntermAggregate *constructor = getAsAggregate();
386 if (!constructor || !constructor->isConstructor())
387 {
388 return false;
389 }
390 for (TIntermNode *&node : *constructor->getSequence())
391 {
392 if (!node->getAsConstantUnion())
393 return false;
394 }
395 return true;
396}
397
Corentin Wallez509e4562016-08-25 14:55:44 -0400398// static
399TIntermTyped *TIntermTyped::CreateIndexNode(int index)
400{
401 TConstantUnion *u = new TConstantUnion[1];
402 u[0].setIConst(index);
403
404 TType type(EbtInt, EbpUndefined, EvqConst, 1);
405 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
406 return node;
407}
408
409// static
410TIntermTyped *TIntermTyped::CreateZero(const TType &type)
411{
412 TType constType(type);
413 constType.setQualifier(EvqConst);
414
415 if (!type.isArray() && type.getBasicType() != EbtStruct)
416 {
417 ASSERT(type.isScalar() || type.isVector() || type.isMatrix());
418
419 size_t size = constType.getObjectSize();
420 TConstantUnion *u = new TConstantUnion[size];
421 for (size_t i = 0; i < size; ++i)
422 {
423 switch (type.getBasicType())
424 {
425 case EbtFloat:
426 u[i].setFConst(0.0f);
427 break;
428 case EbtInt:
429 u[i].setIConst(0);
430 break;
431 case EbtUInt:
432 u[i].setUConst(0u);
433 break;
434 case EbtBool:
435 u[i].setBConst(false);
436 break;
437 default:
438 UNREACHABLE();
439 return nullptr;
440 }
441 }
442
443 TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
444 return node;
445 }
446
447 TIntermAggregate *constructor = new TIntermAggregate(sh::TypeToConstructorOperator(type));
448 constructor->setType(constType);
449
450 if (type.isArray())
451 {
452 TType elementType(type);
453 elementType.clearArrayness();
454
455 size_t arraySize = type.getArraySize();
456 for (size_t i = 0; i < arraySize; ++i)
457 {
458 constructor->getSequence()->push_back(CreateZero(elementType));
459 }
460 }
461 else
462 {
463 ASSERT(type.getBasicType() == EbtStruct);
464
465 TStructure *structure = type.getStruct();
466 for (const auto &field : structure->fields())
467 {
468 constructor->getSequence()->push_back(CreateZero(*field->type()));
469 }
470 }
471
472 return constructor;
473}
474
Corentin Wallez36fd1002016-12-08 11:30:44 -0500475// static
476TIntermTyped *TIntermTyped::CreateBool(bool value)
477{
478 TConstantUnion *u = new TConstantUnion[1];
479 u[0].setBConst(value);
480
481 TType type(EbtBool, EbpUndefined, EvqConst, 1);
482 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
483 return node;
484}
485
Olli Etuahod7a25242015-08-18 13:49:45 +0300486TIntermConstantUnion::TIntermConstantUnion(const TIntermConstantUnion &node) : TIntermTyped(node)
487{
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200488 mUnionArrayPointer = node.mUnionArrayPointer;
Olli Etuahod7a25242015-08-18 13:49:45 +0300489}
490
Olli Etuahobd674552016-10-06 13:28:42 +0100491void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
492{
493 setName(function.getMangledName());
494 setId(function.getUniqueId());
495}
496
Olli Etuahod7a25242015-08-18 13:49:45 +0300497TIntermAggregate::TIntermAggregate(const TIntermAggregate &node)
498 : TIntermOperator(node),
Olli Etuahod7a25242015-08-18 13:49:45 +0300499 mUserDefined(node.mUserDefined),
Olli Etuahod7a25242015-08-18 13:49:45 +0300500 mUseEmulatedFunction(node.mUseEmulatedFunction),
Olli Etuahobd674552016-10-06 13:28:42 +0100501 mGotPrecisionFromChildren(node.mGotPrecisionFromChildren),
502 mFunctionInfo(node.mFunctionInfo)
Olli Etuahod7a25242015-08-18 13:49:45 +0300503{
504 for (TIntermNode *child : node.mSequence)
505 {
506 TIntermTyped *typedChild = child->getAsTyped();
507 ASSERT(typedChild != nullptr);
508 TIntermTyped *childCopy = typedChild->deepCopy();
509 mSequence.push_back(childCopy);
510 }
511}
512
Olli Etuahob6fa0432016-09-28 16:28:05 +0100513TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermTyped(node)
514{
515 TIntermTyped *operandCopy = node.mOperand->deepCopy();
516 ASSERT(operandCopy != nullptr);
517 mOperand = operandCopy;
518}
519
Olli Etuahod7a25242015-08-18 13:49:45 +0300520TIntermBinary::TIntermBinary(const TIntermBinary &node)
521 : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
522{
523 TIntermTyped *leftCopy = node.mLeft->deepCopy();
524 TIntermTyped *rightCopy = node.mRight->deepCopy();
525 ASSERT(leftCopy != nullptr && rightCopy != nullptr);
526 mLeft = leftCopy;
527 mRight = rightCopy;
528}
529
530TIntermUnary::TIntermUnary(const TIntermUnary &node)
531 : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
532{
533 TIntermTyped *operandCopy = node.mOperand->deepCopy();
534 ASSERT(operandCopy != nullptr);
535 mOperand = operandCopy;
536}
537
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300538TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermTyped(node)
Olli Etuahod7a25242015-08-18 13:49:45 +0300539{
Olli Etuahod7a25242015-08-18 13:49:45 +0300540 TIntermTyped *conditionCopy = node.mCondition->deepCopy();
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300541 TIntermTyped *trueCopy = node.mTrueExpression->deepCopy();
542 TIntermTyped *falseCopy = node.mFalseExpression->deepCopy();
Olli Etuahod7a25242015-08-18 13:49:45 +0300543 ASSERT(conditionCopy != nullptr && trueCopy != nullptr && falseCopy != nullptr);
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300544 mCondition = conditionCopy;
545 mTrueExpression = trueCopy;
546 mFalseExpression = falseCopy;
Olli Etuahod7a25242015-08-18 13:49:45 +0300547}
548
Jamie Madillb1a85f42014-08-19 15:23:24 -0400549bool TIntermOperator::isAssignment() const
550{
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300551 return IsAssignment(mOp);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400552}
553
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300554bool TIntermOperator::isMultiplication() const
555{
556 switch (mOp)
557 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500558 case EOpMul:
559 case EOpMatrixTimesMatrix:
560 case EOpMatrixTimesVector:
561 case EOpMatrixTimesScalar:
562 case EOpVectorTimesMatrix:
563 case EOpVectorTimesScalar:
564 return true;
565 default:
566 return false;
Olli Etuaho8f76bcc2015-06-02 13:54:20 +0300567 }
568}
569
Jamie Madillb1a85f42014-08-19 15:23:24 -0400570//
571// returns true if the operator is for one of the constructors
572//
573bool TIntermOperator::isConstructor() const
574{
575 switch (mOp)
576 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500577 case EOpConstructVec2:
578 case EOpConstructVec3:
579 case EOpConstructVec4:
580 case EOpConstructMat2:
581 case EOpConstructMat2x3:
582 case EOpConstructMat2x4:
583 case EOpConstructMat3x2:
584 case EOpConstructMat3:
585 case EOpConstructMat3x4:
586 case EOpConstructMat4x2:
587 case EOpConstructMat4x3:
588 case EOpConstructMat4:
589 case EOpConstructFloat:
590 case EOpConstructIVec2:
591 case EOpConstructIVec3:
592 case EOpConstructIVec4:
593 case EOpConstructInt:
594 case EOpConstructUVec2:
595 case EOpConstructUVec3:
596 case EOpConstructUVec4:
597 case EOpConstructUInt:
598 case EOpConstructBVec2:
599 case EOpConstructBVec3:
600 case EOpConstructBVec4:
601 case EOpConstructBool:
602 case EOpConstructStruct:
603 return true;
604 default:
605 return false;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400606 }
607}
608
Olli Etuaho1dded802016-08-18 18:13:13 +0300609TOperator TIntermBinary::GetMulOpBasedOnOperands(const TType &left, const TType &right)
610{
611 if (left.isMatrix())
612 {
613 if (right.isMatrix())
614 {
615 return EOpMatrixTimesMatrix;
616 }
617 else
618 {
619 if (right.isVector())
620 {
621 return EOpMatrixTimesVector;
622 }
623 else
624 {
625 return EOpMatrixTimesScalar;
626 }
627 }
628 }
629 else
630 {
631 if (right.isMatrix())
632 {
633 if (left.isVector())
634 {
635 return EOpVectorTimesMatrix;
636 }
637 else
638 {
639 return EOpMatrixTimesScalar;
640 }
641 }
642 else
643 {
644 // Neither operand is a matrix.
645 if (left.isVector() == right.isVector())
646 {
647 // Leave as component product.
648 return EOpMul;
649 }
650 else
651 {
652 return EOpVectorTimesScalar;
653 }
654 }
655 }
656}
657
658TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const TType &right)
659{
660 if (left.isMatrix())
661 {
662 if (right.isMatrix())
663 {
664 return EOpMatrixTimesMatrixAssign;
665 }
666 else
667 {
668 // right should be scalar, but this may not be validated yet.
669 return EOpMatrixTimesScalarAssign;
670 }
671 }
672 else
673 {
674 if (right.isMatrix())
675 {
676 // Left should be a vector, but this may not be validated yet.
677 return EOpVectorTimesMatrixAssign;
678 }
679 else
680 {
681 // Neither operand is a matrix.
682 if (left.isVector() == right.isVector())
683 {
684 // Leave as component product.
685 return EOpMulAssign;
686 }
687 else
688 {
689 // left should be vector and right should be scalar, but this may not be validated
690 // yet.
691 return EOpVectorTimesScalarAssign;
692 }
693 }
694 }
695}
696
Jamie Madillb1a85f42014-08-19 15:23:24 -0400697//
698// Make sure the type of a unary operator is appropriate for its
699// combination of operation and operand type.
700//
Olli Etuahoa2234302016-08-31 12:05:39 +0300701void TIntermUnary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400702{
Olli Etuahoa2234302016-08-31 12:05:39 +0300703 TQualifier resultQualifier = EvqTemporary;
704 if (mOperand->getQualifier() == EvqConst)
705 resultQualifier = EvqConst;
706
707 unsigned char operandPrimarySize =
708 static_cast<unsigned char>(mOperand->getType().getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400709 switch (mOp)
710 {
Olli Etuahoa2234302016-08-31 12:05:39 +0300711 case EOpFloatBitsToInt:
712 setType(TType(EbtInt, EbpHigh, resultQualifier, operandPrimarySize));
713 break;
714 case EOpFloatBitsToUint:
715 setType(TType(EbtUInt, EbpHigh, resultQualifier, operandPrimarySize));
716 break;
717 case EOpIntBitsToFloat:
718 case EOpUintBitsToFloat:
719 setType(TType(EbtFloat, EbpHigh, resultQualifier, operandPrimarySize));
720 break;
721 case EOpPackSnorm2x16:
722 case EOpPackUnorm2x16:
723 case EOpPackHalf2x16:
724 setType(TType(EbtUInt, EbpHigh, resultQualifier));
725 break;
726 case EOpUnpackSnorm2x16:
727 case EOpUnpackUnorm2x16:
728 setType(TType(EbtFloat, EbpHigh, resultQualifier, 2));
729 break;
730 case EOpUnpackHalf2x16:
731 setType(TType(EbtFloat, EbpMedium, resultQualifier, 2));
732 break;
733 case EOpAny:
734 case EOpAll:
735 setType(TType(EbtBool, EbpUndefined, resultQualifier));
736 break;
737 case EOpLength:
738 case EOpDeterminant:
739 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier));
740 break;
741 case EOpTranspose:
742 setType(TType(EbtFloat, mOperand->getType().getPrecision(), resultQualifier,
743 static_cast<unsigned char>(mOperand->getType().getRows()),
744 static_cast<unsigned char>(mOperand->getType().getCols())));
745 break;
746 case EOpIsInf:
747 case EOpIsNan:
748 setType(TType(EbtBool, EbpUndefined, resultQualifier, operandPrimarySize));
749 break;
750 default:
751 setType(mOperand->getType());
752 mType.setQualifier(resultQualifier);
753 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400754 }
Olli Etuahoa2234302016-08-31 12:05:39 +0300755}
Jamie Madillb1a85f42014-08-19 15:23:24 -0400756
Olli Etuahob6fa0432016-09-28 16:28:05 +0100757TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
758 : TIntermTyped(TType(EbtFloat, EbpUndefined)),
759 mOperand(operand),
760 mSwizzleOffsets(swizzleOffsets)
761{
762 ASSERT(mSwizzleOffsets.size() <= 4);
763 promote();
764}
765
Olli Etuahoa2234302016-08-31 12:05:39 +0300766TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
767 : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
768{
769 promote();
Jamie Madillb1a85f42014-08-19 15:23:24 -0400770}
771
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300772TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
773 : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
774{
775 promote();
776}
777
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300778TIntermTernary::TIntermTernary(TIntermTyped *cond,
779 TIntermTyped *trueExpression,
780 TIntermTyped *falseExpression)
781 : TIntermTyped(trueExpression->getType()),
782 mCondition(cond),
783 mTrueExpression(trueExpression),
784 mFalseExpression(falseExpression)
785{
786 getTypePointer()->setQualifier(
787 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression));
788}
789
790// static
791TQualifier TIntermTernary::DetermineQualifier(TIntermTyped *cond,
792 TIntermTyped *trueExpression,
793 TIntermTyped *falseExpression)
794{
795 if (cond->getQualifier() == EvqConst && trueExpression->getQualifier() == EvqConst &&
796 falseExpression->getQualifier() == EvqConst)
797 {
798 return EvqConst;
799 }
800 return EvqTemporary;
801}
802
Olli Etuahob6fa0432016-09-28 16:28:05 +0100803void TIntermSwizzle::promote()
804{
805 TQualifier resultQualifier = EvqTemporary;
806 if (mOperand->getQualifier() == EvqConst)
807 resultQualifier = EvqConst;
808
809 auto numFields = mSwizzleOffsets.size();
810 setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
811 static_cast<unsigned char>(numFields)));
812}
813
814bool TIntermSwizzle::hasDuplicateOffsets() const
815{
816 int offsetCount[4] = {0u, 0u, 0u, 0u};
817 for (const auto offset : mSwizzleOffsets)
818 {
819 offsetCount[offset]++;
820 if (offsetCount[offset] > 1)
821 {
822 return true;
823 }
824 }
825 return false;
826}
827
828void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
829{
830 for (const int offset : mSwizzleOffsets)
831 {
832 switch (offset)
833 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500834 case 0:
835 *out << "x";
836 break;
837 case 1:
838 *out << "y";
839 break;
840 case 2:
841 *out << "z";
842 break;
843 case 3:
844 *out << "w";
845 break;
846 default:
847 UNREACHABLE();
Olli Etuahob6fa0432016-09-28 16:28:05 +0100848 }
849 }
850}
851
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100852TQualifier TIntermBinary::GetCommaQualifier(int shaderVersion,
853 const TIntermTyped *left,
854 const TIntermTyped *right)
855{
856 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
857 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
858 right->getQualifier() != EvqConst)
859 {
860 return EvqTemporary;
861 }
862 return EvqConst;
863}
Olli Etuahob6fa0432016-09-28 16:28:05 +0100864
865// Establishes the type of the result of the binary operation.
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300866void TIntermBinary::promote()
Jamie Madillb1a85f42014-08-19 15:23:24 -0400867{
Olli Etuaho1dded802016-08-18 18:13:13 +0300868 ASSERT(!isMultiplication() ||
869 mOp == GetMulOpBasedOnOperands(mLeft->getType(), mRight->getType()));
870
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100871 // Comma is handled as a special case.
872 if (mOp == EOpComma)
873 {
874 setType(mRight->getType());
875 return;
876 }
877
Jamie Madillb1a85f42014-08-19 15:23:24 -0400878 // Base assumption: just make the type the same as the left
879 // operand. Then only deviations from this need be coded.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400880 setType(mLeft->getType());
881
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200882 TQualifier resultQualifier = EvqConst;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400883 // Binary operations results in temporary variables unless both
884 // operands are const.
885 if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst)
886 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200887 resultQualifier = EvqTemporary;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400888 getTypePointer()->setQualifier(EvqTemporary);
889 }
890
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300891 // Handle indexing ops.
892 switch (mOp)
893 {
894 case EOpIndexDirect:
895 case EOpIndexIndirect:
896 if (mLeft->isArray())
897 {
898 mType.clearArrayness();
899 }
900 else if (mLeft->isMatrix())
901 {
902 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier,
903 static_cast<unsigned char>(mLeft->getRows())));
904 }
905 else if (mLeft->isVector())
906 {
907 setType(TType(mLeft->getBasicType(), mLeft->getPrecision(), resultQualifier));
908 }
909 else
910 {
911 UNREACHABLE();
912 }
913 return;
914 case EOpIndexDirectStruct:
915 {
916 const TFieldList &fields = mLeft->getType().getStruct()->fields();
917 const int i = mRight->getAsConstantUnion()->getIConst(0);
918 setType(*fields[i]->type());
919 getTypePointer()->setQualifier(resultQualifier);
920 return;
921 }
922 case EOpIndexDirectInterfaceBlock:
923 {
924 const TFieldList &fields = mLeft->getType().getInterfaceBlock()->fields();
925 const int i = mRight->getAsConstantUnion()->getIConst(0);
926 setType(*fields[i]->type());
927 getTypePointer()->setQualifier(resultQualifier);
928 return;
929 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300930 default:
931 break;
932 }
933
934 ASSERT(mLeft->isArray() == mRight->isArray());
935
936 // The result gets promoted to the highest precision.
937 TPrecision higherPrecision = GetHigherPrecision(mLeft->getPrecision(), mRight->getPrecision());
938 getTypePointer()->setPrecision(higherPrecision);
939
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500940 const int nominalSize = std::max(mLeft->getNominalSize(), mRight->getNominalSize());
Jamie Madillb1a85f42014-08-19 15:23:24 -0400941
942 //
943 // All scalars or structs. Code after this test assumes this case is removed!
944 //
945 if (nominalSize == 1)
946 {
947 switch (mOp)
948 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500949 //
950 // Promote to conditional
951 //
952 case EOpEqual:
953 case EOpNotEqual:
954 case EOpLessThan:
955 case EOpGreaterThan:
956 case EOpLessThanEqual:
957 case EOpGreaterThanEqual:
958 setType(TType(EbtBool, EbpUndefined, resultQualifier));
959 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400960
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500961 //
962 // And and Or operate on conditionals
963 //
964 case EOpLogicalAnd:
965 case EOpLogicalXor:
966 case EOpLogicalOr:
967 ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
968 setType(TType(EbtBool, EbpUndefined, resultQualifier));
969 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400970
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500971 default:
972 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400973 }
Olli Etuaho63e1ec52016-08-18 22:05:12 +0300974 return;
Jamie Madillb1a85f42014-08-19 15:23:24 -0400975 }
976
977 // If we reach here, at least one of the operands is vector or matrix.
978 // The other operand could be a scalar, vector, or matrix.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400979 TBasicType basicType = mLeft->getBasicType();
Olli Etuaho1dded802016-08-18 18:13:13 +0300980
Jamie Madillb1a85f42014-08-19 15:23:24 -0400981 switch (mOp)
982 {
Olli Etuaho1dded802016-08-18 18:13:13 +0300983 case EOpMul:
984 break;
985 case EOpMatrixTimesScalar:
986 if (mRight->isMatrix())
Jamie Madillb1a85f42014-08-19 15:23:24 -0400987 {
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200988 setType(TType(basicType, higherPrecision, resultQualifier,
989 static_cast<unsigned char>(mRight->getCols()),
990 static_cast<unsigned char>(mRight->getRows())));
Jamie Madillb1a85f42014-08-19 15:23:24 -0400991 }
Olli Etuaho1dded802016-08-18 18:13:13 +0300992 break;
993 case EOpMatrixTimesVector:
994 setType(TType(basicType, higherPrecision, resultQualifier,
995 static_cast<unsigned char>(mLeft->getRows()), 1));
996 break;
997 case EOpMatrixTimesMatrix:
Olli Etuahob1edc4f2015-11-02 17:20:03 +0200998 setType(TType(basicType, higherPrecision, resultQualifier,
999 static_cast<unsigned char>(mRight->getCols()),
1000 static_cast<unsigned char>(mLeft->getRows())));
Olli Etuaho1dded802016-08-18 18:13:13 +03001001 break;
1002 case EOpVectorTimesScalar:
Olli Etuahob1edc4f2015-11-02 17:20:03 +02001003 setType(TType(basicType, higherPrecision, resultQualifier,
Olli Etuaho1dded802016-08-18 18:13:13 +03001004 static_cast<unsigned char>(nominalSize), 1));
1005 break;
1006 case EOpVectorTimesMatrix:
1007 setType(TType(basicType, higherPrecision, resultQualifier,
1008 static_cast<unsigned char>(mRight->getCols()), 1));
1009 break;
1010 case EOpMulAssign:
1011 case EOpVectorTimesScalarAssign:
1012 case EOpVectorTimesMatrixAssign:
1013 case EOpMatrixTimesScalarAssign:
1014 case EOpMatrixTimesMatrixAssign:
1015 ASSERT(mOp == GetMulAssignOpBasedOnOperands(mLeft->getType(), mRight->getType()));
1016 break;
1017 case EOpAssign:
1018 case EOpInitialize:
Olli Etuaho1dded802016-08-18 18:13:13 +03001019 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1020 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
1021 break;
1022 case EOpAdd:
1023 case EOpSub:
1024 case EOpDiv:
1025 case EOpIMod:
1026 case EOpBitShiftLeft:
1027 case EOpBitShiftRight:
1028 case EOpBitwiseAnd:
1029 case EOpBitwiseXor:
1030 case EOpBitwiseOr:
1031 case EOpAddAssign:
1032 case EOpSubAssign:
1033 case EOpDivAssign:
1034 case EOpIModAssign:
1035 case EOpBitShiftLeftAssign:
1036 case EOpBitShiftRightAssign:
1037 case EOpBitwiseAndAssign:
1038 case EOpBitwiseXorAssign:
1039 case EOpBitwiseOrAssign:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001040 {
1041 const int secondarySize =
1042 std::max(mLeft->getSecondarySize(), mRight->getSecondarySize());
1043 setType(TType(basicType, higherPrecision, resultQualifier,
1044 static_cast<unsigned char>(nominalSize),
1045 static_cast<unsigned char>(secondarySize)));
1046 ASSERT(!mLeft->isArray() && !mRight->isArray());
Olli Etuaho1dded802016-08-18 18:13:13 +03001047 break;
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001048 }
Olli Etuaho1dded802016-08-18 18:13:13 +03001049 case EOpEqual:
1050 case EOpNotEqual:
1051 case EOpLessThan:
1052 case EOpGreaterThan:
1053 case EOpLessThanEqual:
1054 case EOpGreaterThanEqual:
1055 ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
1056 (mLeft->getSecondarySize() == mRight->getSecondarySize()));
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001057 setType(TType(EbtBool, EbpUndefined, resultQualifier));
Olli Etuaho1dded802016-08-18 18:13:13 +03001058 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001059
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001060 case EOpIndexDirect:
1061 case EOpIndexIndirect:
1062 case EOpIndexDirectInterfaceBlock:
1063 case EOpIndexDirectStruct:
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001064 // These ops should be already fully handled.
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001065 UNREACHABLE();
1066 break;
Olli Etuaho1dded802016-08-18 18:13:13 +03001067 default:
Olli Etuaho63e1ec52016-08-18 22:05:12 +03001068 UNREACHABLE();
1069 break;
Jamie Madillb1a85f42014-08-19 15:23:24 -04001070 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04001071}
1072
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001073const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001074{
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001075 if (isArray())
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001076 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001077 ASSERT(index < static_cast<int>(getType().getArraySize()));
1078 TType arrayElementType = getType();
1079 arrayElementType.clearArrayness();
1080 size_t arrayElementSize = arrayElementType.getObjectSize();
1081 return &mUnionArrayPointer[arrayElementSize * index];
1082 }
1083 else if (isMatrix())
1084 {
1085 ASSERT(index < getType().getCols());
1086 int size = getType().getRows();
1087 return &mUnionArrayPointer[size * index];
1088 }
1089 else if (isVector())
1090 {
1091 ASSERT(index < getType().getNominalSize());
1092 return &mUnionArrayPointer[index];
1093 }
1094 else
1095 {
1096 UNREACHABLE();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001097 return nullptr;
1098 }
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001099}
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001100
Olli Etuahob6fa0432016-09-28 16:28:05 +01001101TIntermTyped *TIntermSwizzle::fold()
1102{
1103 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1104 if (operandConstant == nullptr)
1105 {
1106 return nullptr;
1107 }
1108
1109 TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
1110 for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
1111 {
1112 constArray[i] = *operandConstant->foldIndexing(mSwizzleOffsets.at(i));
1113 }
1114 return CreateFoldedNode(constArray, this, mType.getQualifier());
1115}
1116
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001117TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
1118{
1119 TIntermConstantUnion *leftConstant = mLeft->getAsConstantUnion();
1120 TIntermConstantUnion *rightConstant = mRight->getAsConstantUnion();
1121 switch (mOp)
1122 {
1123 case EOpIndexDirect:
1124 {
1125 if (leftConstant == nullptr || rightConstant == nullptr)
1126 {
1127 return nullptr;
1128 }
1129 int index = rightConstant->getIConst(0);
1130
1131 const TConstantUnion *constArray = leftConstant->foldIndexing(index);
1132 return CreateFoldedNode(constArray, this, mType.getQualifier());
1133 }
1134 case EOpIndexDirectStruct:
1135 {
1136 if (leftConstant == nullptr || rightConstant == nullptr)
1137 {
1138 return nullptr;
1139 }
1140 const TFieldList &fields = mLeft->getType().getStruct()->fields();
1141 size_t index = static_cast<size_t>(rightConstant->getIConst(0));
1142
1143 size_t previousFieldsSize = 0;
1144 for (size_t i = 0; i < index; ++i)
1145 {
1146 previousFieldsSize += fields[i]->type()->getObjectSize();
1147 }
1148
1149 const TConstantUnion *constArray = leftConstant->getUnionArrayPointer();
1150 return CreateFoldedNode(constArray + previousFieldsSize, this, mType.getQualifier());
1151 }
1152 case EOpIndexIndirect:
1153 case EOpIndexDirectInterfaceBlock:
1154 // Can never be constant folded.
1155 return nullptr;
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001156 default:
1157 {
1158 if (leftConstant == nullptr || rightConstant == nullptr)
1159 {
1160 return nullptr;
1161 }
Jamie Madill5db69f52016-09-15 12:47:32 -04001162 TConstantUnion *constArray =
1163 leftConstant->foldBinary(mOp, rightConstant, diagnostics, mLeft->getLine());
Olli Etuaho3272a6d2016-08-29 17:54:50 +03001164
1165 // Nodes may be constant folded without being qualified as constant.
1166 return CreateFoldedNode(constArray, this, mType.getQualifier());
1167 }
1168 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001169}
1170
Olli Etuahof119a262016-08-19 15:54:22 +03001171TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
Olli Etuaho95310b02015-06-02 17:43:38 +03001172{
1173 TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
1174 if (operandConstant == nullptr)
1175 {
1176 return nullptr;
1177 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301178
1179 TConstantUnion *constArray = nullptr;
1180 switch (mOp)
1181 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001182 case EOpAny:
1183 case EOpAll:
1184 case EOpLength:
1185 case EOpTranspose:
1186 case EOpDeterminant:
1187 case EOpInverse:
1188 case EOpPackSnorm2x16:
1189 case EOpUnpackSnorm2x16:
1190 case EOpPackUnorm2x16:
1191 case EOpUnpackUnorm2x16:
1192 case EOpPackHalf2x16:
1193 case EOpUnpackHalf2x16:
1194 constArray = operandConstant->foldUnaryNonComponentWise(mOp);
1195 break;
1196 default:
1197 constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
1198 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301199 }
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001200
1201 // Nodes may be constant folded without being qualified as constant.
Olli Etuahoc9550582016-08-29 17:56:22 +03001202 return CreateFoldedNode(constArray, this, mType.getQualifier());
Olli Etuahob43846e2015-06-02 18:18:57 +03001203}
1204
Olli Etuahof119a262016-08-19 15:54:22 +03001205TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
Olli Etuahob43846e2015-06-02 18:18:57 +03001206{
1207 // Make sure that all params are constant before actual constant folding.
1208 for (auto *param : *getSequence())
Olli Etuaho95310b02015-06-02 17:43:38 +03001209 {
Olli Etuahob43846e2015-06-02 18:18:57 +03001210 if (param->getAsConstantUnion() == nullptr)
1211 {
1212 return nullptr;
1213 }
Olli Etuaho95310b02015-06-02 17:43:38 +03001214 }
Olli Etuaho1d122782015-11-06 15:35:17 +02001215 TConstantUnion *constArray = nullptr;
1216 if (isConstructor())
Olli Etuahof119a262016-08-19 15:54:22 +03001217 constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
Olli Etuaho1d122782015-11-06 15:35:17 +02001218 else
Olli Etuahof119a262016-08-19 15:54:22 +03001219 constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
Olli Etuaho7c3848e2015-11-04 13:19:17 +02001220
1221 // Nodes may be constant folded without being qualified as constant.
1222 TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
1223 return CreateFoldedNode(constArray, this, resultQualifier);
Olli Etuaho95310b02015-06-02 17:43:38 +03001224}
1225
Jamie Madillb1a85f42014-08-19 15:23:24 -04001226//
1227// The fold functions see if an operation on a constant can be done in place,
1228// without generating run-time code.
1229//
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001230// Returns the constant value to keep using or nullptr.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001231//
Olli Etuaho3fdec912016-08-18 15:08:06 +03001232TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
1233 TIntermConstantUnion *rightNode,
Jamie Madill5db69f52016-09-15 12:47:32 -04001234 TDiagnostics *diagnostics,
1235 const TSourceLoc &line)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001236{
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001237 const TConstantUnion *leftArray = getUnionArrayPointer();
1238 const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001239
Olli Etuahof119a262016-08-19 15:54:22 +03001240 ASSERT(leftArray && rightArray);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001241
1242 size_t objectSize = getType().getObjectSize();
1243
1244 // for a case like float f = vec4(2, 3, 4, 5) + 1.2;
1245 if (rightNode->getType().getObjectSize() == 1 && objectSize > 1)
1246 {
1247 rightArray = Vectorize(*rightNode->getUnionArrayPointer(), objectSize);
1248 }
1249 else if (rightNode->getType().getObjectSize() > 1 && objectSize == 1)
1250 {
1251 // for a case like float f = 1.2 + vec4(2, 3, 4, 5);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001252 leftArray = Vectorize(*getUnionArrayPointer(), rightNode->getType().getObjectSize());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001253 objectSize = rightNode->getType().getObjectSize();
1254 }
1255
1256 TConstantUnion *resultArray = nullptr;
1257
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001258 switch (op)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001259 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001260 case EOpAdd:
1261 resultArray = new TConstantUnion[objectSize];
1262 for (size_t i = 0; i < objectSize; i++)
1263 resultArray[i] =
1264 TConstantUnion::add(leftArray[i], rightArray[i], diagnostics, line);
1265 break;
1266 case EOpSub:
1267 resultArray = new TConstantUnion[objectSize];
1268 for (size_t i = 0; i < objectSize; i++)
1269 resultArray[i] =
1270 TConstantUnion::sub(leftArray[i], rightArray[i], diagnostics, line);
1271 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001272
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001273 case EOpMul:
1274 case EOpVectorTimesScalar:
1275 case EOpMatrixTimesScalar:
1276 resultArray = new TConstantUnion[objectSize];
1277 for (size_t i = 0; i < objectSize; i++)
1278 resultArray[i] =
1279 TConstantUnion::mul(leftArray[i], rightArray[i], diagnostics, line);
1280 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001281
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001282 case EOpMatrixTimesMatrix:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001283 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001284 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001285 ASSERT(getType().getBasicType() == EbtFloat && rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001286
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001287 const int leftCols = getCols();
1288 const int leftRows = getRows();
1289 const int rightCols = rightNode->getType().getCols();
1290 const int rightRows = rightNode->getType().getRows();
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001291 const int resultCols = rightCols;
1292 const int resultRows = leftRows;
1293
1294 resultArray = new TConstantUnion[resultCols * resultRows];
1295 for (int row = 0; row < resultRows; row++)
1296 {
1297 for (int column = 0; column < resultCols; column++)
1298 {
1299 resultArray[resultRows * column + row].setFConst(0.0f);
1300 for (int i = 0; i < leftCols; i++)
1301 {
1302 resultArray[resultRows * column + row].setFConst(
1303 resultArray[resultRows * column + row].getFConst() +
1304 leftArray[i * leftRows + row].getFConst() *
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001305 rightArray[column * rightRows + i].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001306 }
1307 }
1308 }
1309 }
1310 break;
1311
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001312 case EOpDiv:
1313 case EOpIMod:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001314 {
1315 resultArray = new TConstantUnion[objectSize];
1316 for (size_t i = 0; i < objectSize; i++)
1317 {
1318 switch (getType().getBasicType())
1319 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001320 case EbtFloat:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001321 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001322 ASSERT(op == EOpDiv);
1323 float dividend = leftArray[i].getFConst();
1324 float divisor = rightArray[i].getFConst();
1325 if (divisor == 0.0f)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001326 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001327 if (dividend == 0.0f)
Olli Etuahod4453572016-09-27 13:21:46 +01001328 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001329 diagnostics->warning(
1330 getLine(),
1331 "Zero divided by zero during constant folding generated NaN",
1332 "/", "");
1333 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
Olli Etuahod4453572016-09-27 13:21:46 +01001334 }
1335 else
1336 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001337 diagnostics->warning(
1338 getLine(), "Divide by zero during constant folding", "/", "");
1339 bool negativeResult =
1340 std::signbit(dividend) != std::signbit(divisor);
1341 resultArray[i].setFConst(
1342 negativeResult ? -std::numeric_limits<float>::infinity()
1343 : std::numeric_limits<float>::infinity());
Olli Etuahod4453572016-09-27 13:21:46 +01001344 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001345 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001346 else if (gl::isInf(dividend) && gl::isInf(divisor))
1347 {
1348 diagnostics->warning(getLine(),
1349 "Infinity divided by infinity during constant "
1350 "folding generated NaN",
1351 "/", "");
1352 resultArray[i].setFConst(std::numeric_limits<float>::quiet_NaN());
1353 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001354 else
1355 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001356 float result = dividend / divisor;
1357 if (!gl::isInf(dividend) && gl::isInf(result))
Olli Etuahod4453572016-09-27 13:21:46 +01001358 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001359 diagnostics->warning(
1360 getLine(), "Constant folded division overflowed to infinity",
1361 "/", "");
1362 }
1363 resultArray[i].setFConst(result);
1364 }
1365 break;
1366 }
1367 case EbtInt:
1368 if (rightArray[i] == 0)
1369 {
1370 diagnostics->warning(
1371 getLine(), "Divide by zero error during constant folding", "/", "");
1372 resultArray[i].setIConst(INT_MAX);
1373 }
1374 else
1375 {
1376 int lhs = leftArray[i].getIConst();
1377 int divisor = rightArray[i].getIConst();
1378 if (op == EOpDiv)
1379 {
1380 // Check for the special case where the minimum representable number
1381 // is
1382 // divided by -1. If left alone this leads to integer overflow in
1383 // C++.
1384 // ESSL 3.00.6 section 4.1.3 Integers:
1385 // "However, for the case where the minimum representable value is
1386 // divided by -1, it is allowed to return either the minimum
1387 // representable value or the maximum representable value."
1388 if (lhs == -0x7fffffff - 1 && divisor == -1)
1389 {
1390 resultArray[i].setIConst(0x7fffffff);
1391 }
1392 else
1393 {
1394 resultArray[i].setIConst(lhs / divisor);
1395 }
Olli Etuahod4453572016-09-27 13:21:46 +01001396 }
1397 else
1398 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001399 ASSERT(op == EOpIMod);
1400 if (lhs < 0 || divisor < 0)
1401 {
1402 // ESSL 3.00.6 section 5.9: Results of modulus are undefined
1403 // when
1404 // either one of the operands is negative.
1405 diagnostics->warning(getLine(),
1406 "Negative modulus operator operand "
1407 "encountered during constant folding",
1408 "%", "");
1409 resultArray[i].setIConst(0);
1410 }
1411 else
1412 {
1413 resultArray[i].setIConst(lhs % divisor);
1414 }
Olli Etuahod4453572016-09-27 13:21:46 +01001415 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001416 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001417 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001418
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001419 case EbtUInt:
1420 if (rightArray[i] == 0)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001421 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001422 diagnostics->warning(
1423 getLine(), "Divide by zero error during constant folding", "/", "");
1424 resultArray[i].setUConst(UINT_MAX);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001425 }
1426 else
1427 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001428 if (op == EOpDiv)
1429 {
1430 resultArray[i].setUConst(leftArray[i].getUConst() /
1431 rightArray[i].getUConst());
1432 }
1433 else
1434 {
1435 ASSERT(op == EOpIMod);
1436 resultArray[i].setUConst(leftArray[i].getUConst() %
1437 rightArray[i].getUConst());
1438 }
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001439 }
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001440 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001441
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001442 default:
1443 UNREACHABLE();
1444 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001445 }
1446 }
1447 }
1448 break;
1449
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001450 case EOpMatrixTimesVector:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001451 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001452 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001453 ASSERT(rightNode->getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001454
1455 const int matrixCols = getCols();
1456 const int matrixRows = getRows();
1457
1458 resultArray = new TConstantUnion[matrixRows];
1459
1460 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1461 {
1462 resultArray[matrixRow].setFConst(0.0f);
1463 for (int col = 0; col < matrixCols; col++)
1464 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001465 resultArray[matrixRow].setFConst(
1466 resultArray[matrixRow].getFConst() +
1467 leftArray[col * matrixRows + matrixRow].getFConst() *
1468 rightArray[col].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001469 }
1470 }
1471 }
1472 break;
1473
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001474 case EOpVectorTimesMatrix:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001475 {
Jamie Madill5db69f52016-09-15 12:47:32 -04001476 // TODO(jmadll): This code should check for overflows.
Olli Etuaho3fdec912016-08-18 15:08:06 +03001477 ASSERT(getType().getBasicType() == EbtFloat);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001478
1479 const int matrixCols = rightNode->getType().getCols();
1480 const int matrixRows = rightNode->getType().getRows();
1481
1482 resultArray = new TConstantUnion[matrixCols];
1483
1484 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
1485 {
1486 resultArray[matrixCol].setFConst(0.0f);
1487 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1488 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001489 resultArray[matrixCol].setFConst(
1490 resultArray[matrixCol].getFConst() +
1491 leftArray[matrixRow].getFConst() *
1492 rightArray[matrixCol * matrixRows + matrixRow].getFConst());
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001493 }
1494 }
1495 }
1496 break;
1497
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001498 case EOpLogicalAnd:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001499 {
1500 resultArray = new TConstantUnion[objectSize];
1501 for (size_t i = 0; i < objectSize; i++)
1502 {
1503 resultArray[i] = leftArray[i] && rightArray[i];
1504 }
1505 }
1506 break;
1507
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001508 case EOpLogicalOr:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001509 {
1510 resultArray = new TConstantUnion[objectSize];
1511 for (size_t i = 0; i < objectSize; i++)
1512 {
1513 resultArray[i] = leftArray[i] || rightArray[i];
1514 }
1515 }
1516 break;
1517
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001518 case EOpLogicalXor:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001519 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001520 ASSERT(getType().getBasicType() == EbtBool);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001521 resultArray = new TConstantUnion[objectSize];
1522 for (size_t i = 0; i < objectSize; i++)
1523 {
Olli Etuaho3fdec912016-08-18 15:08:06 +03001524 resultArray[i].setBConst(leftArray[i] != rightArray[i]);
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001525 }
1526 }
1527 break;
1528
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001529 case EOpBitwiseAnd:
1530 resultArray = new TConstantUnion[objectSize];
1531 for (size_t i = 0; i < objectSize; i++)
1532 resultArray[i] = leftArray[i] & rightArray[i];
1533 break;
1534 case EOpBitwiseXor:
1535 resultArray = new TConstantUnion[objectSize];
1536 for (size_t i = 0; i < objectSize; i++)
1537 resultArray[i] = leftArray[i] ^ rightArray[i];
1538 break;
1539 case EOpBitwiseOr:
1540 resultArray = new TConstantUnion[objectSize];
1541 for (size_t i = 0; i < objectSize; i++)
1542 resultArray[i] = leftArray[i] | rightArray[i];
1543 break;
1544 case EOpBitShiftLeft:
1545 resultArray = new TConstantUnion[objectSize];
1546 for (size_t i = 0; i < objectSize; i++)
1547 resultArray[i] =
1548 TConstantUnion::lshift(leftArray[i], rightArray[i], diagnostics, line);
1549 break;
1550 case EOpBitShiftRight:
1551 resultArray = new TConstantUnion[objectSize];
1552 for (size_t i = 0; i < objectSize; i++)
1553 resultArray[i] =
1554 TConstantUnion::rshift(leftArray[i], rightArray[i], diagnostics, line);
1555 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001556
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001557 case EOpLessThan:
1558 ASSERT(objectSize == 1);
1559 resultArray = new TConstantUnion[1];
1560 resultArray->setBConst(*leftArray < *rightArray);
1561 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001562
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001563 case EOpGreaterThan:
1564 ASSERT(objectSize == 1);
1565 resultArray = new TConstantUnion[1];
1566 resultArray->setBConst(*leftArray > *rightArray);
1567 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001568
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001569 case EOpLessThanEqual:
1570 ASSERT(objectSize == 1);
1571 resultArray = new TConstantUnion[1];
1572 resultArray->setBConst(!(*leftArray > *rightArray));
1573 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001574
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001575 case EOpGreaterThanEqual:
1576 ASSERT(objectSize == 1);
1577 resultArray = new TConstantUnion[1];
1578 resultArray->setBConst(!(*leftArray < *rightArray));
1579 break;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001580
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001581 case EOpEqual:
1582 case EOpNotEqual:
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001583 {
1584 resultArray = new TConstantUnion[1];
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001585 bool equal = true;
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001586 for (size_t i = 0; i < objectSize; i++)
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001587 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001588 if (leftArray[i] != rightArray[i])
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001589 {
Olli Etuaho40d9edf2015-11-12 17:30:34 +02001590 equal = false;
1591 break; // break out of for loop
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001592 }
1593 }
1594 if (op == EOpEqual)
1595 {
1596 resultArray->setBConst(equal);
1597 }
1598 else
1599 {
1600 resultArray->setBConst(!equal);
1601 }
1602 }
1603 break;
1604
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001605 default:
1606 UNREACHABLE();
1607 return nullptr;
Olli Etuaho2c4b7462015-06-08 11:30:31 +03001608 }
1609 return resultArray;
1610}
1611
Olli Etuahof119a262016-08-19 15:54:22 +03001612// The fold functions do operations on a constant at GLSL compile time, without generating run-time
1613// code. Returns the constant value to keep using. Nullptr should not be returned.
1614TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
Jamie Madillb1a85f42014-08-19 15:23:24 -04001615{
Olli Etuahof119a262016-08-19 15:54:22 +03001616 // Do operations where the return type may have a different number of components compared to the
1617 // operand type.
Jamie Madillb1a85f42014-08-19 15:23:24 -04001618
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001619 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001620 ASSERT(operandArray);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301621
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001622 size_t objectSize = getType().getObjectSize();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301623 TConstantUnion *resultArray = nullptr;
1624 switch (op)
1625 {
Olli Etuahof119a262016-08-19 15:54:22 +03001626 case EOpAny:
1627 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301628 resultArray = new TConstantUnion();
1629 resultArray->setBConst(false);
1630 for (size_t i = 0; i < objectSize; i++)
1631 {
1632 if (operandArray[i].getBConst())
1633 {
1634 resultArray->setBConst(true);
1635 break;
1636 }
1637 }
1638 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301639
Olli Etuahof119a262016-08-19 15:54:22 +03001640 case EOpAll:
1641 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301642 resultArray = new TConstantUnion();
1643 resultArray->setBConst(true);
1644 for (size_t i = 0; i < objectSize; i++)
1645 {
1646 if (!operandArray[i].getBConst())
1647 {
1648 resultArray->setBConst(false);
1649 break;
1650 }
1651 }
1652 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301653
Olli Etuahof119a262016-08-19 15:54:22 +03001654 case EOpLength:
1655 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301656 resultArray = new TConstantUnion();
1657 resultArray->setFConst(VectorLength(operandArray, objectSize));
1658 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301659
Olli Etuahof119a262016-08-19 15:54:22 +03001660 case EOpTranspose:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301661 {
Olli Etuahof119a262016-08-19 15:54:22 +03001662 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301663 resultArray = new TConstantUnion[objectSize];
1664 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03001665 GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
Arun Patoleab2b9a22015-07-06 18:27:56 +05301666 SetUnionArrayFromMatrix(result, resultArray);
1667 break;
1668 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301669
Olli Etuahof119a262016-08-19 15:54:22 +03001670 case EOpDeterminant:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301671 {
Olli Etuahof119a262016-08-19 15:54:22 +03001672 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301673 unsigned int size = getType().getNominalSize();
1674 ASSERT(size >= 2 && size <= 4);
1675 resultArray = new TConstantUnion();
1676 resultArray->setFConst(GetMatrix(operandArray, size).determinant());
1677 break;
1678 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301679
Olli Etuahof119a262016-08-19 15:54:22 +03001680 case EOpInverse:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301681 {
Olli Etuahof119a262016-08-19 15:54:22 +03001682 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301683 unsigned int size = getType().getNominalSize();
1684 ASSERT(size >= 2 && size <= 4);
Olli Etuahof119a262016-08-19 15:54:22 +03001685 resultArray = new TConstantUnion[objectSize];
Arun Patoleab2b9a22015-07-06 18:27:56 +05301686 angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
1687 SetUnionArrayFromMatrix(result, resultArray);
1688 break;
1689 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301690
Olli Etuahof119a262016-08-19 15:54:22 +03001691 case EOpPackSnorm2x16:
1692 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301693 ASSERT(getType().getNominalSize() == 2);
1694 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001695 resultArray->setUConst(
1696 gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301697 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301698
Olli Etuahof119a262016-08-19 15:54:22 +03001699 case EOpUnpackSnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301700 {
Olli Etuahof119a262016-08-19 15:54:22 +03001701 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301702 resultArray = new TConstantUnion[2];
1703 float f1, f2;
1704 gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1705 resultArray[0].setFConst(f1);
1706 resultArray[1].setFConst(f2);
1707 break;
1708 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301709
Olli Etuahof119a262016-08-19 15:54:22 +03001710 case EOpPackUnorm2x16:
1711 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301712 ASSERT(getType().getNominalSize() == 2);
1713 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001714 resultArray->setUConst(
1715 gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301716 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301717
Olli Etuahof119a262016-08-19 15:54:22 +03001718 case EOpUnpackUnorm2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301719 {
Olli Etuahof119a262016-08-19 15:54:22 +03001720 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301721 resultArray = new TConstantUnion[2];
1722 float f1, f2;
1723 gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
1724 resultArray[0].setFConst(f1);
1725 resultArray[1].setFConst(f2);
1726 break;
1727 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301728
Olli Etuahof119a262016-08-19 15:54:22 +03001729 case EOpPackHalf2x16:
1730 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301731 ASSERT(getType().getNominalSize() == 2);
1732 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03001733 resultArray->setUConst(
1734 gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
Arun Patoleab2b9a22015-07-06 18:27:56 +05301735 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301736
Olli Etuahof119a262016-08-19 15:54:22 +03001737 case EOpUnpackHalf2x16:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301738 {
Olli Etuahof119a262016-08-19 15:54:22 +03001739 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301740 resultArray = new TConstantUnion[2];
1741 float f1, f2;
1742 gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
1743 resultArray[0].setFConst(f1);
1744 resultArray[1].setFConst(f2);
1745 break;
1746 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301747
Olli Etuahof119a262016-08-19 15:54:22 +03001748 default:
1749 UNREACHABLE();
1750 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301751 }
1752
1753 return resultArray;
1754}
1755
Olli Etuahof119a262016-08-19 15:54:22 +03001756TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
1757 TDiagnostics *diagnostics)
Arun Patoleab2b9a22015-07-06 18:27:56 +05301758{
Olli Etuahof119a262016-08-19 15:54:22 +03001759 // Do unary operations where each component of the result is computed based on the corresponding
1760 // component of the operand. Also folds normalize, though the divisor in that case takes all
1761 // components into account.
Arun Patoleab2b9a22015-07-06 18:27:56 +05301762
Olli Etuaho5c0e0232015-11-11 15:55:59 +02001763 const TConstantUnion *operandArray = getUnionArrayPointer();
Olli Etuahof119a262016-08-19 15:54:22 +03001764 ASSERT(operandArray);
Jamie Madillb1a85f42014-08-19 15:23:24 -04001765
1766 size_t objectSize = getType().getObjectSize();
1767
Arun Patoleab2b9a22015-07-06 18:27:56 +05301768 TConstantUnion *resultArray = new TConstantUnion[objectSize];
1769 for (size_t i = 0; i < objectSize; i++)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301770 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -05001771 switch (op)
Arun Patole9d0b1f92015-05-20 14:27:17 +05301772 {
Olli Etuahof119a262016-08-19 15:54:22 +03001773 case EOpNegative:
1774 switch (getType().getBasicType())
1775 {
1776 case EbtFloat:
1777 resultArray[i].setFConst(-operandArray[i].getFConst());
1778 break;
1779 case EbtInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001780 if (operandArray[i] == std::numeric_limits<int>::min())
1781 {
1782 // The minimum representable integer doesn't have a positive
1783 // counterpart, rather the negation overflows and in ESSL is supposed to
1784 // wrap back to the minimum representable integer. Make sure that we
1785 // don't actually let the negation overflow, which has undefined
1786 // behavior in C++.
1787 resultArray[i].setIConst(std::numeric_limits<int>::min());
1788 }
1789 else
1790 {
1791 resultArray[i].setIConst(-operandArray[i].getIConst());
1792 }
Olli Etuahof119a262016-08-19 15:54:22 +03001793 break;
1794 case EbtUInt:
Olli Etuaho42fad762016-09-28 10:06:29 +01001795 if (operandArray[i] == 0x80000000u)
1796 {
1797 resultArray[i].setUConst(0x80000000u);
1798 }
1799 else
1800 {
1801 resultArray[i].setUConst(static_cast<unsigned int>(
1802 -static_cast<int>(operandArray[i].getUConst())));
1803 }
Olli Etuahof119a262016-08-19 15:54:22 +03001804 break;
1805 default:
1806 UNREACHABLE();
1807 return nullptr;
1808 }
Arun Patole1155ddd2015-06-05 18:04:36 +05301809 break;
Arun Patolecdfa8f52015-06-30 17:48:25 +05301810
Olli Etuahof119a262016-08-19 15:54:22 +03001811 case EOpPositive:
1812 switch (getType().getBasicType())
1813 {
1814 case EbtFloat:
1815 resultArray[i].setFConst(operandArray[i].getFConst());
1816 break;
1817 case EbtInt:
1818 resultArray[i].setIConst(operandArray[i].getIConst());
1819 break;
1820 case EbtUInt:
1821 resultArray[i].setUConst(static_cast<unsigned int>(
1822 static_cast<int>(operandArray[i].getUConst())));
1823 break;
1824 default:
1825 UNREACHABLE();
1826 return nullptr;
1827 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301828 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301829
Olli Etuahof119a262016-08-19 15:54:22 +03001830 case EOpLogicalNot:
1831 switch (getType().getBasicType())
1832 {
1833 case EbtBool:
1834 resultArray[i].setBConst(!operandArray[i].getBConst());
1835 break;
1836 default:
1837 UNREACHABLE();
1838 return nullptr;
1839 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301840 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301841
Olli Etuahof119a262016-08-19 15:54:22 +03001842 case EOpBitwiseNot:
1843 switch (getType().getBasicType())
1844 {
1845 case EbtInt:
1846 resultArray[i].setIConst(~operandArray[i].getIConst());
1847 break;
1848 case EbtUInt:
1849 resultArray[i].setUConst(~operandArray[i].getUConst());
1850 break;
1851 default:
1852 UNREACHABLE();
1853 return nullptr;
1854 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05301855 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301856
Olli Etuahof119a262016-08-19 15:54:22 +03001857 case EOpRadians:
1858 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301859 resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
1860 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301861
Olli Etuahof119a262016-08-19 15:54:22 +03001862 case EOpDegrees:
1863 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301864 resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
1865 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301866
Olli Etuahof119a262016-08-19 15:54:22 +03001867 case EOpSin:
1868 foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301869 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301870
Olli Etuahof119a262016-08-19 15:54:22 +03001871 case EOpCos:
1872 foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
1873 break;
1874
1875 case EOpTan:
1876 foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
1877 break;
1878
1879 case EOpAsin:
1880 // For asin(x), results are undefined if |x| > 1, we are choosing to set result to
1881 // 0.
1882 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1883 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1884 diagnostics, &resultArray[i]);
1885 else
1886 foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
1887 break;
1888
1889 case EOpAcos:
1890 // For acos(x), results are undefined if |x| > 1, we are choosing to set result to
1891 // 0.
1892 if (fabsf(operandArray[i].getFConst()) > 1.0f)
1893 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1894 diagnostics, &resultArray[i]);
1895 else
1896 foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
1897 break;
1898
1899 case EOpAtan:
1900 foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
1901 break;
1902
1903 case EOpSinh:
1904 foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
1905 break;
1906
1907 case EOpCosh:
1908 foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
1909 break;
1910
1911 case EOpTanh:
1912 foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
1913 break;
1914
1915 case EOpAsinh:
1916 foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
1917 break;
1918
1919 case EOpAcosh:
1920 // For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
1921 if (operandArray[i].getFConst() < 1.0f)
1922 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1923 diagnostics, &resultArray[i]);
1924 else
1925 foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
1926 break;
1927
1928 case EOpAtanh:
1929 // For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
1930 // 0.
1931 if (fabsf(operandArray[i].getFConst()) >= 1.0f)
1932 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
1933 diagnostics, &resultArray[i]);
1934 else
1935 foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
1936 break;
1937
1938 case EOpAbs:
1939 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301940 {
Olli Etuahof119a262016-08-19 15:54:22 +03001941 case EbtFloat:
1942 resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
1943 break;
1944 case EbtInt:
1945 resultArray[i].setIConst(abs(operandArray[i].getIConst()));
1946 break;
1947 default:
1948 UNREACHABLE();
1949 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301950 }
1951 break;
Olli Etuahof119a262016-08-19 15:54:22 +03001952
1953 case EOpSign:
1954 switch (getType().getBasicType())
Arun Patoleab2b9a22015-07-06 18:27:56 +05301955 {
Olli Etuahof119a262016-08-19 15:54:22 +03001956 case EbtFloat:
1957 {
1958 float fConst = operandArray[i].getFConst();
1959 float fResult = 0.0f;
1960 if (fConst > 0.0f)
1961 fResult = 1.0f;
1962 else if (fConst < 0.0f)
1963 fResult = -1.0f;
1964 resultArray[i].setFConst(fResult);
1965 break;
1966 }
1967 case EbtInt:
1968 {
1969 int iConst = operandArray[i].getIConst();
1970 int iResult = 0;
1971 if (iConst > 0)
1972 iResult = 1;
1973 else if (iConst < 0)
1974 iResult = -1;
1975 resultArray[i].setIConst(iResult);
1976 break;
1977 }
1978 default:
1979 UNREACHABLE();
1980 return nullptr;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301981 }
1982 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301983
Olli Etuahof119a262016-08-19 15:54:22 +03001984 case EOpFloor:
1985 foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
1986 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301987
Olli Etuahof119a262016-08-19 15:54:22 +03001988 case EOpTrunc:
1989 foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
1990 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301991
Olli Etuahof119a262016-08-19 15:54:22 +03001992 case EOpRound:
1993 foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
1994 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05301995
Olli Etuahof119a262016-08-19 15:54:22 +03001996 case EOpRoundEven:
Arun Patoleab2b9a22015-07-06 18:27:56 +05301997 {
Olli Etuahof119a262016-08-19 15:54:22 +03001998 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05301999 float x = operandArray[i].getFConst();
2000 float result;
2001 float fractPart = modff(x, &result);
2002 if (fabsf(fractPart) == 0.5f)
2003 result = 2.0f * roundf(x / 2.0f);
2004 else
2005 result = roundf(x);
2006 resultArray[i].setFConst(result);
2007 break;
2008 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302009
Olli Etuahof119a262016-08-19 15:54:22 +03002010 case EOpCeil:
2011 foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
2012 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302013
Olli Etuahof119a262016-08-19 15:54:22 +03002014 case EOpFract:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302015 {
Olli Etuahof119a262016-08-19 15:54:22 +03002016 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302017 float x = operandArray[i].getFConst();
2018 resultArray[i].setFConst(x - floorf(x));
2019 break;
2020 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302021
Olli Etuahof119a262016-08-19 15:54:22 +03002022 case EOpIsNan:
2023 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302024 resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
2025 break;
Arun Patole551279e2015-07-07 18:18:23 +05302026
Olli Etuahof119a262016-08-19 15:54:22 +03002027 case EOpIsInf:
2028 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302029 resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
2030 break;
Arun Patole551279e2015-07-07 18:18:23 +05302031
Olli Etuahof119a262016-08-19 15:54:22 +03002032 case EOpFloatBitsToInt:
2033 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302034 resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
2035 break;
Arun Patole551279e2015-07-07 18:18:23 +05302036
Olli Etuahof119a262016-08-19 15:54:22 +03002037 case EOpFloatBitsToUint:
2038 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole551279e2015-07-07 18:18:23 +05302039 resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
2040 break;
Arun Patole551279e2015-07-07 18:18:23 +05302041
Olli Etuahof119a262016-08-19 15:54:22 +03002042 case EOpIntBitsToFloat:
2043 ASSERT(getType().getBasicType() == EbtInt);
Arun Patole551279e2015-07-07 18:18:23 +05302044 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
2045 break;
Arun Patole551279e2015-07-07 18:18:23 +05302046
Olli Etuahof119a262016-08-19 15:54:22 +03002047 case EOpUintBitsToFloat:
2048 ASSERT(getType().getBasicType() == EbtUInt);
Arun Patole551279e2015-07-07 18:18:23 +05302049 resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
2050 break;
Arun Patole551279e2015-07-07 18:18:23 +05302051
Olli Etuahof119a262016-08-19 15:54:22 +03002052 case EOpExp:
2053 foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
2054 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302055
Olli Etuahof119a262016-08-19 15:54:22 +03002056 case EOpLog:
2057 // For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
2058 if (operandArray[i].getFConst() <= 0.0f)
2059 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2060 diagnostics, &resultArray[i]);
2061 else
2062 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2063 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302064
Olli Etuahof119a262016-08-19 15:54:22 +03002065 case EOpExp2:
2066 foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
2067 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302068
Olli Etuahof119a262016-08-19 15:54:22 +03002069 case EOpLog2:
2070 // For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
2071 // And log2f is not available on some plarforms like old android, so just using
2072 // log(x)/log(2) here.
2073 if (operandArray[i].getFConst() <= 0.0f)
2074 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2075 diagnostics, &resultArray[i]);
2076 else
2077 {
2078 foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
2079 resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
2080 }
2081 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302082
Olli Etuahof119a262016-08-19 15:54:22 +03002083 case EOpSqrt:
2084 // For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
2085 if (operandArray[i].getFConst() < 0.0f)
2086 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2087 diagnostics, &resultArray[i]);
2088 else
2089 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2090 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302091
Olli Etuahof119a262016-08-19 15:54:22 +03002092 case EOpInverseSqrt:
2093 // There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
2094 // so getting the square root first using builtin function sqrt() and then taking
2095 // its inverse.
2096 // Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
2097 // result to 0.
2098 if (operandArray[i].getFConst() <= 0.0f)
2099 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2100 diagnostics, &resultArray[i]);
2101 else
2102 {
2103 foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
2104 resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
2105 }
2106 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302107
Olli Etuahof119a262016-08-19 15:54:22 +03002108 case EOpVectorLogicalNot:
2109 ASSERT(getType().getBasicType() == EbtBool);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302110 resultArray[i].setBConst(!operandArray[i].getBConst());
2111 break;
Arun Patoleab2b9a22015-07-06 18:27:56 +05302112
Olli Etuahof119a262016-08-19 15:54:22 +03002113 case EOpNormalize:
Arun Patoleab2b9a22015-07-06 18:27:56 +05302114 {
Olli Etuahof119a262016-08-19 15:54:22 +03002115 ASSERT(getType().getBasicType() == EbtFloat);
2116 float x = operandArray[i].getFConst();
Arun Patoleab2b9a22015-07-06 18:27:56 +05302117 float length = VectorLength(operandArray, objectSize);
2118 if (length)
2119 resultArray[i].setFConst(x / length);
2120 else
Olli Etuahof119a262016-08-19 15:54:22 +03002121 UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
2122 diagnostics, &resultArray[i]);
Arun Patoleab2b9a22015-07-06 18:27:56 +05302123 break;
2124 }
Arun Patoleab2b9a22015-07-06 18:27:56 +05302125
Olli Etuahof119a262016-08-19 15:54:22 +03002126 case EOpDFdx:
2127 case EOpDFdy:
2128 case EOpFwidth:
2129 ASSERT(getType().getBasicType() == EbtFloat);
Arun Patole0c5409f2015-07-08 15:17:53 +05302130 // Derivatives of constant arguments should be 0.
2131 resultArray[i].setFConst(0.0f);
2132 break;
Arun Patole0c5409f2015-07-08 15:17:53 +05302133
Olli Etuahof119a262016-08-19 15:54:22 +03002134 default:
2135 return nullptr;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302136 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302137 }
Jamie Madillb1a85f42014-08-19 15:23:24 -04002138
Arun Patoleab2b9a22015-07-06 18:27:56 +05302139 return resultArray;
Jamie Madillb1a85f42014-08-19 15:23:24 -04002140}
2141
Olli Etuahof119a262016-08-19 15:54:22 +03002142void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
2143 FloatTypeUnaryFunc builtinFunc,
2144 TConstantUnion *result) const
Arun Patole9dea48f2015-04-02 11:45:09 +05302145{
2146 ASSERT(builtinFunc);
2147
Olli Etuahof119a262016-08-19 15:54:22 +03002148 ASSERT(getType().getBasicType() == EbtFloat);
2149 result->setFConst(builtinFunc(parameter.getFConst()));
Arun Patole9dea48f2015-04-02 11:45:09 +05302150}
2151
Jamie Madillb1a85f42014-08-19 15:23:24 -04002152// static
Olli Etuahof119a262016-08-19 15:54:22 +03002153TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
Olli Etuaho1d122782015-11-06 15:35:17 +02002154{
2155 ASSERT(aggregate->getSequence()->size() > 0u);
2156 size_t resultSize = aggregate->getType().getObjectSize();
2157 TConstantUnion *resultArray = new TConstantUnion[resultSize];
2158 TBasicType basicType = aggregate->getBasicType();
2159
2160 size_t resultIndex = 0u;
2161
2162 if (aggregate->getSequence()->size() == 1u)
2163 {
2164 TIntermNode *argument = aggregate->getSequence()->front();
2165 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2166 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2167 // Check the special case of constructing a matrix diagonal from a single scalar,
2168 // or a vector from a single scalar.
2169 if (argumentConstant->getType().getObjectSize() == 1u)
2170 {
2171 if (aggregate->isMatrix())
2172 {
2173 int resultCols = aggregate->getType().getCols();
2174 int resultRows = aggregate->getType().getRows();
2175 for (int col = 0; col < resultCols; ++col)
2176 {
2177 for (int row = 0; row < resultRows; ++row)
2178 {
2179 if (col == row)
2180 {
2181 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2182 }
2183 else
2184 {
2185 resultArray[resultIndex].setFConst(0.0f);
2186 }
2187 ++resultIndex;
2188 }
2189 }
2190 }
2191 else
2192 {
2193 while (resultIndex < resultSize)
2194 {
2195 resultArray[resultIndex].cast(basicType, argumentUnionArray[0]);
2196 ++resultIndex;
2197 }
2198 }
2199 ASSERT(resultIndex == resultSize);
2200 return resultArray;
2201 }
2202 else if (aggregate->isMatrix() && argumentConstant->isMatrix())
2203 {
2204 // The special case of constructing a matrix from a matrix.
2205 int argumentCols = argumentConstant->getType().getCols();
2206 int argumentRows = argumentConstant->getType().getRows();
2207 int resultCols = aggregate->getType().getCols();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002208 int resultRows = aggregate->getType().getRows();
Olli Etuaho1d122782015-11-06 15:35:17 +02002209 for (int col = 0; col < resultCols; ++col)
2210 {
2211 for (int row = 0; row < resultRows; ++row)
2212 {
2213 if (col < argumentCols && row < argumentRows)
2214 {
2215 resultArray[resultIndex].cast(basicType,
2216 argumentUnionArray[col * argumentRows + row]);
2217 }
2218 else if (col == row)
2219 {
2220 resultArray[resultIndex].setFConst(1.0f);
2221 }
2222 else
2223 {
2224 resultArray[resultIndex].setFConst(0.0f);
2225 }
2226 ++resultIndex;
2227 }
2228 }
2229 ASSERT(resultIndex == resultSize);
2230 return resultArray;
2231 }
2232 }
2233
2234 for (TIntermNode *&argument : *aggregate->getSequence())
2235 {
2236 TIntermConstantUnion *argumentConstant = argument->getAsConstantUnion();
2237 size_t argumentSize = argumentConstant->getType().getObjectSize();
2238 const TConstantUnion *argumentUnionArray = argumentConstant->getUnionArrayPointer();
2239 for (size_t i = 0u; i < argumentSize; ++i)
2240 {
2241 if (resultIndex >= resultSize)
2242 break;
2243 resultArray[resultIndex].cast(basicType, argumentUnionArray[i]);
2244 ++resultIndex;
2245 }
2246 }
2247 ASSERT(resultIndex == resultSize);
2248 return resultArray;
2249}
2250
2251// static
Olli Etuahof119a262016-08-19 15:54:22 +03002252TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
2253 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +05302254{
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002255 TOperator op = aggregate->getOp();
Arun Patole274f0702015-05-05 13:33:30 +05302256 TIntermSequence *sequence = aggregate->getSequence();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002257 unsigned int paramsCount = static_cast<unsigned int>(sequence->size());
Olli Etuaho5c0e0232015-11-11 15:55:59 +02002258 std::vector<const TConstantUnion *> unionArrays(paramsCount);
Arun Patole274f0702015-05-05 13:33:30 +05302259 std::vector<size_t> objectSizes(paramsCount);
Olli Etuahob43846e2015-06-02 18:18:57 +03002260 size_t maxObjectSize = 0;
Arun Patole274f0702015-05-05 13:33:30 +05302261 TBasicType basicType = EbtVoid;
2262 TSourceLoc loc;
2263 for (unsigned int i = 0; i < paramsCount; i++)
2264 {
2265 TIntermConstantUnion *paramConstant = (*sequence)[i]->getAsConstantUnion();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002266 ASSERT(paramConstant != nullptr); // Should be checked already.
Arun Patole274f0702015-05-05 13:33:30 +05302267
2268 if (i == 0)
2269 {
2270 basicType = paramConstant->getType().getBasicType();
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002271 loc = paramConstant->getLine();
Arun Patole274f0702015-05-05 13:33:30 +05302272 }
2273 unionArrays[i] = paramConstant->getUnionArrayPointer();
2274 objectSizes[i] = paramConstant->getType().getObjectSize();
Olli Etuahob43846e2015-06-02 18:18:57 +03002275 if (objectSizes[i] > maxObjectSize)
2276 maxObjectSize = objectSizes[i];
Arun Patole274f0702015-05-05 13:33:30 +05302277 }
2278
Olli Etuahod5da5052016-08-29 13:16:55 +03002279 if (!(*sequence)[0]->getAsTyped()->isMatrix() && aggregate->getOp() != EOpOuterProduct)
Arun Patole7fa33552015-06-10 15:15:18 +05302280 {
2281 for (unsigned int i = 0; i < paramsCount; i++)
2282 if (objectSizes[i] != maxObjectSize)
2283 unionArrays[i] = Vectorize(*unionArrays[i], maxObjectSize);
2284 }
Arun Patole274f0702015-05-05 13:33:30 +05302285
Olli Etuahob43846e2015-06-02 18:18:57 +03002286 TConstantUnion *resultArray = nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302287 if (paramsCount == 2)
2288 {
2289 //
2290 // Binary built-in
2291 //
2292 switch (op)
2293 {
Olli Etuahof119a262016-08-19 15:54:22 +03002294 case EOpAtan:
Arun Patolebf790422015-05-18 17:53:04 +05302295 {
Olli Etuahof119a262016-08-19 15:54:22 +03002296 ASSERT(basicType == EbtFloat);
2297 resultArray = new TConstantUnion[maxObjectSize];
2298 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302299 {
Olli Etuahof119a262016-08-19 15:54:22 +03002300 float y = unionArrays[0][i].getFConst();
2301 float x = unionArrays[1][i].getFConst();
2302 // Results are undefined if x and y are both 0.
2303 if (x == 0.0f && y == 0.0f)
2304 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2305 &resultArray[i]);
2306 else
2307 resultArray[i].setFConst(atan2f(y, x));
Arun Patolebf790422015-05-18 17:53:04 +05302308 }
Olli Etuahof119a262016-08-19 15:54:22 +03002309 break;
Arun Patolebf790422015-05-18 17:53:04 +05302310 }
Arun Patolebf790422015-05-18 17:53:04 +05302311
Olli Etuahof119a262016-08-19 15:54:22 +03002312 case EOpPow:
Arun Patolebf790422015-05-18 17:53:04 +05302313 {
Olli Etuahof119a262016-08-19 15:54:22 +03002314 ASSERT(basicType == EbtFloat);
2315 resultArray = new TConstantUnion[maxObjectSize];
2316 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302317 {
Olli Etuahof119a262016-08-19 15:54:22 +03002318 float x = unionArrays[0][i].getFConst();
2319 float y = unionArrays[1][i].getFConst();
2320 // Results are undefined if x < 0.
2321 // Results are undefined if x = 0 and y <= 0.
2322 if (x < 0.0f)
2323 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2324 &resultArray[i]);
2325 else if (x == 0.0f && y <= 0.0f)
2326 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2327 &resultArray[i]);
2328 else
2329 resultArray[i].setFConst(powf(x, y));
Arun Patolebf790422015-05-18 17:53:04 +05302330 }
Olli Etuahof119a262016-08-19 15:54:22 +03002331 break;
Arun Patolebf790422015-05-18 17:53:04 +05302332 }
Arun Patolebf790422015-05-18 17:53:04 +05302333
Olli Etuahof119a262016-08-19 15:54:22 +03002334 case EOpMod:
Arun Patolebf790422015-05-18 17:53:04 +05302335 {
Olli Etuahof119a262016-08-19 15:54:22 +03002336 ASSERT(basicType == EbtFloat);
2337 resultArray = new TConstantUnion[maxObjectSize];
2338 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302339 {
Olli Etuahof119a262016-08-19 15:54:22 +03002340 float x = unionArrays[0][i].getFConst();
2341 float y = unionArrays[1][i].getFConst();
2342 resultArray[i].setFConst(x - y * floorf(x / y));
Arun Patolebf790422015-05-18 17:53:04 +05302343 }
Olli Etuahof119a262016-08-19 15:54:22 +03002344 break;
Arun Patolebf790422015-05-18 17:53:04 +05302345 }
Arun Patolebf790422015-05-18 17:53:04 +05302346
Olli Etuahof119a262016-08-19 15:54:22 +03002347 case EOpMin:
Arun Patole274f0702015-05-05 13:33:30 +05302348 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002349 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302350 for (size_t i = 0; i < maxObjectSize; i++)
2351 {
2352 switch (basicType)
2353 {
Olli Etuahof119a262016-08-19 15:54:22 +03002354 case EbtFloat:
2355 resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(),
2356 unionArrays[1][i].getFConst()));
2357 break;
2358 case EbtInt:
2359 resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(),
2360 unionArrays[1][i].getIConst()));
2361 break;
2362 case EbtUInt:
2363 resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(),
2364 unionArrays[1][i].getUConst()));
2365 break;
2366 default:
2367 UNREACHABLE();
2368 break;
Arun Patole274f0702015-05-05 13:33:30 +05302369 }
2370 }
Olli Etuahof119a262016-08-19 15:54:22 +03002371 break;
Arun Patole274f0702015-05-05 13:33:30 +05302372 }
Arun Patole274f0702015-05-05 13:33:30 +05302373
Olli Etuahof119a262016-08-19 15:54:22 +03002374 case EOpMax:
Arun Patole274f0702015-05-05 13:33:30 +05302375 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002376 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302377 for (size_t i = 0; i < maxObjectSize; i++)
2378 {
2379 switch (basicType)
2380 {
Olli Etuahof119a262016-08-19 15:54:22 +03002381 case EbtFloat:
2382 resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(),
2383 unionArrays[1][i].getFConst()));
2384 break;
2385 case EbtInt:
2386 resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(),
2387 unionArrays[1][i].getIConst()));
2388 break;
2389 case EbtUInt:
2390 resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(),
2391 unionArrays[1][i].getUConst()));
2392 break;
2393 default:
2394 UNREACHABLE();
2395 break;
Arun Patole274f0702015-05-05 13:33:30 +05302396 }
2397 }
Olli Etuahof119a262016-08-19 15:54:22 +03002398 break;
Arun Patole274f0702015-05-05 13:33:30 +05302399 }
Arun Patole274f0702015-05-05 13:33:30 +05302400
Olli Etuahof119a262016-08-19 15:54:22 +03002401 case EOpStep:
Arun Patolebf790422015-05-18 17:53:04 +05302402 {
Olli Etuahof119a262016-08-19 15:54:22 +03002403 ASSERT(basicType == EbtFloat);
2404 resultArray = new TConstantUnion[maxObjectSize];
2405 for (size_t i = 0; i < maxObjectSize; i++)
2406 resultArray[i].setFConst(
2407 unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f
2408 : 1.0f);
2409 break;
Arun Patolebf790422015-05-18 17:53:04 +05302410 }
Arun Patolebf790422015-05-18 17:53:04 +05302411
Olli Etuahof119a262016-08-19 15:54:22 +03002412 case EOpLessThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302413 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002414 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302415 for (size_t i = 0; i < maxObjectSize; i++)
2416 {
2417 switch (basicType)
2418 {
Olli Etuahof119a262016-08-19 15:54:22 +03002419 case EbtFloat:
2420 resultArray[i].setBConst(unionArrays[0][i].getFConst() <
2421 unionArrays[1][i].getFConst());
2422 break;
2423 case EbtInt:
2424 resultArray[i].setBConst(unionArrays[0][i].getIConst() <
2425 unionArrays[1][i].getIConst());
2426 break;
2427 case EbtUInt:
2428 resultArray[i].setBConst(unionArrays[0][i].getUConst() <
2429 unionArrays[1][i].getUConst());
2430 break;
2431 default:
2432 UNREACHABLE();
2433 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302434 }
2435 }
Olli Etuahof119a262016-08-19 15:54:22 +03002436 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302437 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302438
Olli Etuahof119a262016-08-19 15:54:22 +03002439 case EOpLessThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302440 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002441 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302442 for (size_t i = 0; i < maxObjectSize; i++)
2443 {
2444 switch (basicType)
2445 {
Olli Etuahof119a262016-08-19 15:54:22 +03002446 case EbtFloat:
2447 resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
2448 unionArrays[1][i].getFConst());
2449 break;
2450 case EbtInt:
2451 resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
2452 unionArrays[1][i].getIConst());
2453 break;
2454 case EbtUInt:
2455 resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
2456 unionArrays[1][i].getUConst());
2457 break;
2458 default:
2459 UNREACHABLE();
2460 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302461 }
2462 }
Olli Etuahof119a262016-08-19 15:54:22 +03002463 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302464 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302465
Olli Etuahof119a262016-08-19 15:54:22 +03002466 case EOpGreaterThan:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302467 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002468 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302469 for (size_t i = 0; i < maxObjectSize; i++)
2470 {
2471 switch (basicType)
2472 {
Olli Etuahof119a262016-08-19 15:54:22 +03002473 case EbtFloat:
2474 resultArray[i].setBConst(unionArrays[0][i].getFConst() >
2475 unionArrays[1][i].getFConst());
2476 break;
2477 case EbtInt:
2478 resultArray[i].setBConst(unionArrays[0][i].getIConst() >
2479 unionArrays[1][i].getIConst());
2480 break;
2481 case EbtUInt:
2482 resultArray[i].setBConst(unionArrays[0][i].getUConst() >
2483 unionArrays[1][i].getUConst());
2484 break;
2485 default:
2486 UNREACHABLE();
2487 break;
Olli Etuahob43846e2015-06-02 18:18:57 +03002488 }
2489 }
Olli Etuahof119a262016-08-19 15:54:22 +03002490 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302491 }
Olli Etuahof119a262016-08-19 15:54:22 +03002492 case EOpGreaterThanEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302493 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002494 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302495 for (size_t i = 0; i < maxObjectSize; i++)
2496 {
2497 switch (basicType)
2498 {
Olli Etuahof119a262016-08-19 15:54:22 +03002499 case EbtFloat:
2500 resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
2501 unionArrays[1][i].getFConst());
2502 break;
2503 case EbtInt:
2504 resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
2505 unionArrays[1][i].getIConst());
2506 break;
2507 case EbtUInt:
2508 resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
2509 unionArrays[1][i].getUConst());
2510 break;
2511 default:
2512 UNREACHABLE();
2513 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302514 }
2515 }
2516 }
2517 break;
2518
Olli Etuahof119a262016-08-19 15:54:22 +03002519 case EOpVectorEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302520 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002521 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302522 for (size_t i = 0; i < maxObjectSize; i++)
2523 {
2524 switch (basicType)
2525 {
Olli Etuahof119a262016-08-19 15:54:22 +03002526 case EbtFloat:
2527 resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
2528 unionArrays[1][i].getFConst());
2529 break;
2530 case EbtInt:
2531 resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
2532 unionArrays[1][i].getIConst());
2533 break;
2534 case EbtUInt:
2535 resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
2536 unionArrays[1][i].getUConst());
2537 break;
2538 case EbtBool:
2539 resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
2540 unionArrays[1][i].getBConst());
2541 break;
2542 default:
2543 UNREACHABLE();
2544 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302545 }
2546 }
Olli Etuahof119a262016-08-19 15:54:22 +03002547 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302548 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302549
Olli Etuahof119a262016-08-19 15:54:22 +03002550 case EOpVectorNotEqual:
Arun Patole9d0b1f92015-05-20 14:27:17 +05302551 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002552 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole9d0b1f92015-05-20 14:27:17 +05302553 for (size_t i = 0; i < maxObjectSize; i++)
2554 {
2555 switch (basicType)
2556 {
Olli Etuahof119a262016-08-19 15:54:22 +03002557 case EbtFloat:
2558 resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
2559 unionArrays[1][i].getFConst());
2560 break;
2561 case EbtInt:
2562 resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
2563 unionArrays[1][i].getIConst());
2564 break;
2565 case EbtUInt:
2566 resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
2567 unionArrays[1][i].getUConst());
2568 break;
2569 case EbtBool:
2570 resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
2571 unionArrays[1][i].getBConst());
2572 break;
2573 default:
2574 UNREACHABLE();
2575 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302576 }
2577 }
Olli Etuahof119a262016-08-19 15:54:22 +03002578 break;
Arun Patole9d0b1f92015-05-20 14:27:17 +05302579 }
Arun Patole9d0b1f92015-05-20 14:27:17 +05302580
Olli Etuahof119a262016-08-19 15:54:22 +03002581 case EOpDistance:
Arun Patole1155ddd2015-06-05 18:04:36 +05302582 {
Olli Etuahof119a262016-08-19 15:54:22 +03002583 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302584 TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002585 resultArray = new TConstantUnion();
Arun Patole1155ddd2015-06-05 18:04:36 +05302586 for (size_t i = 0; i < maxObjectSize; i++)
2587 {
2588 float x = unionArrays[0][i].getFConst();
2589 float y = unionArrays[1][i].getFConst();
2590 distanceArray[i].setFConst(x - y);
2591 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002592 resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
Olli Etuahof119a262016-08-19 15:54:22 +03002593 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302594 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302595
Olli Etuahof119a262016-08-19 15:54:22 +03002596 case EOpDot:
2597 ASSERT(basicType == EbtFloat);
Olli Etuahob43846e2015-06-02 18:18:57 +03002598 resultArray = new TConstantUnion();
Olli Etuahof119a262016-08-19 15:54:22 +03002599 resultArray->setFConst(
2600 VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
2601 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302602
Olli Etuahof119a262016-08-19 15:54:22 +03002603 case EOpCross:
Arun Patole1155ddd2015-06-05 18:04:36 +05302604 {
Olli Etuahof119a262016-08-19 15:54:22 +03002605 ASSERT(basicType == EbtFloat && maxObjectSize == 3);
Olli Etuahob43846e2015-06-02 18:18:57 +03002606 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002607 float x0 = unionArrays[0][0].getFConst();
2608 float x1 = unionArrays[0][1].getFConst();
2609 float x2 = unionArrays[0][2].getFConst();
2610 float y0 = unionArrays[1][0].getFConst();
2611 float y1 = unionArrays[1][1].getFConst();
2612 float y2 = unionArrays[1][2].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002613 resultArray[0].setFConst(x1 * y2 - y1 * x2);
2614 resultArray[1].setFConst(x2 * y0 - y2 * x0);
2615 resultArray[2].setFConst(x0 * y1 - y0 * x1);
Olli Etuahof119a262016-08-19 15:54:22 +03002616 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302617 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302618
Olli Etuahof119a262016-08-19 15:54:22 +03002619 case EOpReflect:
Arun Patole1155ddd2015-06-05 18:04:36 +05302620 {
Olli Etuahof119a262016-08-19 15:54:22 +03002621 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302622 // genType reflect (genType I, genType N) :
Olli Etuahof119a262016-08-19 15:54:22 +03002623 // For the incident vector I and surface orientation N, returns the reflection
2624 // direction:
Arun Patole1155ddd2015-06-05 18:04:36 +05302625 // I - 2 * dot(N, I) * N.
Olli Etuahof119a262016-08-19 15:54:22 +03002626 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302627 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2628 for (size_t i = 0; i < maxObjectSize; i++)
2629 {
2630 float result = unionArrays[0][i].getFConst() -
2631 2.0f * dotProduct * unionArrays[1][i].getFConst();
Olli Etuahob43846e2015-06-02 18:18:57 +03002632 resultArray[i].setFConst(result);
Arun Patole1155ddd2015-06-05 18:04:36 +05302633 }
Olli Etuahof119a262016-08-19 15:54:22 +03002634 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302635 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302636
Olli Etuahof119a262016-08-19 15:54:22 +03002637 case EOpMul:
Arun Patole7fa33552015-06-10 15:15:18 +05302638 {
Olli Etuahof119a262016-08-19 15:54:22 +03002639 ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
2640 (*sequence)[1]->getAsTyped()->isMatrix());
Arun Patole7fa33552015-06-10 15:15:18 +05302641 // Perform component-wise matrix multiplication.
2642 resultArray = new TConstantUnion[maxObjectSize];
Olli Etuahof119a262016-08-19 15:54:22 +03002643 int size = (*sequence)[0]->getAsTyped()->getNominalSize();
Arun Patole7fa33552015-06-10 15:15:18 +05302644 angle::Matrix<float> result =
2645 GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
2646 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002647 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302648 }
Arun Patole7fa33552015-06-10 15:15:18 +05302649
Olli Etuahof119a262016-08-19 15:54:22 +03002650 case EOpOuterProduct:
Arun Patole7fa33552015-06-10 15:15:18 +05302651 {
Olli Etuahof119a262016-08-19 15:54:22 +03002652 ASSERT(basicType == EbtFloat);
Arun Patole7fa33552015-06-10 15:15:18 +05302653 size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
2654 size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
Olli Etuahof119a262016-08-19 15:54:22 +03002655 resultArray = new TConstantUnion[numRows * numCols];
Arun Patole7fa33552015-06-10 15:15:18 +05302656 angle::Matrix<float> result =
Olli Etuahod5da5052016-08-29 13:16:55 +03002657 GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
2658 .outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
Arun Patole7fa33552015-06-10 15:15:18 +05302659 SetUnionArrayFromMatrix(result, resultArray);
Olli Etuahof119a262016-08-19 15:54:22 +03002660 break;
Arun Patole7fa33552015-06-10 15:15:18 +05302661 }
Arun Patole7fa33552015-06-10 15:15:18 +05302662
Olli Etuahof119a262016-08-19 15:54:22 +03002663 default:
2664 UNREACHABLE();
2665 // TODO: Add constant folding support for other built-in operations that take 2
2666 // parameters and not handled above.
2667 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302668 }
2669 }
2670 else if (paramsCount == 3)
2671 {
2672 //
2673 // Ternary built-in
2674 //
2675 switch (op)
2676 {
Olli Etuahof119a262016-08-19 15:54:22 +03002677 case EOpClamp:
Arun Patole274f0702015-05-05 13:33:30 +05302678 {
Olli Etuahob43846e2015-06-02 18:18:57 +03002679 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole274f0702015-05-05 13:33:30 +05302680 for (size_t i = 0; i < maxObjectSize; i++)
2681 {
2682 switch (basicType)
2683 {
Olli Etuahof119a262016-08-19 15:54:22 +03002684 case EbtFloat:
Arun Patole274f0702015-05-05 13:33:30 +05302685 {
Olli Etuahof119a262016-08-19 15:54:22 +03002686 float x = unionArrays[0][i].getFConst();
Arun Patole274f0702015-05-05 13:33:30 +05302687 float min = unionArrays[1][i].getFConst();
2688 float max = unionArrays[2][i].getFConst();
2689 // Results are undefined if min > max.
2690 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002691 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2692 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302693 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002694 resultArray[i].setFConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002695 break;
Arun Patole274f0702015-05-05 13:33:30 +05302696 }
Olli Etuahof119a262016-08-19 15:54:22 +03002697
2698 case EbtInt:
Arun Patole274f0702015-05-05 13:33:30 +05302699 {
Olli Etuahof119a262016-08-19 15:54:22 +03002700 int x = unionArrays[0][i].getIConst();
Arun Patole274f0702015-05-05 13:33:30 +05302701 int min = unionArrays[1][i].getIConst();
2702 int max = unionArrays[2][i].getIConst();
2703 // Results are undefined if min > max.
2704 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002705 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2706 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302707 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002708 resultArray[i].setIConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002709 break;
Arun Patole274f0702015-05-05 13:33:30 +05302710 }
Olli Etuahof119a262016-08-19 15:54:22 +03002711 case EbtUInt:
Arun Patole274f0702015-05-05 13:33:30 +05302712 {
Olli Etuahof119a262016-08-19 15:54:22 +03002713 unsigned int x = unionArrays[0][i].getUConst();
Arun Patole274f0702015-05-05 13:33:30 +05302714 unsigned int min = unionArrays[1][i].getUConst();
2715 unsigned int max = unionArrays[2][i].getUConst();
2716 // Results are undefined if min > max.
2717 if (min > max)
Olli Etuahof119a262016-08-19 15:54:22 +03002718 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2719 &resultArray[i]);
Arun Patole274f0702015-05-05 13:33:30 +05302720 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002721 resultArray[i].setUConst(gl::clamp(x, min, max));
Olli Etuahof119a262016-08-19 15:54:22 +03002722 break;
Arun Patole274f0702015-05-05 13:33:30 +05302723 }
Olli Etuahof119a262016-08-19 15:54:22 +03002724 default:
2725 UNREACHABLE();
2726 break;
Arun Patole274f0702015-05-05 13:33:30 +05302727 }
2728 }
Olli Etuahof119a262016-08-19 15:54:22 +03002729 break;
Arun Patole274f0702015-05-05 13:33:30 +05302730 }
Arun Patole274f0702015-05-05 13:33:30 +05302731
Olli Etuahof119a262016-08-19 15:54:22 +03002732 case EOpMix:
Arun Patolebf790422015-05-18 17:53:04 +05302733 {
Olli Etuahof119a262016-08-19 15:54:22 +03002734 ASSERT(basicType == EbtFloat);
2735 resultArray = new TConstantUnion[maxObjectSize];
2736 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302737 {
Olli Etuahof119a262016-08-19 15:54:22 +03002738 float x = unionArrays[0][i].getFConst();
2739 float y = unionArrays[1][i].getFConst();
2740 TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
2741 if (type == EbtFloat)
Arun Patolebf790422015-05-18 17:53:04 +05302742 {
Olli Etuahof119a262016-08-19 15:54:22 +03002743 // Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
2744 float a = unionArrays[2][i].getFConst();
2745 resultArray[i].setFConst(x * (1.0f - a) + y * a);
2746 }
2747 else // 3rd parameter is EbtBool
2748 {
2749 ASSERT(type == EbtBool);
2750 // Selects which vector each returned component comes from.
2751 // For a component of a that is false, the corresponding component of x is
2752 // returned.
2753 // For a component of a that is true, the corresponding component of y is
2754 // returned.
2755 bool a = unionArrays[2][i].getBConst();
2756 resultArray[i].setFConst(a ? y : x);
Arun Patolebf790422015-05-18 17:53:04 +05302757 }
2758 }
Olli Etuahof119a262016-08-19 15:54:22 +03002759 break;
Arun Patolebf790422015-05-18 17:53:04 +05302760 }
Arun Patolebf790422015-05-18 17:53:04 +05302761
Olli Etuahof119a262016-08-19 15:54:22 +03002762 case EOpSmoothStep:
Arun Patolebf790422015-05-18 17:53:04 +05302763 {
Olli Etuahof119a262016-08-19 15:54:22 +03002764 ASSERT(basicType == EbtFloat);
2765 resultArray = new TConstantUnion[maxObjectSize];
2766 for (size_t i = 0; i < maxObjectSize; i++)
Arun Patolebf790422015-05-18 17:53:04 +05302767 {
Olli Etuahof119a262016-08-19 15:54:22 +03002768 float edge0 = unionArrays[0][i].getFConst();
2769 float edge1 = unionArrays[1][i].getFConst();
2770 float x = unionArrays[2][i].getFConst();
2771 // Results are undefined if edge0 >= edge1.
2772 if (edge0 >= edge1)
Arun Patolebf790422015-05-18 17:53:04 +05302773 {
Olli Etuahof119a262016-08-19 15:54:22 +03002774 UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
2775 &resultArray[i]);
2776 }
2777 else
2778 {
2779 // Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
2780 // Hermite interpolation between 0 and 1 when edge0 < x < edge1.
2781 float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
2782 resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
Arun Patolebf790422015-05-18 17:53:04 +05302783 }
2784 }
Olli Etuahof119a262016-08-19 15:54:22 +03002785 break;
Arun Patolebf790422015-05-18 17:53:04 +05302786 }
Arun Patolebf790422015-05-18 17:53:04 +05302787
Olli Etuahof119a262016-08-19 15:54:22 +03002788 case EOpFaceForward:
Arun Patole1155ddd2015-06-05 18:04:36 +05302789 {
Olli Etuahof119a262016-08-19 15:54:22 +03002790 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302791 // genType faceforward(genType N, genType I, genType Nref) :
2792 // If dot(Nref, I) < 0 return N, otherwise return -N.
Olli Etuahof119a262016-08-19 15:54:22 +03002793 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302794 float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
2795 for (size_t i = 0; i < maxObjectSize; i++)
2796 {
2797 if (dotProduct < 0)
Olli Etuahob43846e2015-06-02 18:18:57 +03002798 resultArray[i].setFConst(unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302799 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002800 resultArray[i].setFConst(-unionArrays[0][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302801 }
Olli Etuahof119a262016-08-19 15:54:22 +03002802 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302803 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302804
Olli Etuahof119a262016-08-19 15:54:22 +03002805 case EOpRefract:
Arun Patole1155ddd2015-06-05 18:04:36 +05302806 {
Olli Etuahof119a262016-08-19 15:54:22 +03002807 ASSERT(basicType == EbtFloat);
Arun Patole1155ddd2015-06-05 18:04:36 +05302808 // genType refract(genType I, genType N, float eta) :
Olli Etuahof119a262016-08-19 15:54:22 +03002809 // For the incident vector I and surface normal N, and the ratio of indices of
2810 // refraction eta,
Arun Patole1155ddd2015-06-05 18:04:36 +05302811 // return the refraction vector. The result is computed by
2812 // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
2813 // if (k < 0.0)
2814 // return genType(0.0)
2815 // else
2816 // return eta * I - (eta * dot(N, I) + sqrt(k)) * N
Olli Etuahof119a262016-08-19 15:54:22 +03002817 resultArray = new TConstantUnion[maxObjectSize];
Arun Patole1155ddd2015-06-05 18:04:36 +05302818 float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
2819 for (size_t i = 0; i < maxObjectSize; i++)
2820 {
2821 float eta = unionArrays[2][i].getFConst();
Olli Etuahof119a262016-08-19 15:54:22 +03002822 float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
Arun Patole1155ddd2015-06-05 18:04:36 +05302823 if (k < 0.0f)
Olli Etuahob43846e2015-06-02 18:18:57 +03002824 resultArray[i].setFConst(0.0f);
Arun Patole1155ddd2015-06-05 18:04:36 +05302825 else
Olli Etuahob43846e2015-06-02 18:18:57 +03002826 resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
Olli Etuahof119a262016-08-19 15:54:22 +03002827 (eta * dotProduct + sqrtf(k)) *
2828 unionArrays[1][i].getFConst());
Arun Patole1155ddd2015-06-05 18:04:36 +05302829 }
Olli Etuahof119a262016-08-19 15:54:22 +03002830 break;
Arun Patole1155ddd2015-06-05 18:04:36 +05302831 }
Arun Patole1155ddd2015-06-05 18:04:36 +05302832
Olli Etuahof119a262016-08-19 15:54:22 +03002833 default:
2834 UNREACHABLE();
2835 // TODO: Add constant folding support for other built-in operations that take 3
2836 // parameters and not handled above.
2837 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +05302838 }
2839 }
Olli Etuahob43846e2015-06-02 18:18:57 +03002840 return resultArray;
Arun Patole274f0702015-05-05 13:33:30 +05302841}
2842
2843// static
Jamie Madillb1a85f42014-08-19 15:23:24 -04002844TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction)
2845{
2846 if (hashFunction == NULL || name.empty())
2847 return name;
2848 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
2849 TStringStream stream;
2850 stream << HASHED_NAME_PREFIX << std::hex << number;
2851 TString hashedName = stream.str();
2852 return hashedName;
2853}
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002854
2855void TIntermTraverser::updateTree()
2856{
Olli Etuahoa6f22092015-05-08 18:31:10 +03002857 for (size_t ii = 0; ii < mInsertions.size(); ++ii)
2858 {
2859 const NodeInsertMultipleEntry &insertion = mInsertions[ii];
2860 ASSERT(insertion.parent);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002861 if (!insertion.insertionsAfter.empty())
2862 {
2863 bool inserted = insertion.parent->insertChildNodes(insertion.position + 1,
2864 insertion.insertionsAfter);
2865 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002866 }
2867 if (!insertion.insertionsBefore.empty())
2868 {
2869 bool inserted =
2870 insertion.parent->insertChildNodes(insertion.position, insertion.insertionsBefore);
2871 ASSERT(inserted);
Olli Etuaho5d91dda2015-06-18 15:47:46 +03002872 }
Olli Etuahoa6f22092015-05-08 18:31:10 +03002873 }
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002874 for (size_t ii = 0; ii < mReplacements.size(); ++ii)
2875 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002876 const NodeUpdateEntry &replacement = mReplacements[ii];
2877 ASSERT(replacement.parent);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002878 bool replaced =
2879 replacement.parent->replaceChildNode(replacement.original, replacement.replacement);
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002880 ASSERT(replaced);
2881
Olli Etuahocd94ef92015-04-16 19:18:10 +03002882 if (!replacement.originalBecomesChildOfReplacement)
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002883 {
2884 // In AST traversing, a parent is visited before its children.
Olli Etuahocd94ef92015-04-16 19:18:10 +03002885 // After we replace a node, if its immediate child is to
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002886 // be replaced, we need to make sure we don't update the replaced
2887 // node; instead, we update the replacement node.
2888 for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
2889 {
Olli Etuahocd94ef92015-04-16 19:18:10 +03002890 NodeUpdateEntry &replacement2 = mReplacements[jj];
2891 if (replacement2.parent == replacement.original)
2892 replacement2.parent = replacement.replacement;
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002893 }
2894 }
2895 }
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03002896 for (size_t ii = 0; ii < mMultiReplacements.size(); ++ii)
2897 {
2898 const NodeReplaceWithMultipleEntry &replacement = mMultiReplacements[ii];
2899 ASSERT(replacement.parent);
Jamie Madilld7b1ab52016-12-12 14:42:19 -05002900 bool replaced = replacement.parent->replaceChildNodeWithMultiple(replacement.original,
2901 replacement.replacements);
Olli Etuahofc0e2bc2015-04-16 13:39:56 +03002902 ASSERT(replaced);
2903 }
Olli Etuahod4f303e2015-05-20 17:09:06 +03002904
Jamie Madill03d863c2016-07-27 18:15:53 -04002905 clearReplacementQueue();
2906}
2907
2908void TIntermTraverser::clearReplacementQueue()
2909{
Olli Etuahod4f303e2015-05-20 17:09:06 +03002910 mReplacements.clear();
2911 mMultiReplacements.clear();
Jamie Madill03d863c2016-07-27 18:15:53 -04002912 mInsertions.clear();
Olli Etuaho853dc1a2014-11-06 17:25:48 +02002913}
Jamie Madill1048e432016-07-23 18:51:28 -04002914
Jamie Madill03d863c2016-07-27 18:15:53 -04002915void TIntermTraverser::queueReplacement(TIntermNode *original,
2916 TIntermNode *replacement,
2917 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002918{
Jamie Madill03d863c2016-07-27 18:15:53 -04002919 queueReplacementWithParent(getParentNode(), original, replacement, originalStatus);
Jamie Madill1048e432016-07-23 18:51:28 -04002920}
2921
Jamie Madill03d863c2016-07-27 18:15:53 -04002922void TIntermTraverser::queueReplacementWithParent(TIntermNode *parent,
2923 TIntermNode *original,
2924 TIntermNode *replacement,
2925 OriginalNode originalStatus)
Jamie Madill1048e432016-07-23 18:51:28 -04002926{
Jamie Madill03d863c2016-07-27 18:15:53 -04002927 bool originalBecomesChild = (originalStatus == OriginalNode::BECOMES_CHILD);
2928 mReplacements.push_back(NodeUpdateEntry(parent, original, replacement, originalBecomesChild));
Jamie Madill1048e432016-07-23 18:51:28 -04002929}
Jamie Madill45bcc782016-11-07 13:58:48 -05002930
2931} // namespace sh