1 //
2 // Copyright 2013 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 // FlagStd140Structs.cpp: Find structs in std140 blocks, where the padding added in the translator
7 // conflicts with the "natural" unpadded type.
8 
9 #include "compiler/translator/FlagStd140Structs.h"
10 
11 #include "compiler/translator/SymbolTable.h"
12 #include "compiler/translator/tree_util/IntermTraverse.h"
13 
14 namespace sh
15 {
16 
17 namespace
18 {
19 
20 class FlagStd140StructsTraverser : public TIntermTraverser
21 {
22   public:
FlagStd140StructsTraverser()23     FlagStd140StructsTraverser() : TIntermTraverser(true, false, false) {}
24 
getMappedStructs() const25     const std::vector<MappedStruct> getMappedStructs() const { return mMappedStructs; }
26 
27   protected:
28     bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
29 
30   private:
31     void mapBlockStructMembers(TIntermSymbol *blockDeclarator, const TInterfaceBlock *block);
32 
33     std::vector<MappedStruct> mMappedStructs;
34 };
35 
mapBlockStructMembers(TIntermSymbol * blockDeclarator,const TInterfaceBlock * block)36 void FlagStd140StructsTraverser::mapBlockStructMembers(TIntermSymbol *blockDeclarator,
37                                                        const TInterfaceBlock *block)
38 {
39     for (auto *field : block->fields())
40     {
41         if (field->type()->getBasicType() == EbtStruct)
42         {
43             MappedStruct mappedStruct;
44             mappedStruct.blockDeclarator = blockDeclarator;
45             mappedStruct.field           = field;
46             mMappedStructs.push_back(mappedStruct);
47         }
48     }
49 }
50 
visitDeclaration(Visit visit,TIntermDeclaration * node)51 bool FlagStd140StructsTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
52 {
53     TIntermTyped *declarator = node->getSequence()->back()->getAsTyped();
54     if (declarator->getBasicType() == EbtInterfaceBlock)
55     {
56         const TInterfaceBlock *block = declarator->getType().getInterfaceBlock();
57         if (block->blockStorage() == EbsStd140)
58         {
59             mapBlockStructMembers(declarator->getAsSymbolNode(), block);
60         }
61     }
62     return false;
63 }
64 
65 }  // anonymous namespace
66 
FlagStd140Structs(TIntermNode * node)67 std::vector<MappedStruct> FlagStd140Structs(TIntermNode *node)
68 {
69     FlagStd140StructsTraverser flaggingTraversal;
70 
71     node->traverse(&flaggingTraversal);
72 
73     return flaggingTraversal.getMappedStructs();
74 }
75 
76 }  // namespace sh
77