Edit

kc3-lang/angle/src/compiler/translator/DetectDiscontinuity.cpp

Branch :

  • Show log

    Commit

  • Author : Corentin Wallez
    Date : 2014-11-10 12:07:37
    Hash : 80bacde5
    Message : Use the [[flatten]] attribute only when a loop is present. Flattening branch-heavy shaders that contained no loops caused regressions. As a temporary workaround we only flatten ifs when there exists a loop. BUG=395048 Change-Id: I95c40f0249643b98c62304a0f2a4563561d1fbbc Reviewed-on: https://chromium-review.googlesource.com/228722 Reviewed-by: Shannon Woods <shannonwoods@chromium.org> Tested-by: Corentin Wallez <cwallez@chromium.org>

  • src/compiler/translator/DetectDiscontinuity.cpp
  • //
    // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // Contains analysis utilities for dealing with HLSL's lack of support for
    // the use of intrinsic functions which (implicitly or explicitly) compute
    // gradients of functions with discontinuities. 
    //
    
    #include "compiler/translator/DetectDiscontinuity.h"
    
    #include "compiler/translator/ParseContext.h"
    
    namespace sh
    {
    
    // Detect Loop Discontinuity
    
    bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
    {
        mLoopDepth = 0;
        mLoopDiscontinuity = false;
        node->traverse(this);
        return mLoopDiscontinuity;
    }
    
    bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop)
    {
        if (visit == PreVisit)
        {
            ++mLoopDepth;
        }
        else if (visit == PostVisit)
        {
            --mLoopDepth;
        }
    
        return true;
    }
    
    bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
    {
        if (mLoopDiscontinuity)
        {
            return false;
        }
    
        if (!mLoopDepth)
        {
            return true;
        }
    
        switch (node->getFlowOp())
        {
          case EOpKill:
            break;
          case EOpBreak:
          case EOpContinue:
          case EOpReturn:
            mLoopDiscontinuity = true;
            break;
          default: UNREACHABLE();
        }
    
        return !mLoopDiscontinuity;
    }
    
    bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
    {
        return !mLoopDiscontinuity;
    }
    
    bool containsLoopDiscontinuity(TIntermNode *node)
    {
        DetectLoopDiscontinuity detectLoopDiscontinuity;
        return detectLoopDiscontinuity.traverse(node);
    }
    
    // Detect Any Loop
    
    bool DetectAnyLoop::traverse(TIntermNode *node)
    {
        mHasLoop = false;
        node->traverse(this);
        return mHasLoop;
    }
    
    bool DetectAnyLoop::visitLoop(Visit visit, TIntermLoop *loop)
    {
        mHasLoop = true;
        return false;
    }
    
    // The following definitions stop all traversal when we have found a loop
    bool DetectAnyLoop::visitBinary(Visit, TIntermBinary *)
    {
        return !mHasLoop;
    }
    
    bool DetectAnyLoop::visitUnary(Visit, TIntermUnary *)
    {
        return !mHasLoop;
    }
    
    bool DetectAnyLoop::visitSelection(Visit, TIntermSelection *)
    {
        return !mHasLoop;
    }
    
    bool DetectAnyLoop::visitAggregate(Visit, TIntermAggregate *)
    {
        return !mHasLoop;
    }
    
    bool DetectAnyLoop::visitBranch(Visit, TIntermBranch *)
    {
        return !mHasLoop;
    }
    
    bool containsAnyLoop(TIntermNode *node)
    {
        DetectAnyLoop detectAnyLoop;
        return detectAnyLoop.traverse(node);
    }
    
    // Detect Gradient Operation
    
    bool DetectGradientOperation::traverse(TIntermNode *node)
    {
        mGradientOperation = false;
        node->traverse(this);
        return mGradientOperation;
    }
    
    bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
    {
        if (mGradientOperation)
        {
            return false;
        }
    
        switch (node->getOp())
        {
          case EOpDFdx:
          case EOpDFdy:
            mGradientOperation = true;
          default:
            break;
        }
    
        return !mGradientOperation;
    }
    
    bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
    {
        if (mGradientOperation)
        {
            return false;
        }
    
        if (node->getOp() == EOpFunctionCall)
        {
            if (!node->isUserDefined())
            {
                TString name = TFunction::unmangleName(node->getName());
    
                if (name == "texture2D" ||
                    name == "texture2DProj" ||
                    name == "textureCube")
                {
                    mGradientOperation = true;
                }
            }
            else
            {
                // When a user defined function is called, we have to
                // conservatively assume it to contain gradient operations
                mGradientOperation = true;
            }
        }
    
        return !mGradientOperation;
    }
    
    bool containsGradientOperation(TIntermNode *node)
    {
        DetectGradientOperation detectGradientOperation;
        return detectGradientOperation.traverse(node);
    }
    }