• 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 ProgramPipelineState;
43 class ProgramBindings;
44 class ProgramAliasedBindings;
45 class Shader;
46 struct ShaderVariableBuffer;
47 struct UnusedUniform;
48 struct VariableLocation;
49 
50 using AtomicCounterBuffer = ShaderVariableBuffer;
51 using ShaderUniform       = std::pair<ShaderType, const sh::ShaderVariable *>;
52 
53 class UniformLinker final : angle::NonCopyable
54 {
55   public:
56     UniformLinker(const ShaderBitSet &activeShaderStages,
57                   const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms);
58     ~UniformLinker();
59 
60     bool link(const Caps &caps,
61               InfoLog &infoLog,
62               const ProgramAliasedBindings &uniformLocationBindings);
63 
64     void getResults(std::vector<LinkedUniform> *uniforms,
65                     std::vector<UnusedUniform> *unusedUniformsOutOrNull,
66                     std::vector<VariableLocation> *uniformLocationsOutOrNull);
67 
68   private:
69     bool validateGraphicsUniforms(InfoLog &infoLog) const;
70     bool validateGraphicsUniformsPerShader(ShaderType shaderToLink,
71                                            bool extendLinkedUniforms,
72                                            std::map<std::string, ShaderUniform> *linkedUniforms,
73                                            InfoLog &infoLog) const;
74     bool flattenUniformsAndCheckCapsForShader(ShaderType shaderType,
75                                               const Caps &caps,
76                                               std::vector<LinkedUniform> &samplerUniforms,
77                                               std::vector<LinkedUniform> &imageUniforms,
78                                               std::vector<LinkedUniform> &atomicCounterUniforms,
79                                               std::vector<LinkedUniform> &inputAttachmentUniforms,
80                                               std::vector<UnusedUniform> &unusedUniforms,
81                                               InfoLog &infoLog);
82 
83     bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
84     bool checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog);
85 
86     bool indexUniforms(InfoLog &infoLog, const ProgramAliasedBindings &uniformLocationBindings);
87     bool gatherUniformLocationsAndCheckConflicts(
88         InfoLog &infoLog,
89         const ProgramAliasedBindings &uniformLocationBindings,
90         std::set<GLuint> *ignoredLocations,
91         int *maxUniformLocation);
92     void pruneUnusedUniforms();
93 
94     ShaderBitSet mActiveShaderStages;
95     const ShaderMap<std::vector<sh::ShaderVariable>> &mShaderUniforms;
96     std::vector<LinkedUniform> mUniforms;
97     std::vector<UnusedUniform> mUnusedUniforms;
98     std::vector<VariableLocation> mUniformLocations;
99 };
100 
101 using GetBlockSizeFunc = std::function<
102     bool(const std::string &blockName, const std::string &blockMappedName, size_t *sizeOut)>;
103 using GetBlockMemberInfoFunc = std::function<
104     bool(const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut)>;
105 
106 // This class is intended to be used during the link step to store interface block information.
107 // It is called by the Impl class during ProgramImpl::link so that it has access to the
108 // real block size and layout.
109 class InterfaceBlockLinker : angle::NonCopyable
110 {
111   public:
112     virtual ~InterfaceBlockLinker();
113 
114     // This is called once per shader stage. It stores a pointer to the block vector, so it's
115     // important that this class does not persist longer than the duration of Program::link.
116     void addShaderBlocks(ShaderType shader, const std::vector<sh::InterfaceBlock> *blocks);
117 
118     // This is called once during a link operation, after all shader blocks are added.
119     void linkBlocks(const GetBlockSizeFunc &getBlockSize,
120                     const GetBlockMemberInfoFunc &getMemberInfo) const;
121 
getShaderBlocks(ShaderType shaderType)122     const std::vector<sh::InterfaceBlock> &getShaderBlocks(ShaderType shaderType) const
123     {
124         ASSERT(mShaderBlocks[shaderType]);
125         return *mShaderBlocks[shaderType];
126     }
127 
128   protected:
129     InterfaceBlockLinker();
130     void init(std::vector<InterfaceBlock> *blocksOut,
131               std::vector<std::string> *unusedInterfaceBlocksOut);
132     void defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize,
133                               const GetBlockMemberInfoFunc &getMemberInfo,
134                               const sh::InterfaceBlock &interfaceBlock,
135                               ShaderType shaderType) const;
136 
137     virtual size_t getCurrentBlockMemberIndex() const = 0;
138 
139     virtual sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
140                                                   const std::string &namePrefix,
141                                                   const std::string &mappedNamePrefix,
142                                                   ShaderType shaderType,
143                                                   int blockIndex) const = 0;
144 
145     ShaderMap<const std::vector<sh::InterfaceBlock> *> mShaderBlocks = {};
146 
147     std::vector<InterfaceBlock> *mBlocksOut             = nullptr;
148     std::vector<std::string> *mUnusedInterfaceBlocksOut = nullptr;
149 };
150 
151 class UniformBlockLinker final : public InterfaceBlockLinker
152 {
153   public:
154     UniformBlockLinker();
155     ~UniformBlockLinker() override;
156 
157     void init(std::vector<InterfaceBlock> *blocksOut,
158               std::vector<LinkedUniform> *uniformsOut,
159               std::vector<std::string> *unusedInterfaceBlocksOut);
160 
161   private:
162     size_t getCurrentBlockMemberIndex() const override;
163 
164     sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
165                                           const std::string &namePrefix,
166                                           const std::string &mappedNamePrefix,
167                                           ShaderType shaderType,
168                                           int blockIndex) const override;
169 
170     std::vector<LinkedUniform> *mUniformsOut = nullptr;
171 };
172 
173 class ShaderStorageBlockLinker final : public InterfaceBlockLinker
174 {
175   public:
176     ShaderStorageBlockLinker();
177     ~ShaderStorageBlockLinker() override;
178 
179     void init(std::vector<InterfaceBlock> *blocksOut,
180               std::vector<BufferVariable> *bufferVariablesOut,
181               std::vector<std::string> *unusedInterfaceBlocksOut);
182 
183   private:
184     size_t getCurrentBlockMemberIndex() const override;
185 
186     sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
187                                           const std::string &namePrefix,
188                                           const std::string &mappedNamePrefix,
189                                           ShaderType shaderType,
190                                           int blockIndex) const override;
191 
192     std::vector<BufferVariable> *mBufferVariablesOut = nullptr;
193 };
194 
195 class AtomicCounterBufferLinker final : angle::NonCopyable
196 {
197   public:
198     AtomicCounterBufferLinker();
199     ~AtomicCounterBufferLinker();
200 
201     void init(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
202     void link(const std::map<int, unsigned int> &sizeMap) const;
203 
204   private:
205     std::vector<AtomicCounterBuffer> *mAtomicCounterBuffersOut = nullptr;
206 };
207 
208 // The link operation is responsible for finishing the link of uniform and interface blocks.
209 // This way it can filter out unreferenced resources and still have access to the info.
210 // TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks.
211 struct UnusedUniform
212 {
UnusedUniformUnusedUniform213     UnusedUniform(std::string name,
214                   bool isSampler,
215                   bool isImage,
216                   bool isAtomicCounter,
217                   bool isFragmentInOut)
218     {
219         this->name            = name;
220         this->isSampler       = isSampler;
221         this->isImage         = isImage;
222         this->isAtomicCounter = isAtomicCounter;
223         this->isFragmentInOut = isFragmentInOut;
224     }
225 
226     std::string name;
227     bool isSampler;
228     bool isImage;
229     bool isAtomicCounter;
230     bool isFragmentInOut;
231 };
232 
233 struct ProgramLinkedResources
234 {
235     ProgramLinkedResources();
236     ~ProgramLinkedResources();
237 
238     void init(std::vector<InterfaceBlock> *uniformBlocksOut,
239               std::vector<LinkedUniform> *uniformsOut,
240               std::vector<InterfaceBlock> *shaderStorageBlocksOut,
241               std::vector<BufferVariable> *bufferVariablesOut,
242               std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
243 
244     ProgramVaryingPacking varyingPacking;
245     UniformBlockLinker uniformBlockLinker;
246     ShaderStorageBlockLinker shaderStorageBlockLinker;
247     AtomicCounterBufferLinker atomicCounterBufferLinker;
248     std::vector<UnusedUniform> unusedUniforms;
249     std::vector<std::string> unusedInterfaceBlocks;
250 };
251 
252 struct LinkingVariables final : private angle::NonCopyable
253 {
254     LinkingVariables(const ProgramState &state);
255     LinkingVariables(const ProgramPipelineState &state);
256     ~LinkingVariables();
257 
258     ShaderMap<std::vector<sh::ShaderVariable>> outputVaryings;
259     ShaderMap<std::vector<sh::ShaderVariable>> inputVaryings;
260     ShaderMap<std::vector<sh::ShaderVariable>> uniforms;
261     ShaderMap<std::vector<sh::InterfaceBlock>> uniformBlocks;
262     ShaderBitSet isShaderStageUsedBitset;
263 };
264 
265 class CustomBlockLayoutEncoderFactory : angle::NonCopyable
266 {
267   public:
~CustomBlockLayoutEncoderFactory()268     virtual ~CustomBlockLayoutEncoderFactory() {}
269 
270     virtual sh::BlockLayoutEncoder *makeEncoder() = 0;
271 };
272 
273 // Used by the backends in Program*::linkResources to parse interface blocks and provide
274 // information to ProgramLinkedResources' linkers.
275 class ProgramLinkedResourcesLinker final : angle::NonCopyable
276 {
277   public:
ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory * customEncoderFactory)278     ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory *customEncoderFactory)
279         : mCustomEncoderFactory(customEncoderFactory)
280     {}
281 
282     void linkResources(const ProgramState &programState,
283                        const ProgramLinkedResources &resources) const;
284 
285   private:
286     void getAtomicCounterBufferSizeMap(const ProgramState &programState,
287                                        std::map<int, unsigned int> &sizeMapOut) const;
288 
289     CustomBlockLayoutEncoderFactory *mCustomEncoderFactory;
290 };
291 
292 using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>;
293 using InterfaceBlockMap    = std::map<std::string, ShaderInterfaceBlock>;
294 
295 bool LinkValidateProgramGlobalNames(InfoLog &infoLog,
296                                     const ProgramExecutable &executable,
297                                     const LinkingVariables &linkingVariables);
298 bool LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> &outputVaryings,
299                                          const std::vector<sh::ShaderVariable> &inputVaryings,
300                                          ShaderType frontShaderType,
301                                          ShaderType backShaderType,
302                                          int frontShaderVersion,
303                                          int backShaderVersion,
304                                          bool isSeparable,
305                                          InfoLog &infoLog);
306 bool LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> &vertexVaryings,
307                                           const std::vector<sh::ShaderVariable> &fragmentVaryings,
308                                           int vertexShaderVersion,
309                                           InfoLog &infoLog);
310 bool LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &inputVaryings,
311                                  const std::vector<sh::ShaderVariable> &outputVaryings,
312                                  ShaderType inputShaderType,
313                                  ShaderType outputShaderType,
314                                  int inputShaderVersion,
315                                  int outputShaderVersion,
316                                  InfoLog &infoLog);
317 LinkMismatchError LinkValidateProgramVariables(const sh::ShaderVariable &variable1,
318                                                const sh::ShaderVariable &variable2,
319                                                bool validatePrecision,
320                                                bool treatVariable1AsNonArray,
321                                                bool treatVariable2AsNonArray,
322                                                std::string *mismatchedStructOrBlockMemberName);
323 void AddProgramVariableParentPrefix(const std::string &parentName,
324                                     std::string *mismatchedFieldName);
325 bool LinkValidateProgramInterfaceBlocks(const Context *context,
326                                         ShaderBitSet activeProgramStages,
327                                         const ProgramLinkedResources &resources,
328                                         InfoLog &infoLog,
329                                         GLuint *combinedShaderStorageBlocksCountOut);
330 }  // namespace gl
331 
332 #endif  // LIBANGLE_UNIFORMLINKER_H_
333