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