Constant.cpp 61 KB

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