• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 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 // ProgramLinkedResources.h: implements link-time checks for default block uniforms, and generates
8 // uniform locations. Populates data structures related to uniforms so that they can be stored in
9 // program state.
10 
11 #ifndef LIBANGLE_UNIFORMLINKER_H_
12 #define LIBANGLE_UNIFORMLINKER_H_
13 
14 #include "angle_gl.h"
15 #include "common/PackedEnums.h"
16 #include "common/angleutils.h"
17 #include "libANGLE/VaryingPacking.h"
18 
19 #include <functional>
20 
21 namespace sh
22 {
23 class BlockLayoutEncoder;
24 struct BlockMemberInfo;
25 struct InterfaceBlock;
26 struct ShaderVariable;
27 class BlockEncoderVisitor;
28 class ShaderVariableVisitor;
29 struct ShaderVariable;
30 }  // namespace sh
31 
32 namespace gl
33 {
34 struct BufferVariable;
35 struct Caps;
36 class Context;
37 class InfoLog;
38 struct InterfaceBlock;
39 enum class LinkMismatchError;
40 struct LinkedUniform;
41 class ProgramState;
42 class ProgramBindings;
43 class ProgramAliasedBindings;
44 class Shader;
45 struct ShaderVariableBuffer;
46 struct UnusedUniform;
47 struct VariableLocation;
48 
49 using AtomicCounterBuffer = ShaderVariableBuffer;
50 
51 class UniformLinker final : angle::NonCopyable
52 {
53   public:
54     UniformLinker(const ProgramState &state);
55     ~UniformLinker();
56 
57     bool link(const Caps &caps,
58               InfoLog &infoLog,
59               const ProgramAliasedBindings &uniformLocationBindings);
60 
61     void getResults(std::vector<LinkedUniform> *uniforms,
62                     std::vector<UnusedUniform> *unusedUniforms,
63                     std::vector<VariableLocation> *uniformLocations);
64 
65   private:
66     bool validateGraphicsUniforms(InfoLog &infoLog) const;
67 
68     bool flattenUniformsAndCheckCapsForShader(Shader *shader,
69                                               const Caps &caps,
70                                               std::vector<LinkedUniform> &samplerUniforms,
71                                               std::vector<LinkedUniform> &imageUniforms,
72                                               std::vector<LinkedUniform> &atomicCounterUniforms,
73                                               std::vector<UnusedUniform> &unusedUniforms,
74                                               InfoLog &infoLog);
75 
76     bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
77     bool checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog);
78 
79     bool indexUniforms(InfoLog &infoLog, const ProgramAliasedBindings &uniformLocationBindings);
80     bool gatherUniformLocationsAndCheckConflicts(
81         InfoLog &infoLog,
82         const ProgramAliasedBindings &uniformLocationBindings,
83         std::set<GLuint> *ignoredLocations,
84         int *maxUniformLocation);
85     void pruneUnusedUniforms();
86 
87     const ProgramState &mState;
88     std::vector<LinkedUniform> mUniforms;
89     std::vector<UnusedUniform> mUnusedUniforms;
90     std::vector<VariableLocation> mUniformLocations;
91 };
92 
93 using GetBlockSizeFunc = std::function<
94     bool(const std::string &blockName, const std::string &blockMappedName, size_t *sizeOut)>;
95 using GetBlockMemberInfoFunc = std::function<
96     bool(const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut)>;
97 
98 // This class is intended to be used during the link step to store interface block information.
99 // It is called by the Impl class during ProgramImpl::link so that it has access to the
100 // real block size and layout.
101 class InterfaceBlockLinker : angle::NonCopyable
102 {
103   public:
104     virtual ~InterfaceBlockLinker();
105 
106     // This is called once per shader stage. It stores a pointer to the block vector, so it's
107     // important that this class does not persist longer than the duration of Program::link.
108     void addShaderBlocks(ShaderType shader, const std::vector<sh::InterfaceBlock> *blocks);
109 
110     // This is called once during a link operation, after all shader blocks are added.
111     void linkBlocks(const GetBlockSizeFunc &getBlockSize,
112                     const GetBlockMemberInfoFunc &getMemberInfo) const;
113 
114   protected:
115     InterfaceBlockLinker(std::vector<InterfaceBlock> *blocksOut,
116                          std::vector<std::string> *unusedInterfaceBlocksOut);
117     void defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize,
118                               const GetBlockMemberInfoFunc &getMemberInfo,
119                               const sh::InterfaceBlock &interfaceBlock,
120                               ShaderType shaderType) const;
121 
122     virtual size_t getCurrentBlockMemberIndex() const = 0;
123 
124     ShaderMap<const std::vector<sh::InterfaceBlock> *> mShaderBlocks;
125 
126     std::vector<InterfaceBlock> *mBlocksOut;
127     std::vector<std::string> *mUnusedInterfaceBlocksOut;
128 
129     virtual sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
130                                                   const std::string &namePrefix,
131                                                   const std::string &mappedNamePrefix,
132                                                   ShaderType shaderType,
133                                                   int blockIndex) const = 0;
134 };
135 
136 class UniformBlockLinker final : public InterfaceBlockLinker
137 {
138   public:
139     UniformBlockLinker(std::vector<InterfaceBlock> *blocksOut,
140                        std::vector<LinkedUniform> *uniformsOut,
141                        std::vector<std::string> *unusedInterfaceBlocksOut);
142     ~UniformBlockLinker() override;
143 
144   private:
145     size_t getCurrentBlockMemberIndex() const override;
146 
147     sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
148                                           const std::string &namePrefix,
149                                           const std::string &mappedNamePrefix,
150                                           ShaderType shaderType,
151                                           int blockIndex) const override;
152 
153     std::vector<LinkedUniform> *mUniformsOut;
154 };
155 
156 class ShaderStorageBlockLinker final : public InterfaceBlockLinker
157 {
158   public:
159     ShaderStorageBlockLinker(std::vector<InterfaceBlock> *blocksOut,
160                              std::vector<BufferVariable> *bufferVariablesOut,
161                              std::vector<std::string> *unusedInterfaceBlocksOut);
162     ~ShaderStorageBlockLinker() override;
163 
164   private:
165     size_t getCurrentBlockMemberIndex() const override;
166 
167     sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
168                                           const std::string &namePrefix,
169                                           const std::string &mappedNamePrefix,
170                                           ShaderType shaderType,
171                                           int blockIndex) const override;
172 
173     std::vector<BufferVariable> *mBufferVariablesOut;
174 };
175 
176 class AtomicCounterBufferLinker final : angle::NonCopyable
177 {
178   public:
179     AtomicCounterBufferLinker(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
180     ~AtomicCounterBufferLinker();
181 
182     void link(const std::map<int, unsigned int> &sizeMap) const;
183 
184   private:
185     std::vector<AtomicCounterBuffer> *mAtomicCounterBuffersOut;
186 };
187 
188 // The link operation is responsible for finishing the link of uniform and interface blocks.
189 // This way it can filter out unreferenced resources and still have access to the info.
190 // TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks.
191 struct UnusedUniform
192 {
UnusedUniformUnusedUniform193     UnusedUniform(std::string name, bool isSampler, bool isImage, bool isAtomicCounter)
194     {
195         this->name            = name;
196         this->isSampler       = isSampler;
197         this->isImage         = isImage;
198         this->isAtomicCounter = isAtomicCounter;
199     }
200 
201     std::string name;
202     bool isSampler;
203     bool isImage;
204     bool isAtomicCounter;
205 };
206 
207 struct ProgramLinkedResources
208 {
209     ProgramLinkedResources(GLuint maxVaryingVectors,
210                            PackMode packMode,
211                            std::vector<InterfaceBlock> *uniformBlocksOut,
212                            std::vector<LinkedUniform> *uniformsOut,
213                            std::vector<InterfaceBlock> *shaderStorageBlocksOut,
214                            std::vector<BufferVariable> *bufferVariablesOut,
215                            std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
216     ~ProgramLinkedResources();
217 
218     VaryingPacking varyingPacking;
219     UniformBlockLinker uniformBlockLinker;
220     ShaderStorageBlockLinker shaderStorageBlockLinker;
221     AtomicCounterBufferLinker atomicCounterBufferLinker;
222     std::vector<UnusedUniform> unusedUniforms;
223     std::vector<std::string> unusedInterfaceBlocks;
224 };
225 
226 class CustomBlockLayoutEncoderFactory : angle::NonCopyable
227 {
228   public:
~CustomBlockLayoutEncoderFactory()229     virtual ~CustomBlockLayoutEncoderFactory() {}
230 
231     virtual sh::BlockLayoutEncoder *makeEncoder() = 0;
232 };
233 
234 // Used by the backends in Program*::linkResources to parse interface blocks and provide
235 // information to ProgramLinkedResources' linkers.
236 class ProgramLinkedResourcesLinker final : angle::NonCopyable
237 {
238   public:
ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory * customEncoderFactory)239     ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory *customEncoderFactory)
240         : mCustomEncoderFactory(customEncoderFactory)
241     {}
242 
243     void linkResources(const ProgramState &programState,
244                        const ProgramLinkedResources &resources) const;
245 
246   private:
247     void getAtomicCounterBufferSizeMap(const ProgramState &programState,
248                                        std::map<int, unsigned int> &sizeMapOut) const;
249 
250     CustomBlockLayoutEncoderFactory *mCustomEncoderFactory;
251 };
252 
253 }  // namespace gl
254 
255 #endif  // LIBANGLE_UNIFORMLINKER_H_
256