AggregateAssignArraysInSSBOs.cpp (3128B)
1 // 2 // Copyright 2022 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 7 #include "compiler/translator/tree_ops/d3d/AggregateAssignArraysInSSBOs.h" 8 9 #include "compiler/translator/StaticType.h" 10 #include "compiler/translator/Symbol.h" 11 #include "compiler/translator/tree_util/IntermNode_util.h" 12 #include "compiler/translator/tree_util/IntermTraverse.h" 13 #include "compiler/translator/util.h" 14 15 namespace sh 16 { 17 18 namespace 19 { 20 21 class AggregateAssignArraysInSSBOsTraverser : public TIntermTraverser 22 { 23 public: 24 AggregateAssignArraysInSSBOsTraverser(TSymbolTable *symbolTable) 25 : TIntermTraverser(true, false, false, symbolTable) 26 {} 27 28 protected: 29 bool visitBinary(Visit visit, TIntermBinary *node) override 30 { 31 // Replace all aggregate assignments to arrays in SSBOs with element-by-element assignments. 32 // TODO(anglebug.com/7363): this implementation only works for the simple case (assignment 33 // statement), not more complex cases such as assignment-as-expression or functions with 34 // side effects in the RHS. 35 36 if (node->getOp() != EOpAssign) 37 { 38 return true; 39 } 40 else if (!node->getLeft()->getType().isArray()) 41 { 42 return true; 43 } 44 else if (!IsInShaderStorageBlock(node->getLeft())) 45 { 46 return true; 47 } 48 const TType *mediumpIndexType = StaticType::Get<EbtInt, EbpMedium, EvqTemporary, 1, 1>(); 49 auto *indexVariable = CreateTempVariable(mSymbolTable, mediumpIndexType); 50 auto *indexInit = 51 CreateTempInitDeclarationNode(indexVariable, CreateZeroNode(indexVariable->getType())); 52 auto *arraySizeNode = CreateIndexNode(node->getOutermostArraySize()); 53 auto *indexSymbolNode = CreateTempSymbolNode(indexVariable); 54 auto *cond = new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode); 55 auto *indexIncrement = 56 new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy(), nullptr); 57 auto *forLoopBody = new TIntermBlock(); 58 auto *indexedLeft = 59 new TIntermBinary(EOpIndexDirect, node->getLeft(), indexSymbolNode->deepCopy()); 60 auto *indexedRight = 61 new TIntermBinary(EOpIndexDirect, node->getRight(), indexSymbolNode->deepCopy()); 62 auto *assign = new TIntermBinary(TOperator::EOpAssign, indexedLeft, indexedRight); 63 forLoopBody->appendStatement(assign); 64 auto *forLoop = 65 new TIntermLoop(ELoopFor, indexInit, cond, indexIncrement, EnsureBlock(forLoopBody)); 66 queueReplacement(forLoop, OriginalNode::IS_DROPPED); 67 return false; 68 } 69 }; 70 71 } // namespace 72 73 bool AggregateAssignArraysInSSBOs(TCompiler *compiler, 74 TIntermBlock *root, 75 TSymbolTable *symbolTable) 76 { 77 AggregateAssignArraysInSSBOsTraverser traverser(symbolTable); 78 root->traverse(&traverser); 79 return traverser.updateTree(compiler, root); 80 } 81 82 } // namespace sh