• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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