blob: 472232a75d2567171bfb4f708bb28960ae5ab181 [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
11#include "compiler/DetectDiscontinuity.h"
12
daniel@transgaming.com79744f22012-05-31 01:20:24 +000013#include "compiler/ParseHelper.h"
14
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{
daniel@transgaming.com79744f22012-05-31 01:20:24 +000019 mLoopDiscontinuity = false;
daniel@transgaming.come2095642012-05-31 01:20:20 +000020 node->traverse(this);
daniel@transgaming.com79744f22012-05-31 01:20:24 +000021 return mLoopDiscontinuity;
daniel@transgaming.come2095642012-05-31 01:20:20 +000022}
23
daniel@transgaming.com79744f22012-05-31 01:20:24 +000024bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.come2095642012-05-31 01:20:20 +000025{
daniel@transgaming.com79744f22012-05-31 01:20:24 +000026 if (mLoopDiscontinuity)
27 {
28 return false;
29 }
30
daniel@transgaming.come2095642012-05-31 01:20:20 +000031 switch (node->getFlowOp())
32 {
33 case EOpKill:
34 break;
35 case EOpBreak:
36 case EOpContinue:
daniel@transgaming.com79744f22012-05-31 01:20:24 +000037 mLoopDiscontinuity = true;
daniel@transgaming.come2095642012-05-31 01:20:20 +000038 case EOpReturn:
39 break;
40 default: UNREACHABLE();
41 }
42
daniel@transgaming.com79744f22012-05-31 01:20:24 +000043 return !mLoopDiscontinuity;
44}
45
46bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
47{
48 return !mLoopDiscontinuity;
49}
50
51bool containsLoopDiscontinuity(TIntermNode *node)
52{
53 DetectLoopDiscontinuity detectLoopDiscontinuity;
54 return detectLoopDiscontinuity.traverse(node);
55}
56
57bool DetectGradientOperation::traverse(TIntermNode *node)
58{
59 mGradientOperation = false;
60 node->traverse(this);
61 return mGradientOperation;
62}
63
64bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
65{
66 if (mGradientOperation)
67 {
68 return false;
69 }
70
71 switch (node->getOp())
72 {
73 case EOpDFdx:
74 case EOpDFdy:
75 mGradientOperation = true;
76 default:
77 break;
78 }
79
80 return !mGradientOperation;
81}
82
83bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
84{
85 if (mGradientOperation)
86 {
87 return false;
88 }
89
90 if (node->getOp() == EOpFunctionCall)
91 {
92 if (!node->isUserDefined())
93 {
94 TString name = TFunction::unmangleName(node->getName());
95
96 if (name == "texture2D" ||
97 name == "texture2DProj" ||
98 name == "textureCube")
99 {
100 mGradientOperation = true;
101 }
102 }
103 else
104 {
105 // When a user defined function is called, we have to
106 // conservatively assume it to contain gradient operations
107 mGradientOperation = true;
108 }
109 }
110
111 return !mGradientOperation;
112}
113
114bool containsGradientOperation(TIntermNode *node)
115{
116 DetectGradientOperation detectGradientOperation;
117 return detectGradientOperation.traverse(node);
daniel@transgaming.come2095642012-05-31 01:20:20 +0000118}
119}