• 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 // RemoveAtomicCounterBuiltins: Remove atomic counter builtins.
7 //
8 
9 #include "compiler/translator/tree_ops/RemoveAtomicCounterBuiltins.h"
10 
11 #include "compiler/translator/Compiler.h"
12 #include "compiler/translator/tree_util/IntermTraverse.h"
13 
14 namespace sh
15 {
16 namespace
17 {
18 
IsAtomicCounterDecl(const TIntermDeclaration * node)19 bool IsAtomicCounterDecl(const TIntermDeclaration *node)
20 {
21     const TIntermSequence &sequence = *(node->getSequence());
22     TIntermTyped *variable          = sequence.front()->getAsTyped();
23     const TType &type               = variable->getType();
24     return type.getQualifier() == EvqUniform && type.isAtomicCounter();
25 }
26 
27 // Traverser that removes all GLSL built-ins that use AtomicCounters
28 // Only called when the builtins are in use, but no atomic counters have been declared
29 class RemoveAtomicCounterBuiltinsTraverser : public TIntermTraverser
30 {
31   public:
RemoveAtomicCounterBuiltinsTraverser()32     RemoveAtomicCounterBuiltinsTraverser() : TIntermTraverser(true, false, false) {}
33 
visitDeclaration(Visit visit,TIntermDeclaration * node)34     bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
35     {
36         ASSERT(visit == PreVisit);
37 
38         // Active atomic counters should have been removed by RewriteAtomicCounters, and this
39         // traversal should not have been invoked
40         ASSERT(!IsAtomicCounterDecl(node));
41         return false;
42     }
43 
visitAggregate(Visit visit,TIntermAggregate * node)44     bool visitAggregate(Visit visit, TIntermAggregate *node) override
45     {
46         if (node->getOp() == EOpMemoryBarrierAtomicCounter)
47         {
48             // Vulkan does not support atomic counters, so if this builtin finds its way here,
49             // we need to remove it.
50             TIntermSequence emptySequence;
51             mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, emptySequence);
52             return true;
53         }
54 
55         // We shouldn't see any other builtins because they cannot be present without an active
56         // atomic counter, and should have been removed by RewriteAtomicCounters. If this fires,
57         // this traversal should not have been called.
58         ASSERT(!(node->getOp() == EOpCallBuiltInFunction &&
59                  node->getFunction()->isAtomicCounterFunction()));
60 
61         return false;
62     }
63 };
64 
65 }  // anonymous namespace
66 
RemoveAtomicCounterBuiltins(TCompiler * compiler,TIntermBlock * root)67 bool RemoveAtomicCounterBuiltins(TCompiler *compiler, TIntermBlock *root)
68 {
69     RemoveAtomicCounterBuiltinsTraverser traverser;
70     root->traverse(&traverser);
71     return traverser.updateTree(compiler, root);
72 }
73 }  // namespace sh
74