1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/DetectDiscontinuity.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,139 @@ 1.4 +// 1.5 +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 +// Contains analysis utilities for dealing with HLSL's lack of support for 1.10 +// the use of intrinsic functions which (implicitly or explicitly) compute 1.11 +// gradients of functions with discontinuities. 1.12 +// 1.13 + 1.14 +#include "compiler/DetectDiscontinuity.h" 1.15 + 1.16 +#include "compiler/ParseHelper.h" 1.17 + 1.18 +namespace sh 1.19 +{ 1.20 +bool DetectLoopDiscontinuity::traverse(TIntermNode *node) 1.21 +{ 1.22 + mLoopDepth = 0; 1.23 + mLoopDiscontinuity = false; 1.24 + node->traverse(this); 1.25 + return mLoopDiscontinuity; 1.26 +} 1.27 + 1.28 +bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop) 1.29 +{ 1.30 + if (visit == PreVisit) 1.31 + { 1.32 + ++mLoopDepth; 1.33 + } 1.34 + else if (visit == PostVisit) 1.35 + { 1.36 + --mLoopDepth; 1.37 + } 1.38 + 1.39 + return true; 1.40 +} 1.41 + 1.42 +bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node) 1.43 +{ 1.44 + if (mLoopDiscontinuity) 1.45 + { 1.46 + return false; 1.47 + } 1.48 + 1.49 + if (!mLoopDepth) 1.50 + { 1.51 + return true; 1.52 + } 1.53 + 1.54 + switch (node->getFlowOp()) 1.55 + { 1.56 + case EOpKill: 1.57 + break; 1.58 + case EOpBreak: 1.59 + case EOpContinue: 1.60 + case EOpReturn: 1.61 + mLoopDiscontinuity = true; 1.62 + break; 1.63 + default: UNREACHABLE(); 1.64 + } 1.65 + 1.66 + return !mLoopDiscontinuity; 1.67 +} 1.68 + 1.69 +bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node) 1.70 +{ 1.71 + return !mLoopDiscontinuity; 1.72 +} 1.73 + 1.74 +bool containsLoopDiscontinuity(TIntermNode *node) 1.75 +{ 1.76 + DetectLoopDiscontinuity detectLoopDiscontinuity; 1.77 + return detectLoopDiscontinuity.traverse(node); 1.78 +} 1.79 + 1.80 +bool DetectGradientOperation::traverse(TIntermNode *node) 1.81 +{ 1.82 + mGradientOperation = false; 1.83 + node->traverse(this); 1.84 + return mGradientOperation; 1.85 +} 1.86 + 1.87 +bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node) 1.88 +{ 1.89 + if (mGradientOperation) 1.90 + { 1.91 + return false; 1.92 + } 1.93 + 1.94 + switch (node->getOp()) 1.95 + { 1.96 + case EOpDFdx: 1.97 + case EOpDFdy: 1.98 + mGradientOperation = true; 1.99 + default: 1.100 + break; 1.101 + } 1.102 + 1.103 + return !mGradientOperation; 1.104 +} 1.105 + 1.106 +bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node) 1.107 +{ 1.108 + if (mGradientOperation) 1.109 + { 1.110 + return false; 1.111 + } 1.112 + 1.113 + if (node->getOp() == EOpFunctionCall) 1.114 + { 1.115 + if (!node->isUserDefined()) 1.116 + { 1.117 + TString name = TFunction::unmangleName(node->getName()); 1.118 + 1.119 + if (name == "texture2D" || 1.120 + name == "texture2DProj" || 1.121 + name == "textureCube") 1.122 + { 1.123 + mGradientOperation = true; 1.124 + } 1.125 + } 1.126 + else 1.127 + { 1.128 + // When a user defined function is called, we have to 1.129 + // conservatively assume it to contain gradient operations 1.130 + mGradientOperation = true; 1.131 + } 1.132 + } 1.133 + 1.134 + return !mGradientOperation; 1.135 +} 1.136 + 1.137 +bool containsGradientOperation(TIntermNode *node) 1.138 +{ 1.139 + DetectGradientOperation detectGradientOperation; 1.140 + return detectGradientOperation.traverse(node); 1.141 +} 1.142 +}