Home | History | Annotate | Download | only in translator
      1 //
      2 // Copyright (c) 2012 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 // Contains analysis utilities for dealing with HLSL's lack of support for
      7 // the use of intrinsic functions which (implicitly or explicitly) compute
      8 // gradients of functions with discontinuities.
      9 //
     10 
     11 #include "compiler/translator/DetectDiscontinuity.h"
     12 
     13 #include "compiler/translator/ParseContext.h"
     14 
     15 namespace sh
     16 {
     17 bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
     18 {
     19     mLoopDepth = 0;
     20     mLoopDiscontinuity = false;
     21     node->traverse(this);
     22     return mLoopDiscontinuity;
     23 }
     24 
     25 bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop)
     26 {
     27     if (visit == PreVisit)
     28     {
     29         ++mLoopDepth;
     30     }
     31     else if (visit == PostVisit)
     32     {
     33         --mLoopDepth;
     34     }
     35 
     36     return true;
     37 }
     38 
     39 bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
     40 {
     41     if (mLoopDiscontinuity)
     42     {
     43         return false;
     44     }
     45 
     46     if (!mLoopDepth)
     47     {
     48         return true;
     49     }
     50 
     51     switch (node->getFlowOp())
     52     {
     53       case EOpKill:
     54         break;
     55       case EOpBreak:
     56       case EOpContinue:
     57       case EOpReturn:
     58         mLoopDiscontinuity = true;
     59         break;
     60       default: UNREACHABLE();
     61     }
     62 
     63     return !mLoopDiscontinuity;
     64 }
     65 
     66 bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
     67 {
     68     return !mLoopDiscontinuity;
     69 }
     70 
     71 bool containsLoopDiscontinuity(TIntermNode *node)
     72 {
     73     DetectLoopDiscontinuity detectLoopDiscontinuity;
     74     return detectLoopDiscontinuity.traverse(node);
     75 }
     76 
     77 bool DetectGradientOperation::traverse(TIntermNode *node)
     78 {
     79     mGradientOperation = false;
     80     node->traverse(this);
     81     return mGradientOperation;
     82 }
     83 
     84 bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
     85 {
     86     if (mGradientOperation)
     87     {
     88         return false;
     89     }
     90 
     91     switch (node->getOp())
     92     {
     93       case EOpDFdx:
     94       case EOpDFdy:
     95         mGradientOperation = true;
     96       default:
     97         break;
     98     }
     99 
    100     return !mGradientOperation;
    101 }
    102 
    103 bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
    104 {
    105     if (mGradientOperation)
    106     {
    107         return false;
    108     }
    109 
    110     if (node->getOp() == EOpFunctionCall)
    111     {
    112         if (!node->isUserDefined())
    113         {
    114             TString name = TFunction::unmangleName(node->getName());
    115 
    116             if (name == "texture2D" ||
    117                 name == "texture2DProj" ||
    118                 name == "textureCube")
    119             {
    120                 mGradientOperation = true;
    121             }
    122         }
    123         else
    124         {
    125             // When a user defined function is called, we have to
    126             // conservatively assume it to contain gradient operations
    127             mGradientOperation = true;
    128         }
    129     }
    130 
    131     return !mGradientOperation;
    132 }
    133 
    134 bool containsGradientOperation(TIntermNode *node)
    135 {
    136     DetectGradientOperation detectGradientOperation;
    137     return detectGradientOperation.traverse(node);
    138 }
    139 }
    140