1 //
2 // Copyright 2020 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 // CheckEarlyFragmentTestOptimization is an AST traverser to check if early fragment
7 // test as an optimization is feasible.
8 //
9
10 #include "compiler/translator/tree_ops/vulkan/EarlyFragmentTestsOptimization.h"
11
12 #include "compiler/translator/InfoSink.h"
13 #include "compiler/translator/Symbol.h"
14 #include "compiler/translator/tree_util/IntermNode_util.h"
15 #include "compiler/translator/tree_util/IntermTraverse.h"
16
17 namespace sh
18 {
19
20 namespace
21 {
22
23 // Traverser that check conditions that would prevent early fragment tests optmization.
24 class CheckEFTOptimizationTraverser : public TIntermTraverser
25 {
26 public:
27 CheckEFTOptimizationTraverser();
28
29 void visitSymbol(TIntermSymbol *node) override;
30 bool visitBranch(Visit visit, TIntermBranch *node) override;
31
isFragDepthUsed()32 bool isFragDepthUsed() { return mFragDepthUsed; }
isDiscardOpUsed()33 bool isDiscardOpUsed() { return mDiscardOpUsed; }
34
35 protected:
36 bool mFragDepthUsed;
37 bool mDiscardOpUsed;
38 };
39
CheckEFTOptimizationTraverser()40 CheckEFTOptimizationTraverser::CheckEFTOptimizationTraverser()
41 : TIntermTraverser(true, false, false), mFragDepthUsed(false), mDiscardOpUsed(false)
42 {}
43
visitSymbol(TIntermSymbol * node)44 void CheckEFTOptimizationTraverser::visitSymbol(TIntermSymbol *node)
45 {
46 // Check the qualifier from the variable, not from the symbol node. The node may have a
47 // different qualifier if it's the result of a folded ternary node.
48 TQualifier qualifier = node->variable().getType().getQualifier();
49
50 if (qualifier == EvqFragDepth)
51 {
52 mFragDepthUsed = true;
53 }
54 }
55
visitBranch(Visit visit,TIntermBranch * node)56 bool CheckEFTOptimizationTraverser::visitBranch(Visit visit, TIntermBranch *node)
57 {
58 if (node->getFlowOp() == EOpKill)
59 {
60 mDiscardOpUsed = true;
61 }
62 return true;
63 }
64
65 } // namespace
66
CheckEarlyFragmentTestsFeasible(TCompiler * compiler,TIntermNode * root)67 bool CheckEarlyFragmentTestsFeasible(TCompiler *compiler, TIntermNode *root)
68 {
69 CheckEFTOptimizationTraverser traverser;
70 root->traverse(&traverser);
71
72 if (traverser.isFragDepthUsed() || traverser.isDiscardOpUsed())
73 {
74 return false;
75 }
76 return true;
77 }
78
79 } // namespace sh
80