| // |
| // Copyright 2020 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // RemoveAtomicCounterBuiltins: Remove atomic counter builtins. |
| // |
| |
| #include "compiler/translator/tree_ops/vulkan/RemoveAtomicCounterBuiltins.h" |
| |
| #include "compiler/translator/Compiler.h" |
| #include "compiler/translator/tree_util/IntermTraverse.h" |
| |
| namespace sh |
| { |
| namespace |
| { |
| |
| bool IsAtomicCounterDecl(const TIntermDeclaration *node) |
| { |
| const TIntermSequence &sequence = *(node->getSequence()); |
| TIntermTyped *variable = sequence.front()->getAsTyped(); |
| const TType &type = variable->getType(); |
| return type.getQualifier() == EvqUniform && type.isAtomicCounter(); |
| } |
| |
| // Traverser that removes all GLSL built-ins that use AtomicCounters |
| // Only called when the builtins are in use, but no atomic counters have been declared |
| class RemoveAtomicCounterBuiltinsTraverser : public TIntermTraverser |
| { |
| public: |
| RemoveAtomicCounterBuiltinsTraverser() : TIntermTraverser(true, false, false) {} |
| |
| bool visitDeclaration(Visit visit, TIntermDeclaration *node) override |
| { |
| ASSERT(visit == PreVisit); |
| |
| // Active atomic counters should have been removed by RewriteAtomicCounters, and this |
| // traversal should not have been invoked |
| ASSERT(!IsAtomicCounterDecl(node)); |
| return false; |
| } |
| |
| bool visitAggregate(Visit visit, TIntermAggregate *node) override |
| { |
| if (node->getOp() == EOpMemoryBarrierAtomicCounter) |
| { |
| // Vulkan does not support atomic counters, so if this builtin finds its way here, |
| // we need to remove it. |
| TIntermSequence emptySequence; |
| mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, |
| std::move(emptySequence)); |
| return true; |
| } |
| |
| // We shouldn't see any other builtins because they cannot be present without an active |
| // atomic counter, and should have been removed by RewriteAtomicCounters. If this fires, |
| // this traversal should not have been called. |
| ASSERT(!(node->getOp() == EOpCallBuiltInFunction && |
| node->getFunction()->isAtomicCounterFunction())); |
| |
| return false; |
| } |
| }; |
| |
| } // anonymous namespace |
| |
| bool RemoveAtomicCounterBuiltins(TCompiler *compiler, TIntermBlock *root) |
| { |
| RemoveAtomicCounterBuiltinsTraverser traverser; |
| root->traverse(&traverser); |
| return traverser.updateTree(compiler, root); |
| } |
| } // namespace sh |