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

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2016 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             : // gl_FragColor needs to broadcast to all color buffers in ES2 if
       7             : // GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
       8             : //
       9             : // We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end
      10             : // of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1]
      11             : // with gl_FragData[0].
      12             : //
      13             : 
      14             : #include "compiler/translator/EmulateGLFragColorBroadcast.h"
      15             : #include "compiler/translator/IntermNode.h"
      16             : 
      17             : namespace sh
      18             : {
      19             : 
      20             : namespace
      21             : {
      22             : 
      23           0 : class GLFragColorBroadcastTraverser : public TIntermTraverser
      24             : {
      25             :   public:
      26           0 :     GLFragColorBroadcastTraverser(int maxDrawBuffers)
      27           0 :         : TIntermTraverser(true, false, false),
      28             :           mMainSequence(nullptr),
      29             :           mGLFragColorUsed(false),
      30           0 :           mMaxDrawBuffers(maxDrawBuffers)
      31             :     {
      32           0 :     }
      33             : 
      34             :     void broadcastGLFragColor();
      35             : 
      36           0 :     bool isGLFragColorUsed() const { return mGLFragColorUsed; }
      37             : 
      38             :   protected:
      39             :     void visitSymbol(TIntermSymbol *node) override;
      40             :     bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
      41             : 
      42             :     TIntermBinary *constructGLFragDataNode(int index) const;
      43             :     TIntermBinary *constructGLFragDataAssignNode(int index) const;
      44             : 
      45             :   private:
      46             :     TIntermSequence *mMainSequence;
      47             :     bool mGLFragColorUsed;
      48             :     int mMaxDrawBuffers;
      49             : };
      50             : 
      51           0 : TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
      52             : {
      53           0 :     TType gl_FragDataType = TType(EbtFloat, EbpMedium, EvqFragData, 4);
      54           0 :     gl_FragDataType.setArraySize(mMaxDrawBuffers);
      55             : 
      56           0 :     TIntermSymbol *symbol   = new TIntermSymbol(0, "gl_FragData", gl_FragDataType);
      57           0 :     TIntermTyped *indexNode = TIntermTyped::CreateIndexNode(index);
      58             : 
      59           0 :     TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
      60           0 :     return binary;
      61             : }
      62             : 
      63           0 : TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const
      64             : {
      65           0 :     TIntermTyped *fragDataIndex = constructGLFragDataNode(index);
      66           0 :     TIntermTyped *fragDataZero  = constructGLFragDataNode(0);
      67             : 
      68           0 :     return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero);
      69             : }
      70             : 
      71           0 : void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
      72             : {
      73           0 :     if (node->getSymbol() == "gl_FragColor")
      74             :     {
      75           0 :         queueReplacement(node, constructGLFragDataNode(0), OriginalNode::IS_DROPPED);
      76           0 :         mGLFragColorUsed = true;
      77             :     }
      78           0 : }
      79             : 
      80           0 : bool GLFragColorBroadcastTraverser::visitFunctionDefinition(Visit visit,
      81             :                                                             TIntermFunctionDefinition *node)
      82             : {
      83           0 :     ASSERT(visit == PreVisit);
      84           0 :     if (node->getFunctionSymbolInfo()->isMain())
      85             :     {
      86           0 :         TIntermBlock *body = node->getBody();
      87           0 :         ASSERT(body);
      88           0 :         mMainSequence = body->getSequence();
      89             :     }
      90           0 :     return true;
      91             : }
      92             : 
      93           0 : void GLFragColorBroadcastTraverser::broadcastGLFragColor()
      94             : {
      95           0 :     ASSERT(mMaxDrawBuffers > 1);
      96           0 :     if (!mGLFragColorUsed)
      97             :     {
      98           0 :         return;
      99             :     }
     100           0 :     ASSERT(mMainSequence);
     101             :     // Now insert statements
     102             :     //   gl_FragData[1] = gl_FragData[0];
     103             :     //   ...
     104             :     //   gl_FragData[maxDrawBuffers - 1] = gl_FragData[0];
     105           0 :     for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex)
     106             :     {
     107           0 :         mMainSequence->insert(mMainSequence->end(), constructGLFragDataAssignNode(colorIndex));
     108             :     }
     109             : }
     110             : 
     111             : }  // namespace anonymous
     112             : 
     113           0 : void EmulateGLFragColorBroadcast(TIntermNode *root,
     114             :                                  int maxDrawBuffers,
     115             :                                  std::vector<sh::OutputVariable> *outputVariables)
     116             : {
     117           0 :     ASSERT(maxDrawBuffers > 1);
     118           0 :     GLFragColorBroadcastTraverser traverser(maxDrawBuffers);
     119           0 :     root->traverse(&traverser);
     120           0 :     if (traverser.isGLFragColorUsed())
     121             :     {
     122           0 :         traverser.updateTree();
     123           0 :         traverser.broadcastGLFragColor();
     124           0 :         for (auto &var : *outputVariables)
     125             :         {
     126           0 :             if (var.name == "gl_FragColor")
     127             :             {
     128             :                 // TODO(zmo): Find a way to keep the original variable information.
     129           0 :                 var.name       = "gl_FragData";
     130           0 :                 var.mappedName = "gl_FragData";
     131           0 :                 var.arraySize  = maxDrawBuffers;
     132             :             }
     133             :         }
     134             :     }
     135           0 : }
     136             : 
     137             : }  // namespace sh

Generated by: LCOV version 1.13