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