parseConst.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. //
  2. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions
  7. // are met:
  8. //
  9. // Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. //
  12. // Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following
  14. // disclaimer in the documentation and/or other materials provided
  15. // with the distribution.
  16. //
  17. // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
  18. // contributors may be used to endorse or promote products derived
  19. // from this software without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. // POSSIBILITY OF SUCH DAMAGE.
  33. //
  34. //
  35. // Traverse a tree of constants to create a single folded constant.
  36. // It should only be used when the whole tree is known to be constant.
  37. //
  38. #include "ParseHelper.h"
  39. namespace glslang {
  40. class TConstTraverser : public TIntermTraverser {
  41. public:
  42. TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
  43. : unionArray(cUnion), type(t),
  44. constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
  45. matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
  46. virtual void visitConstantUnion(TIntermConstantUnion* node);
  47. virtual bool visitAggregate(TVisit, TIntermAggregate* node);
  48. int index;
  49. TConstUnionArray unionArray;
  50. TOperator tOp;
  51. const TType& type;
  52. TOperator constructorType;
  53. bool singleConstantParam;
  54. bool error;
  55. int size; // size of the constructor ( 4 for vec4)
  56. bool isMatrix;
  57. int matrixCols;
  58. int matrixRows;
  59. protected:
  60. TConstTraverser(TConstTraverser&);
  61. TConstTraverser& operator=(TConstTraverser&);
  62. };
  63. bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
  64. {
  65. if (! node->isConstructor() && node->getOp() != EOpComma) {
  66. error = true;
  67. return false;
  68. }
  69. bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
  70. if (flag) {
  71. singleConstantParam = true;
  72. constructorType = node->getOp();
  73. size = node->getType().computeNumComponents();
  74. if (node->getType().isMatrix()) {
  75. isMatrix = true;
  76. matrixCols = node->getType().getMatrixCols();
  77. matrixRows = node->getType().getMatrixRows();
  78. }
  79. }
  80. for (TIntermSequence::iterator p = node->getSequence().begin();
  81. p != node->getSequence().end(); p++) {
  82. if (node->getOp() == EOpComma)
  83. index = 0;
  84. (*p)->traverse(this);
  85. }
  86. if (flag)
  87. {
  88. singleConstantParam = false;
  89. constructorType = EOpNull;
  90. size = 0;
  91. isMatrix = false;
  92. matrixCols = 0;
  93. matrixRows = 0;
  94. }
  95. return false;
  96. }
  97. void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
  98. {
  99. TConstUnionArray leftUnionArray(unionArray);
  100. int instanceSize = type.computeNumComponents();
  101. if (index >= instanceSize)
  102. return;
  103. if (! singleConstantParam) {
  104. int rightUnionSize = node->getType().computeNumComponents();
  105. const TConstUnionArray& rightUnionArray = node->getConstArray();
  106. for (int i = 0; i < rightUnionSize; i++) {
  107. if (index >= instanceSize)
  108. return;
  109. leftUnionArray[index] = rightUnionArray[i];
  110. index++;
  111. }
  112. } else {
  113. int endIndex = index + size;
  114. const TConstUnionArray& rightUnionArray = node->getConstArray();
  115. if (! isMatrix) {
  116. int count = 0;
  117. int nodeComps = node->getType().computeNumComponents();
  118. for (int i = index; i < endIndex; i++) {
  119. if (i >= instanceSize)
  120. return;
  121. leftUnionArray[i] = rightUnionArray[count];
  122. (index)++;
  123. if (nodeComps > 1)
  124. count++;
  125. }
  126. } else {
  127. // constructing a matrix, but from what?
  128. if (node->isMatrix()) {
  129. // Matrix from a matrix; this has the outer matrix, node is the argument matrix.
  130. // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
  131. // identity matrix.
  132. for (int c = 0; c < matrixCols; ++c) {
  133. for (int r = 0; r < matrixRows; ++r) {
  134. int targetOffset = index + c * matrixRows + r;
  135. if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
  136. int srcOffset = c * node->getType().getMatrixRows() + r;
  137. leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
  138. } else if (r == c)
  139. leftUnionArray[targetOffset].setDConst(1.0);
  140. else
  141. leftUnionArray[targetOffset].setDConst(0.0);
  142. }
  143. }
  144. } else {
  145. // matrix from vector or scalar
  146. int count = 0;
  147. const int startIndex = index;
  148. int nodeComps = node->getType().computeNumComponents();
  149. for (int i = startIndex; i < endIndex; i++) {
  150. if (i >= instanceSize)
  151. return;
  152. if (nodeComps == 1) {
  153. // If there is a single scalar parameter to a matrix
  154. // constructor, it is used to initialize all the
  155. // components on the matrix's diagonal, with the
  156. // remaining components initialized to 0.0.
  157. if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
  158. leftUnionArray[i] = rightUnionArray[count];
  159. else
  160. leftUnionArray[i].setDConst(0.0);
  161. } else {
  162. // construct the matrix in column-major order, from
  163. // the components provided, in order
  164. leftUnionArray[i] = rightUnionArray[count];
  165. }
  166. index++;
  167. if (nodeComps > 1)
  168. count++;
  169. }
  170. }
  171. }
  172. }
  173. }
  174. bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
  175. {
  176. if (root == 0)
  177. return false;
  178. TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
  179. root->traverse(&it);
  180. if (it.error)
  181. return true;
  182. else
  183. return false;
  184. }
  185. } // end namespace glslang