LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - ScalarizeVecAndMatConstructorArgs.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 126 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       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             : // Scalarize vector and matrix constructor args, so that vectors built from components don't have
       7             : // matrix arguments, and matrices built from components don't have vector arguments. This avoids
       8             : // driver bugs around vector and matrix constructors.
       9             : //
      10             : 
      11             : #include "common/debug.h"
      12             : #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
      13             : 
      14             : #include <algorithm>
      15             : 
      16             : #include "angle_gl.h"
      17             : #include "common/angleutils.h"
      18             : #include "compiler/translator/IntermNode.h"
      19             : 
      20             : namespace sh
      21             : {
      22             : 
      23             : namespace
      24             : {
      25             : 
      26           0 : bool ContainsMatrixNode(const TIntermSequence &sequence)
      27             : {
      28           0 :     for (size_t ii = 0; ii < sequence.size(); ++ii)
      29             :     {
      30           0 :         TIntermTyped *node = sequence[ii]->getAsTyped();
      31           0 :         if (node && node->isMatrix())
      32           0 :             return true;
      33             :     }
      34           0 :     return false;
      35             : }
      36             : 
      37           0 : bool ContainsVectorNode(const TIntermSequence &sequence)
      38             : {
      39           0 :     for (size_t ii = 0; ii < sequence.size(); ++ii)
      40             :     {
      41           0 :         TIntermTyped *node = sequence[ii]->getAsTyped();
      42           0 :         if (node && node->isVector())
      43           0 :             return true;
      44             :     }
      45           0 :     return false;
      46             : }
      47             : 
      48           0 : TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index)
      49             : {
      50           0 :     return new TIntermBinary(EOpIndexDirect, symbolNode, TIntermTyped::CreateIndexNode(index));
      51             : }
      52             : 
      53           0 : TIntermBinary *ConstructMatrixIndexBinaryNode(
      54             :     TIntermSymbol *symbolNode, int colIndex, int rowIndex)
      55             : {
      56             :     TIntermBinary *colVectorNode =
      57           0 :         ConstructVectorIndexBinaryNode(symbolNode, colIndex);
      58             : 
      59             :     return new TIntermBinary(EOpIndexDirect, colVectorNode,
      60           0 :                              TIntermTyped::CreateIndexNode(rowIndex));
      61             : }
      62             : 
      63           0 : class ScalarizeArgsTraverser : public TIntermTraverser
      64             : {
      65             :   public:
      66           0 :     ScalarizeArgsTraverser(sh::GLenum shaderType,
      67             :                            bool fragmentPrecisionHigh,
      68             :                            unsigned int *temporaryIndex)
      69           0 :         : TIntermTraverser(true, false, false),
      70             :           mShaderType(shaderType),
      71           0 :           mFragmentPrecisionHigh(fragmentPrecisionHigh)
      72             :     {
      73           0 :         useTemporaryIndex(temporaryIndex);
      74           0 :     }
      75             : 
      76             :   protected:
      77             :     bool visitAggregate(Visit visit, TIntermAggregate *node) override;
      78             :     bool visitBlock(Visit visit, TIntermBlock *node) override;
      79             : 
      80             :   private:
      81             :     void scalarizeArgs(TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix);
      82             : 
      83             :     // If we have the following code:
      84             :     //   mat4 m(0);
      85             :     //   vec4 v(1, m);
      86             :     // We will rewrite to:
      87             :     //   mat4 m(0);
      88             :     //   mat4 s0 = m;
      89             :     //   vec4 v(1, s0[0][0], s0[0][1], s0[0][2]);
      90             :     // This function is to create nodes for "mat4 s0 = m;" and insert it to the code sequence. This
      91             :     // way the possible side effects of the constructor argument will only be evaluated once.
      92             :     void createTempVariable(TIntermTyped *original);
      93             : 
      94             :     std::vector<TIntermSequence> mBlockStack;
      95             : 
      96             :     sh::GLenum mShaderType;
      97             :     bool mFragmentPrecisionHigh;
      98             : };
      99             : 
     100           0 : bool ScalarizeArgsTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
     101             : {
     102           0 :     if (visit == PreVisit)
     103             :     {
     104           0 :         switch (node->getOp())
     105             :         {
     106             :           case EOpConstructVec2:
     107             :           case EOpConstructVec3:
     108             :           case EOpConstructVec4:
     109             :           case EOpConstructBVec2:
     110             :           case EOpConstructBVec3:
     111             :           case EOpConstructBVec4:
     112             :           case EOpConstructIVec2:
     113             :           case EOpConstructIVec3:
     114             :           case EOpConstructIVec4:
     115           0 :             if (ContainsMatrixNode(*(node->getSequence())))
     116           0 :                 scalarizeArgs(node, false, true);
     117           0 :             break;
     118             :           case EOpConstructMat2:
     119             :           case EOpConstructMat2x3:
     120             :           case EOpConstructMat2x4:
     121             :           case EOpConstructMat3x2:
     122             :           case EOpConstructMat3:
     123             :           case EOpConstructMat3x4:
     124             :           case EOpConstructMat4x2:
     125             :           case EOpConstructMat4x3:
     126             :           case EOpConstructMat4:
     127           0 :             if (ContainsVectorNode(*(node->getSequence())))
     128           0 :                 scalarizeArgs(node, true, false);
     129           0 :             break;
     130             :           default:
     131           0 :             break;
     132             :         }
     133             :     }
     134           0 :     return true;
     135             : }
     136             : 
     137           0 : bool ScalarizeArgsTraverser::visitBlock(Visit visit, TIntermBlock *node)
     138             : {
     139           0 :     mBlockStack.push_back(TIntermSequence());
     140             :     {
     141           0 :         for (TIntermNode *child : *node->getSequence())
     142             :         {
     143           0 :             ASSERT(child != nullptr);
     144           0 :             child->traverse(this);
     145           0 :             mBlockStack.back().push_back(child);
     146             :         }
     147             :     }
     148           0 :     if (mBlockStack.back().size() > node->getSequence()->size())
     149             :     {
     150           0 :         node->getSequence()->clear();
     151           0 :         *(node->getSequence()) = mBlockStack.back();
     152             :     }
     153           0 :     mBlockStack.pop_back();
     154           0 :     return false;
     155             : }
     156             : 
     157           0 : void ScalarizeArgsTraverser::scalarizeArgs(TIntermAggregate *aggregate,
     158             :                                            bool scalarizeVector,
     159             :                                            bool scalarizeMatrix)
     160             : {
     161           0 :     ASSERT(aggregate);
     162           0 :     int size = 0;
     163           0 :     switch (aggregate->getOp())
     164             :     {
     165             :       case EOpConstructVec2:
     166             :       case EOpConstructBVec2:
     167             :       case EOpConstructIVec2:
     168           0 :         size = 2;
     169           0 :         break;
     170             :       case EOpConstructVec3:
     171             :       case EOpConstructBVec3:
     172             :       case EOpConstructIVec3:
     173           0 :         size = 3;
     174           0 :         break;
     175             :       case EOpConstructVec4:
     176             :       case EOpConstructBVec4:
     177             :       case EOpConstructIVec4:
     178             :       case EOpConstructMat2:
     179           0 :         size = 4;
     180           0 :         break;
     181             :       case EOpConstructMat2x3:
     182             :       case EOpConstructMat3x2:
     183           0 :         size = 6;
     184           0 :         break;
     185             :       case EOpConstructMat2x4:
     186             :       case EOpConstructMat4x2:
     187           0 :         size = 8;
     188           0 :         break;
     189             :       case EOpConstructMat3:
     190           0 :         size = 9;
     191           0 :         break;
     192             :       case EOpConstructMat3x4:
     193             :       case EOpConstructMat4x3:
     194           0 :         size = 12;
     195           0 :         break;
     196             :       case EOpConstructMat4:
     197           0 :         size = 16;
     198           0 :         break;
     199             :       default:
     200           0 :         break;
     201             :     }
     202           0 :     TIntermSequence *sequence = aggregate->getSequence();
     203           0 :     TIntermSequence original(*sequence);
     204           0 :     sequence->clear();
     205           0 :     for (size_t ii = 0; ii < original.size(); ++ii)
     206             :     {
     207           0 :         ASSERT(size > 0);
     208           0 :         TIntermTyped *node = original[ii]->getAsTyped();
     209           0 :         ASSERT(node);
     210           0 :         createTempVariable(node);
     211           0 :         if (node->isScalar())
     212             :         {
     213           0 :             sequence->push_back(createTempSymbol(node->getType()));
     214           0 :             size--;
     215             :         }
     216           0 :         else if (node->isVector())
     217             :         {
     218           0 :             if (scalarizeVector)
     219             :             {
     220           0 :                 int repeat = std::min(size, node->getNominalSize());
     221           0 :                 size -= repeat;
     222           0 :                 for (int index = 0; index < repeat; ++index)
     223             :                 {
     224           0 :                     TIntermSymbol *symbolNode = createTempSymbol(node->getType());
     225             :                     TIntermBinary *newNode = ConstructVectorIndexBinaryNode(
     226           0 :                         symbolNode, index);
     227           0 :                     sequence->push_back(newNode);
     228             :                 }
     229             :             }
     230             :             else
     231             :             {
     232           0 :                 TIntermSymbol *symbolNode = createTempSymbol(node->getType());
     233           0 :                 sequence->push_back(symbolNode);
     234           0 :                 size -= node->getNominalSize();
     235             :             }
     236             :         }
     237             :         else
     238             :         {
     239           0 :             ASSERT(node->isMatrix());
     240           0 :             if (scalarizeMatrix)
     241             :             {
     242           0 :                 int colIndex = 0, rowIndex = 0;
     243           0 :                 int repeat = std::min(size, node->getCols() * node->getRows());
     244           0 :                 size -= repeat;
     245           0 :                 while (repeat > 0)
     246             :                 {
     247           0 :                     TIntermSymbol *symbolNode = createTempSymbol(node->getType());
     248             :                     TIntermBinary *newNode = ConstructMatrixIndexBinaryNode(
     249           0 :                         symbolNode, colIndex, rowIndex);
     250           0 :                     sequence->push_back(newNode);
     251           0 :                     rowIndex++;
     252           0 :                     if (rowIndex >= node->getRows())
     253             :                     {
     254           0 :                         rowIndex = 0;
     255           0 :                         colIndex++;
     256             :                     }
     257           0 :                     repeat--;
     258             :                 }
     259             :             }
     260             :             else
     261             :             {
     262           0 :                 TIntermSymbol *symbolNode = createTempSymbol(node->getType());
     263           0 :                 sequence->push_back(symbolNode);
     264           0 :                 size -= node->getCols() * node->getRows();
     265             :             }
     266             :         }
     267             :     }
     268           0 : }
     269             : 
     270           0 : void ScalarizeArgsTraverser::createTempVariable(TIntermTyped *original)
     271             : {
     272           0 :     ASSERT(original);
     273           0 :     nextTemporaryIndex();
     274           0 :     TIntermDeclaration *decl = createTempInitDeclaration(original);
     275             : 
     276           0 :     TType type = original->getType();
     277           0 :     if (mShaderType == GL_FRAGMENT_SHADER &&
     278           0 :         type.getBasicType() == EbtFloat &&
     279           0 :         type.getPrecision() == EbpUndefined)
     280             :     {
     281             :         // We use the highest available precision for the temporary variable
     282             :         // to avoid computing the actual precision using the rules defined
     283             :         // in GLSL ES 1.0 Section 4.5.2.
     284           0 :         TIntermBinary *init = decl->getSequence()->at(0)->getAsBinaryNode();
     285           0 :         init->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
     286           0 :         init->getLeft()->getTypePointer()->setPrecision(mFragmentPrecisionHigh ? EbpHigh
     287           0 :                                                                                : EbpMedium);
     288             :     }
     289             : 
     290           0 :     ASSERT(mBlockStack.size() > 0);
     291           0 :     TIntermSequence &sequence = mBlockStack.back();
     292           0 :     sequence.push_back(decl);
     293           0 : }
     294             : 
     295             : }  // namespace anonymous
     296             : 
     297           0 : void ScalarizeVecAndMatConstructorArgs(TIntermBlock *root,
     298             :                                        sh::GLenum shaderType,
     299             :                                        bool fragmentPrecisionHigh,
     300             :                                        unsigned int *temporaryIndex)
     301             : {
     302           0 :     ScalarizeArgsTraverser scalarizer(shaderType, fragmentPrecisionHigh, temporaryIndex);
     303           0 :     root->traverse(&scalarizer);
     304           0 : }
     305             : 
     306             : }  // namespace sh

Generated by: LCOV version 1.13