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