Edit

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

Branch :

  • Show log

    Commit

  • Author : daniel@transgaming.com
    Date : 2012-05-31 01:20:24
    Hash : 79744f22
    Message : Added a traverser for detecting gradient operations. TRAC #20737 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@1121 736b8ea6-26fd-11df-bfd4-992fa37f6226

  • src/compiler/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/DetectDiscontinuity.h"
    
    #include "compiler/ParseHelper.h"
    
    namespace sh
    {
    bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
    {
        mLoopDiscontinuity = false;
        node->traverse(this);
        return mLoopDiscontinuity;
    }
    
    bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
    {
        if (mLoopDiscontinuity)
        {
            return false;
        }
    
        switch (node->getFlowOp())
        {
          case EOpKill:
            break;
          case EOpBreak:
          case EOpContinue:
            mLoopDiscontinuity = true;
          case EOpReturn:
            break;
          default: UNREACHABLE();
        }
    
        return !mLoopDiscontinuity;
    }
    
    bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
    {
        return !mLoopDiscontinuity;
    }
    
    bool containsLoopDiscontinuity(TIntermNode *node)
    {
        DetectLoopDiscontinuity detectLoopDiscontinuity;
        return detectLoopDiscontinuity.traverse(node);
    }
    
    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);
    }
    }