• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 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 // RemoveInactiveInterfaceVariables.h:
7 //  Drop shader interface variable declarations for those that are inactive.
8 //
9 
10 #include "compiler/translator/tree_ops/RemoveInactiveInterfaceVariables.h"
11 
12 #include "compiler/translator/SymbolTable.h"
13 #include "compiler/translator/tree_util/IntermTraverse.h"
14 #include "compiler/translator/util.h"
15 
16 namespace sh
17 {
18 
19 namespace
20 {
21 
22 // Traverser that removes all declarations that correspond to inactive variables.
23 class RemoveInactiveInterfaceVariablesTraverser : public TIntermTraverser
24 {
25   public:
26     RemoveInactiveInterfaceVariablesTraverser(
27         const std::vector<sh::ShaderVariable> &attributes,
28         const std::vector<sh::ShaderVariable> &inputVaryings,
29         const std::vector<sh::ShaderVariable> &outputVariables,
30         const std::vector<sh::ShaderVariable> &uniforms,
31         const std::vector<sh::InterfaceBlock> &interfaceBlocks);
32 
33     bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
34 
35   private:
36     const std::vector<sh::ShaderVariable> &mAttributes;
37     const std::vector<sh::ShaderVariable> &mInputVaryings;
38     const std::vector<sh::ShaderVariable> &mOutputVariables;
39     const std::vector<sh::ShaderVariable> &mUniforms;
40     const std::vector<sh::InterfaceBlock> &mInterfaceBlocks;
41 };
42 
RemoveInactiveInterfaceVariablesTraverser(const std::vector<sh::ShaderVariable> & attributes,const std::vector<sh::ShaderVariable> & inputVaryings,const std::vector<sh::ShaderVariable> & outputVariables,const std::vector<sh::ShaderVariable> & uniforms,const std::vector<sh::InterfaceBlock> & interfaceBlocks)43 RemoveInactiveInterfaceVariablesTraverser::RemoveInactiveInterfaceVariablesTraverser(
44     const std::vector<sh::ShaderVariable> &attributes,
45     const std::vector<sh::ShaderVariable> &inputVaryings,
46     const std::vector<sh::ShaderVariable> &outputVariables,
47     const std::vector<sh::ShaderVariable> &uniforms,
48     const std::vector<sh::InterfaceBlock> &interfaceBlocks)
49     : TIntermTraverser(true, false, false),
50       mAttributes(attributes),
51       mInputVaryings(inputVaryings),
52       mOutputVariables(outputVariables),
53       mUniforms(uniforms),
54       mInterfaceBlocks(interfaceBlocks)
55 {}
56 
57 template <typename Variable>
IsVariableActive(const std::vector<Variable> & mVars,const ImmutableString & name)58 bool IsVariableActive(const std::vector<Variable> &mVars, const ImmutableString &name)
59 {
60     for (const Variable &var : mVars)
61     {
62         if (name == var.name)
63         {
64             return var.active;
65         }
66     }
67     UNREACHABLE();
68     return true;
69 }
70 
visitDeclaration(Visit visit,TIntermDeclaration * node)71 bool RemoveInactiveInterfaceVariablesTraverser::visitDeclaration(Visit visit,
72                                                                  TIntermDeclaration *node)
73 {
74     // SeparateDeclarations should have already been run.
75     ASSERT(node->getSequence()->size() == 1u);
76 
77     TIntermTyped *declarator = node->getSequence()->front()->getAsTyped();
78     ASSERT(declarator);
79 
80     TIntermSymbol *asSymbol = declarator->getAsSymbolNode();
81     if (!asSymbol)
82     {
83         return false;
84     }
85 
86     const TType &type = declarator->getType();
87 
88     // Remove all shader interface variables except outputs, i.e. uniforms, interface blocks and
89     // inputs.
90     //
91     // Imagine a situation where the VS doesn't write to a varying but the FS reads from it.  This
92     // is allowed, though the value of the varying is undefined.  If the varying is removed here,
93     // the situation is changed to VS not declaring the varying, but the FS reading from it, which
94     // is not allowed.  That's why inactive shader outputs are not removed.
95     //
96     // Inactive fragment shader outputs can be removed though, as there is no next stage.
97     bool removeDeclaration     = false;
98     const TQualifier qualifier = type.getQualifier();
99 
100     if (type.isInterfaceBlock())
101     {
102         removeDeclaration = !IsVariableActive(mInterfaceBlocks, type.getInterfaceBlock()->name());
103     }
104     else if (qualifier == EvqUniform)
105     {
106         removeDeclaration = !IsVariableActive(mUniforms, asSymbol->getName());
107     }
108     else if (qualifier == EvqAttribute || qualifier == EvqVertexIn)
109     {
110         removeDeclaration = !IsVariableActive(mAttributes, asSymbol->getName());
111     }
112     else if (IsShaderIn(qualifier))
113     {
114         removeDeclaration = !IsVariableActive(mInputVaryings, asSymbol->getName());
115     }
116     else if (qualifier == EvqFragmentOut)
117     {
118         removeDeclaration = !IsVariableActive(mOutputVariables, asSymbol->getName());
119     }
120 
121     if (removeDeclaration)
122     {
123         TIntermSequence emptySequence;
124         mMultiReplacements.emplace_back(getParentNode()->getAsBlock(), node, emptySequence);
125     }
126 
127     return false;
128 }
129 
130 }  // namespace
131 
RemoveInactiveInterfaceVariables(TCompiler * compiler,TIntermBlock * root,const std::vector<sh::ShaderVariable> & attributes,const std::vector<sh::ShaderVariable> & inputVaryings,const std::vector<sh::ShaderVariable> & outputVariables,const std::vector<sh::ShaderVariable> & uniforms,const std::vector<sh::InterfaceBlock> & interfaceBlocks)132 bool RemoveInactiveInterfaceVariables(TCompiler *compiler,
133                                       TIntermBlock *root,
134                                       const std::vector<sh::ShaderVariable> &attributes,
135                                       const std::vector<sh::ShaderVariable> &inputVaryings,
136                                       const std::vector<sh::ShaderVariable> &outputVariables,
137                                       const std::vector<sh::ShaderVariable> &uniforms,
138                                       const std::vector<sh::InterfaceBlock> &interfaceBlocks)
139 {
140     RemoveInactiveInterfaceVariablesTraverser traverser(attributes, inputVaryings, outputVariables,
141                                                         uniforms, interfaceBlocks);
142     root->traverse(&traverser);
143     return traverser.updateTree(compiler, root);
144 }
145 
146 }  // namespace sh
147