• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 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 // blocklayout.h:
7 //   Methods and classes related to uniform layout and packing in GLSL and HLSL.
8 //
9 
10 #ifndef COMMON_BLOCKLAYOUT_H_
11 #define COMMON_BLOCKLAYOUT_H_
12 
13 #include <cstddef>
14 #include <map>
15 #include <vector>
16 
17 #include <GLSLANG/ShaderLang.h>
18 #include "angle_gl.h"
19 
20 namespace sh
21 {
22 struct ShaderVariable;
23 struct InterfaceBlock;
24 
25 struct BlockMemberInfo
26 {
27     constexpr BlockMemberInfo() = default;
28 
BlockMemberInfoBlockMemberInfo29     constexpr BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
30         : offset(offset),
31           arrayStride(arrayStride),
32           matrixStride(matrixStride),
33           isRowMajorMatrix(isRowMajorMatrix)
34     {}
35 
BlockMemberInfoBlockMemberInfo36     constexpr BlockMemberInfo(int offset,
37                               int arrayStride,
38                               int matrixStride,
39                               bool isRowMajorMatrix,
40                               int topLevelArrayStride)
41         : offset(offset),
42           arrayStride(arrayStride),
43           matrixStride(matrixStride),
44           isRowMajorMatrix(isRowMajorMatrix),
45           topLevelArrayStride(topLevelArrayStride)
46     {}
47 
48     // A single integer identifying the offset of an active variable.
49     int offset = -1;
50 
51     // A single integer identifying the stride between array elements in an active variable.
52     int arrayStride = -1;
53 
54     // A single integer identifying the stride between columns of a column-major matrix or rows of a
55     // row-major matrix.
56     int matrixStride = -1;
57 
58     // A single integer identifying whether an active variable is a row-major matrix.
59     bool isRowMajorMatrix = false;
60 
61     // A single integer identifying the number of active array elements of the top-level shader
62     // storage block member containing the active variable.
63     int topLevelArrayStride = -1;
64 };
65 
ComponentAlignment(size_t numComponents)66 constexpr size_t ComponentAlignment(size_t numComponents)
67 {
68     return (numComponents == 3u ? 4u : numComponents);
69 }
70 
71 constexpr BlockMemberInfo kDefaultBlockMemberInfo;
72 
73 class BlockLayoutEncoder
74 {
75   public:
76     BlockLayoutEncoder();
~BlockLayoutEncoder()77     virtual ~BlockLayoutEncoder() {}
78 
79     BlockMemberInfo encodeType(GLenum type,
80                                const std::vector<unsigned int> &arraySizes,
81                                bool isRowMajorMatrix);
82 
getCurrentOffset()83     size_t getCurrentOffset() const { return mCurrentOffset * kBytesPerComponent; }
84     size_t getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor);
85 
86     // Called when entering/exiting a structure variable.
87     virtual void enterAggregateType(const ShaderVariable &structVar) = 0;
88     virtual void exitAggregateType(const ShaderVariable &structVar)  = 0;
89 
90     static constexpr size_t kBytesPerComponent           = 4u;
91     static constexpr unsigned int kComponentsPerRegister = 4u;
92 
93     static size_t GetBlockRegister(const BlockMemberInfo &info);
94     static size_t GetBlockRegisterElement(const BlockMemberInfo &info);
95 
96   protected:
97     void align(size_t baseAlignment);
98 
99     virtual void getBlockLayoutInfo(GLenum type,
100                                     const std::vector<unsigned int> &arraySizes,
101                                     bool isRowMajorMatrix,
102                                     int *arrayStrideOut,
103                                     int *matrixStrideOut) = 0;
104     virtual void advanceOffset(GLenum type,
105                                const std::vector<unsigned int> &arraySizes,
106                                bool isRowMajorMatrix,
107                                int arrayStride,
108                                int matrixStride)          = 0;
109 
110     size_t mCurrentOffset;
111 };
112 
113 // Will return default values for everything.
114 class DummyBlockEncoder : public BlockLayoutEncoder
115 {
116   public:
117     DummyBlockEncoder() = default;
118 
enterAggregateType(const ShaderVariable & structVar)119     void enterAggregateType(const ShaderVariable &structVar) override {}
exitAggregateType(const ShaderVariable & structVar)120     void exitAggregateType(const ShaderVariable &structVar) override {}
121 
122   protected:
123     void getBlockLayoutInfo(GLenum type,
124                             const std::vector<unsigned int> &arraySizes,
125                             bool isRowMajorMatrix,
126                             int *arrayStrideOut,
127                             int *matrixStrideOut) override;
128 
advanceOffset(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int arrayStride,int matrixStride)129     void advanceOffset(GLenum type,
130                        const std::vector<unsigned int> &arraySizes,
131                        bool isRowMajorMatrix,
132                        int arrayStride,
133                        int matrixStride) override
134     {}
135 };
136 
137 // Block layout according to the std140 block layout
138 // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
139 
140 class Std140BlockEncoder : public BlockLayoutEncoder
141 {
142   public:
143     Std140BlockEncoder();
144 
145     void enterAggregateType(const ShaderVariable &structVar) override;
146     void exitAggregateType(const ShaderVariable &structVar) override;
147 
148   protected:
149     void getBlockLayoutInfo(GLenum type,
150                             const std::vector<unsigned int> &arraySizes,
151                             bool isRowMajorMatrix,
152                             int *arrayStrideOut,
153                             int *matrixStrideOut) override;
154     void advanceOffset(GLenum type,
155                        const std::vector<unsigned int> &arraySizes,
156                        bool isRowMajorMatrix,
157                        int arrayStride,
158                        int matrixStride) override;
159 
160     virtual size_t getBaseAlignment(const ShaderVariable &variable) const;
161     virtual size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const;
162 };
163 
164 class Std430BlockEncoder : public Std140BlockEncoder
165 {
166   public:
167     Std430BlockEncoder();
168 
169   protected:
170     size_t getBaseAlignment(const ShaderVariable &variable) const override;
171     size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const override;
172 };
173 
174 using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
175 
176 void GetInterfaceBlockInfo(const std::vector<ShaderVariable> &fields,
177                            const std::string &prefix,
178                            BlockLayoutEncoder *encoder,
179                            BlockLayoutMap *blockInfoOut);
180 
181 // Used for laying out the default uniform block on the Vulkan backend.
182 void GetActiveUniformBlockInfo(const std::vector<ShaderVariable> &uniforms,
183                                const std::string &prefix,
184                                BlockLayoutEncoder *encoder,
185                                BlockLayoutMap *blockInfoOut);
186 
187 class ShaderVariableVisitor
188 {
189   public:
~ShaderVariableVisitor()190     virtual ~ShaderVariableVisitor() {}
191 
enterStruct(const ShaderVariable & structVar)192     virtual void enterStruct(const ShaderVariable &structVar) {}
exitStruct(const ShaderVariable & structVar)193     virtual void exitStruct(const ShaderVariable &structVar) {}
194 
enterStructAccess(const ShaderVariable & structVar,bool isRowMajor)195     virtual void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
exitStructAccess(const ShaderVariable & structVar,bool isRowMajor)196     virtual void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
197 
enterArray(const ShaderVariable & arrayVar)198     virtual void enterArray(const ShaderVariable &arrayVar) {}
exitArray(const ShaderVariable & arrayVar)199     virtual void exitArray(const ShaderVariable &arrayVar) {}
200 
enterArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)201     virtual void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {}
exitArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)202     virtual void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {}
203 
visitSampler(const sh::ShaderVariable & sampler)204     virtual void visitSampler(const sh::ShaderVariable &sampler) {}
205 
206     virtual void visitVariable(const ShaderVariable &variable, bool isRowMajor) = 0;
207 
208   protected:
ShaderVariableVisitor()209     ShaderVariableVisitor() {}
210 };
211 
212 class VariableNameVisitor : public ShaderVariableVisitor
213 {
214   public:
215     VariableNameVisitor(const std::string &namePrefix, const std::string &mappedNamePrefix);
216     ~VariableNameVisitor() override;
217 
218     void enterStruct(const ShaderVariable &structVar) override;
219     void exitStruct(const ShaderVariable &structVar) override;
220     void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
221     void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
222     void enterArray(const ShaderVariable &arrayVar) override;
223     void exitArray(const ShaderVariable &arrayVar) override;
224     void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
225     void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
226 
227   protected:
visitNamedSampler(const sh::ShaderVariable & sampler,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)228     virtual void visitNamedSampler(const sh::ShaderVariable &sampler,
229                                    const std::string &name,
230                                    const std::string &mappedName,
231                                    const std::vector<unsigned int> &arraySizes)
232     {}
233     virtual void visitNamedVariable(const ShaderVariable &variable,
234                                     bool isRowMajor,
235                                     const std::string &name,
236                                     const std::string &mappedName,
237                                     const std::vector<unsigned int> &arraySizes) = 0;
238 
239     std::string collapseNameStack() const;
240     std::string collapseMappedNameStack() const;
241 
242   private:
243     void visitSampler(const sh::ShaderVariable &sampler) final;
244     void visitVariable(const ShaderVariable &variable, bool isRowMajor) final;
245 
246     std::vector<std::string> mNameStack;
247     std::vector<std::string> mMappedNameStack;
248     std::vector<unsigned int> mArraySizeStack;
249 };
250 
251 class BlockEncoderVisitor : public VariableNameVisitor
252 {
253   public:
254     BlockEncoderVisitor(const std::string &namePrefix,
255                         const std::string &mappedNamePrefix,
256                         BlockLayoutEncoder *encoder);
257     ~BlockEncoderVisitor() override;
258 
259     void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
260     void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
261     void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
262     void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
263 
264     void visitNamedVariable(const ShaderVariable &variable,
265                             bool isRowMajor,
266                             const std::string &name,
267                             const std::string &mappedName,
268                             const std::vector<unsigned int> &arraySizes) override;
269 
encodeVariable(const ShaderVariable & variable,const BlockMemberInfo & variableInfo,const std::string & name,const std::string & mappedName)270     virtual void encodeVariable(const ShaderVariable &variable,
271                                 const BlockMemberInfo &variableInfo,
272                                 const std::string &name,
273                                 const std::string &mappedName)
274     {}
275 
276   protected:
277     int mTopLevelArraySize           = 1;
278     int mTopLevelArrayStride         = 0;
279     bool mIsTopLevelArrayStrideReady = true;
280     bool mSkipEnabled                = false;
281 
282   private:
283     BlockLayoutEncoder *mEncoder;
284     unsigned int mStructStackSize = 0;
285 };
286 
287 void TraverseShaderVariable(const ShaderVariable &variable,
288                             bool isRowMajorLayout,
289                             ShaderVariableVisitor *visitor);
290 
291 template <typename T>
TraverseShaderVariables(const std::vector<T> & vars,bool isRowMajorLayout,ShaderVariableVisitor * visitor)292 void TraverseShaderVariables(const std::vector<T> &vars,
293                              bool isRowMajorLayout,
294                              ShaderVariableVisitor *visitor)
295 {
296     for (const T &var : vars)
297     {
298         TraverseShaderVariable(var, isRowMajorLayout, visitor);
299     }
300 }
301 
302 template <typename T>
TraverseActiveShaderVariables(const std::vector<T> & vars,bool isRowMajorLayout,ShaderVariableVisitor * visitor)303 void TraverseActiveShaderVariables(const std::vector<T> &vars,
304                                    bool isRowMajorLayout,
305                                    ShaderVariableVisitor *visitor)
306 {
307     for (const T &var : vars)
308     {
309         if (var.active)
310         {
311             TraverseShaderVariable(var, isRowMajorLayout, visitor);
312         }
313     }
314 }
315 }  // namespace sh
316 
317 #endif  // COMMON_BLOCKLAYOUT_H_
318