Hash :
80bacde5
Author :
Date :
2014-11-10T12:07:37
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>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
//
// 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);
}
}