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