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/DetectDiscontinuity.h" 12 13 #include "compiler/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