Home | History | Annotate | Download | only in MachineIndependent
      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 //
     36 // Traverse a tree of constants to create a single folded constant.
     37 // It should only be used when the whole tree is known to be constant.
     38 //
     39 
     40 #include "ParseHelper.h"
     41 
     42 namespace glslang {
     43 
     44 class TConstTraverser : public TIntermTraverser {
     45 public:
     46     TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
     47       : unionArray(cUnion), type(t),
     48         constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
     49         matrixCols(0), matrixRows(0) {  index = 0; tOp = EOpNull; }
     50 
     51     virtual void visitConstantUnion(TIntermConstantUnion* node);
     52     virtual bool visitAggregate(TVisit, TIntermAggregate* node);
     53 
     54     int index;
     55     TConstUnionArray unionArray;
     56     TOperator tOp;
     57     const TType& type;
     58     TOperator constructorType;
     59     bool singleConstantParam;
     60     bool error;
     61     int size; // size of the constructor ( 4 for vec4)
     62     bool isMatrix;
     63     int matrixCols;
     64     int matrixRows;
     65 
     66 protected:
     67     TConstTraverser(TConstTraverser&);
     68     TConstTraverser& operator=(TConstTraverser&);
     69 };
     70 
     71 bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
     72 {
     73     if (! node->isConstructor() && node->getOp() != EOpComma) {
     74         error = true;
     75 
     76         return false;
     77     }
     78 
     79     bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
     80     if (flag) {
     81         singleConstantParam = true;
     82         constructorType = node->getOp();
     83         size = node->getType().computeNumComponents();
     84 
     85         if (node->getType().isMatrix()) {
     86             isMatrix = true;
     87             matrixCols = node->getType().getMatrixCols();
     88             matrixRows = node->getType().getMatrixRows();
     89         }
     90     }
     91 
     92     for (TIntermSequence::iterator p = node->getSequence().begin();
     93                                    p != node->getSequence().end(); p++) {
     94 
     95         if (node->getOp() == EOpComma)
     96             index = 0;
     97 
     98         (*p)->traverse(this);
     99     }
    100     if (flag)
    101     {
    102         singleConstantParam = false;
    103         constructorType = EOpNull;
    104         size = 0;
    105         isMatrix = false;
    106         matrixCols = 0;
    107         matrixRows = 0;
    108     }
    109 
    110     return false;
    111 }
    112 
    113 void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
    114 {
    115     TConstUnionArray leftUnionArray(unionArray);
    116     int instanceSize = type.computeNumComponents();
    117 
    118     if (index >= instanceSize)
    119         return;
    120 
    121     if (! singleConstantParam) {
    122         int rightUnionSize = node->getType().computeNumComponents();
    123 
    124         const TConstUnionArray& rightUnionArray = node->getConstArray();
    125         for (int i = 0; i < rightUnionSize; i++) {
    126             if (index >= instanceSize)
    127                 return;
    128             leftUnionArray[index] = rightUnionArray[i];
    129 
    130             index++;
    131         }
    132     } else {
    133         int endIndex = index + size;
    134         const TConstUnionArray& rightUnionArray = node->getConstArray();
    135         if (! isMatrix) {
    136             int count = 0;
    137             int nodeComps = node->getType().computeNumComponents();
    138             for (int i = index; i < endIndex; i++) {
    139                 if (i >= instanceSize)
    140                     return;
    141 
    142                 leftUnionArray[i] = rightUnionArray[count];
    143 
    144                 (index)++;
    145 
    146                 if (nodeComps > 1)
    147                     count++;
    148             }
    149         } else {
    150             // constructing a matrix, but from what?
    151             if (node->isMatrix()) {
    152                 // Matrix from a matrix; this has the outer matrix, node is the argument matrix.
    153                 // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
    154                 // identity matrix.
    155                 for (int c = 0; c < matrixCols; ++c) {
    156                     for (int r = 0; r < matrixRows; ++r) {
    157                         int targetOffset = index + c * matrixRows + r;
    158                         if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
    159                             int srcOffset = c * node->getType().getMatrixRows() + r;
    160                             leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
    161                         } else if (r == c)
    162                             leftUnionArray[targetOffset].setDConst(1.0);
    163                         else
    164                             leftUnionArray[targetOffset].setDConst(0.0);
    165                     }
    166                 }
    167             } else {
    168                 // matrix from vector
    169                 int count = 0;
    170                 const int startIndex = index;
    171                 int nodeComps = node->getType().computeNumComponents();
    172                 for (int i = startIndex; i < endIndex; i++) {
    173                     if (i >= instanceSize)
    174                         return;
    175                     if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
    176                         leftUnionArray[i] = rightUnionArray[count];
    177                     else
    178                         leftUnionArray[i].setDConst(0.0);
    179 
    180                     index++;
    181 
    182                     if (nodeComps > 1)
    183                         count++;
    184                 }
    185             }
    186         }
    187     }
    188 }
    189 
    190 bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
    191 {
    192     if (root == 0)
    193         return false;
    194 
    195     TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
    196 
    197     root->traverse(&it);
    198     if (it.error)
    199         return true;
    200     else
    201         return false;
    202 }
    203 
    204 } // end namespace glslang
    205