xref: /aosp_15_r20/external/angle/src/compiler/translator/tree_ops/hlsl/AggregateAssignArraysInSSBOs.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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/hlsl/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:
AggregateAssignArraysInSSBOsTraverser(TSymbolTable * symbolTable)24     AggregateAssignArraysInSSBOsTraverser(TSymbolTable *symbolTable)
25         : TIntermTraverser(true, false, false, symbolTable)
26     {}
27 
28   protected:
visitBinary(Visit visit,TIntermBinary * node)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/42265833): this implementation only works for the simple case
33         // (assignment statement), not more complex cases such as assignment-as-expression or
34         // functions with 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 = new TIntermLoop(ELoopFor, indexInit, cond, indexIncrement, forLoopBody);
65         queueReplacement(forLoop, OriginalNode::IS_DROPPED);
66         return false;
67     }
68 };
69 
70 }  // namespace
71 
AggregateAssignArraysInSSBOs(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable)72 bool AggregateAssignArraysInSSBOs(TCompiler *compiler,
73                                   TIntermBlock *root,
74                                   TSymbolTable *symbolTable)
75 {
76     AggregateAssignArraysInSSBOsTraverser traverser(symbolTable);
77     root->traverse(&traverser);
78     return traverser.updateTree(compiler, root);
79 }
80 
81 }  // namespace sh
82