• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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 
AggregateAssignArraysInSSBOs(TCompiler * compiler,TIntermBlock * root,TSymbolTable * symbolTable)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
83