summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp')
-rw-r--r--gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp127
1 files changed, 127 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp
new file mode 100644
index 0000000000..a23d0770ef
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/NameNamelessUniformBuffers.cpp
@@ -0,0 +1,127 @@
+//
+// Copyright 2019 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.
+//
+// NameNamelessUniformBuffers: Gives nameless uniform buffer variables internal names.
+//
+
+#include "compiler/translator/tree_ops/NameNamelessUniformBuffers.h"
+
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermNode_util.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
+
+namespace sh
+{
+namespace
+{
+// Traverse uniform buffer declarations and give name to nameless declarations. Keeps track of
+// the interface fields which will be used in the source without the interface block variable name
+// and replaces them with name.field.
+class NameUniformBufferVariablesTraverser : public TIntermTraverser
+{
+ public:
+ explicit NameUniformBufferVariablesTraverser(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, false, symbolTable)
+ {}
+
+ bool visitDeclaration(Visit visit, TIntermDeclaration *decl) override
+ {
+ ASSERT(visit == PreVisit);
+
+ const TIntermSequence &sequence = *(decl->getSequence());
+
+ TIntermTyped *variableNode = sequence.front()->getAsTyped();
+ const TType &type = variableNode->getType();
+
+ // If it's an interface block, it may have to be converted if it contains any row-major
+ // fields.
+ if (!type.isInterfaceBlock())
+ {
+ return true;
+ }
+
+ // Multi declaration statements are already separated, so there can only be one variable
+ // here.
+ ASSERT(sequence.size() == 1);
+ const TVariable *variable = &variableNode->getAsSymbolNode()->variable();
+ if (variable->symbolType() != SymbolType::Empty)
+ {
+ return false;
+ }
+
+ TIntermDeclaration *newDeclaration = new TIntermDeclaration;
+ TVariable *newVariable = new TVariable(mSymbolTable, kEmptyImmutableString, &type,
+ SymbolType::AngleInternal, variable->extensions());
+ newDeclaration->appendDeclarator(new TIntermSymbol(newVariable));
+
+ queueReplacement(newDeclaration, OriginalNode::IS_DROPPED);
+
+ // It's safe to key the map with the interface block, as there couldn't have been multiple
+ // declarations with this interface block (as the variable is nameless), so for nameless
+ // uniform buffers, the interface block is unique.
+ mNamelessUniformBuffersMap[type.getInterfaceBlock()] = newVariable;
+
+ return false;
+ }
+
+ void visitSymbol(TIntermSymbol *symbol) override
+ {
+ const TType &type = symbol->getType();
+
+ // The symbols we are looking for have the interface block pointer set, but are not
+ // interface blocks. These are references to fields of nameless uniform buffers.
+ if (type.isInterfaceBlock() || type.getInterfaceBlock() == nullptr)
+ {
+ return;
+ }
+
+ const TInterfaceBlock *block = type.getInterfaceBlock();
+
+ // If block variable is not nameless, there's nothing to do.
+ if (mNamelessUniformBuffersMap.count(block) == 0)
+ {
+ return;
+ }
+
+ const ImmutableString symbolName = symbol->getName();
+
+ // Find which field it is
+ const TVector<TField *> fields = block->fields();
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); ++fieldIndex)
+ {
+ const TField *field = fields[fieldIndex];
+ if (field->name() != symbolName)
+ {
+ continue;
+ }
+
+ // Replace this node with a binary node that indexes the named uniform buffer.
+ TIntermSymbol *namedUniformBuffer =
+ new TIntermSymbol(mNamelessUniformBuffersMap[block]);
+ TIntermBinary *replacement =
+ new TIntermBinary(EOpIndexDirectInterfaceBlock, namedUniformBuffer,
+ CreateIndexNode(static_cast<uint32_t>(fieldIndex)));
+
+ queueReplacement(replacement, OriginalNode::IS_DROPPED);
+
+ return;
+ }
+
+ UNREACHABLE();
+ }
+
+ private:
+ // A map from nameless uniform buffers to their named replacements.
+ std::unordered_map<const TInterfaceBlock *, const TVariable *> mNamelessUniformBuffersMap;
+};
+} // anonymous namespace
+
+bool NameNamelessUniformBuffers(TCompiler *compiler, TIntermBlock *root, TSymbolTable *symbolTable)
+{
+ NameUniformBufferVariablesTraverser nameUniformBufferVariables(symbolTable);
+ root->traverse(&nameUniformBufferVariables);
+ return nameUniformBufferVariables.updateTree(compiler, root);
+}
+} // namespace sh