summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp')
-rw-r--r--gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp
new file mode 100644
index 0000000000..4293f4c4da
--- /dev/null
+++ b/gfx/angle/checkout/src/compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.cpp
@@ -0,0 +1,76 @@
+//
+// Copyright 2022 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.
+//
+
+#include "compiler/translator/tree_ops/d3d/AggregateAssignStructsInSSBOs.h"
+
+#include "compiler/translator/StaticType.h"
+#include "compiler/translator/Symbol.h"
+#include "compiler/translator/tree_util/IntermNode_util.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
+#include "compiler/translator/util.h"
+
+namespace sh
+{
+
+namespace
+{
+
+class AggregateAssignStructsInSSBOsTraverser : public TIntermTraverser
+{
+ public:
+ AggregateAssignStructsInSSBOsTraverser(TSymbolTable *symbolTable)
+ : TIntermTraverser(true, false, false, symbolTable)
+ {}
+
+ protected:
+ bool visitBinary(Visit visit, TIntermBinary *node) override
+ {
+ // Replace all assignments to structs in SSBOs with field-by-field asignments.
+ // TODO(anglebug.com/7362): this implementation only works for the simple case (assignment
+ // statement), not more complex cases such as assignment-as-expression or functions with
+ // side effects in the RHS.
+ const TStructure *s;
+ if (node->getOp() != EOpAssign)
+ {
+ return true;
+ }
+ else if (!IsInShaderStorageBlock(node->getLeft()))
+ {
+ return true;
+ }
+ else if (!(s = node->getLeft()->getType().getStruct()))
+ {
+ return true;
+ }
+ ASSERT(node->getRight()->getType().getStruct() == s);
+ auto *block = new TIntermBlock();
+ for (int i = 0; i < static_cast<int>(s->fields().size()); ++i)
+ {
+ auto *left = new TIntermBinary(EOpIndexDirectStruct, node->getLeft()->deepCopy(),
+ CreateIndexNode(i));
+ auto *right = new TIntermBinary(EOpIndexDirectStruct, node->getRight()->deepCopy(),
+ CreateIndexNode(i));
+ auto *assign = new TIntermBinary(TOperator::EOpAssign, left, right);
+ block->appendStatement(assign);
+ }
+
+ queueReplacement(block, OriginalNode::IS_DROPPED);
+ return false;
+ }
+};
+
+} // namespace
+
+bool AggregateAssignStructsInSSBOs(TCompiler *compiler,
+ TIntermBlock *root,
+ TSymbolTable *symbolTable)
+{
+ AggregateAssignStructsInSSBOsTraverser traverser(symbolTable);
+ root->traverse(&traverser);
+ return traverser.updateTree(compiler, root);
+}
+
+} // namespace sh