RemoveAtomicCounterBuiltins.cpp (2598B)
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 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: 32 RemoveAtomicCounterBuiltinsTraverser() : TIntermTraverser(true, false, false) {} 33 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 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, 52 std::move(emptySequence)); 53 return true; 54 } 55 56 // We shouldn't see any other builtins because they cannot be present without an active 57 // atomic counter, and should have been removed by RewriteAtomicCounters. If this fires, 58 // this traversal should not have been called. 59 ASSERT(!(BuiltInGroup::IsBuiltIn(node->getOp()) && 60 node->getFunction()->isAtomicCounterFunction())); 61 62 return false; 63 } 64 }; 65 66 } // anonymous namespace 67 68 bool RemoveAtomicCounterBuiltins(TCompiler *compiler, TIntermBlock *root) 69 { 70 RemoveAtomicCounterBuiltinsTraverser traverser; 71 root->traverse(&traverser); 72 return traverser.updateTree(compiler, root); 73 } 74 } // namespace sh