blob: 334eb0bfa8baf5a2460a1d26f75e0c55e107806c [file] [log] [blame]
daniel@transgaming.come2095642012-05-31 01:20:20 +00001//
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
Geoff Lang17732822013-08-29 13:46:49 -040011#include "compiler/translator/DetectDiscontinuity.h"
daniel@transgaming.come2095642012-05-31 01:20:20 +000012
Jamie Madill6b9cb252013-10-17 10:45:47 -040013#include "compiler/translator/ParseContext.h"
daniel@transgaming.com79744f22012-05-31 01:20:24 +000014
daniel@transgaming.come2095642012-05-31 01:20:20 +000015namespace sh
16{
daniel@transgaming.com79744f22012-05-31 01:20:24 +000017bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
daniel@transgaming.come2095642012-05-31 01:20:20 +000018{
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +000019 mLoopDepth = 0;
daniel@transgaming.com79744f22012-05-31 01:20:24 +000020 mLoopDiscontinuity = false;
daniel@transgaming.come2095642012-05-31 01:20:20 +000021 node->traverse(this);
daniel@transgaming.com79744f22012-05-31 01:20:24 +000022 return mLoopDiscontinuity;
daniel@transgaming.come2095642012-05-31 01:20:20 +000023}
24
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +000025bool 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
daniel@transgaming.com79744f22012-05-31 01:20:24 +000039bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.come2095642012-05-31 01:20:20 +000040{
daniel@transgaming.com79744f22012-05-31 01:20:24 +000041 if (mLoopDiscontinuity)
42 {
43 return false;
44 }
45
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +000046 if (!mLoopDepth)
47 {
48 return true;
49 }
50
daniel@transgaming.come2095642012-05-31 01:20:20 +000051 switch (node->getFlowOp())
52 {
53 case EOpKill:
54 break;
55 case EOpBreak:
56 case EOpContinue:
daniel@transgaming.come2095642012-05-31 01:20:20 +000057 case EOpReturn:
shannon.woods@transgaming.come91615c2013-01-25 21:56:03 +000058 mLoopDiscontinuity = true;
daniel@transgaming.come2095642012-05-31 01:20:20 +000059 break;
60 default: UNREACHABLE();
61 }
62
daniel@transgaming.com79744f22012-05-31 01:20:24 +000063 return !mLoopDiscontinuity;
64}
65
66bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
67{
68 return !mLoopDiscontinuity;
69}
70
71bool containsLoopDiscontinuity(TIntermNode *node)
72{
73 DetectLoopDiscontinuity detectLoopDiscontinuity;
74 return detectLoopDiscontinuity.traverse(node);
75}
76
77bool DetectGradientOperation::traverse(TIntermNode *node)
78{
79 mGradientOperation = false;
80 node->traverse(this);
81 return mGradientOperation;
82}
83
84bool 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
103bool 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
134bool containsGradientOperation(TIntermNode *node)
135{
136 DetectGradientOperation detectGradientOperation;
137 return detectGradientOperation.traverse(node);
daniel@transgaming.come2095642012-05-31 01:20:20 +0000138}
139}