• 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     // This constructor is used by the HLSL backend
BlockMemberInfoBlockMemberInfo29     constexpr BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
30         : type(GL_INVALID_ENUM),
31           offset(offset),
32           arrayStride(arrayStride),
33           matrixStride(matrixStride),
34           arraySize(-1),
35           isRowMajorMatrix(isRowMajorMatrix)
36     {}
37 
BlockMemberInfoBlockMemberInfo38     constexpr BlockMemberInfo(int offset,
39                               int arrayStride,
40                               int matrixStride,
41                               bool isRowMajorMatrix,
42                               int topLevelArrayStride)
43         : type(GL_INVALID_ENUM),
44           offset(offset),
45           arrayStride(arrayStride),
46           matrixStride(matrixStride),
47           arraySize(-1),
48           isRowMajorMatrix(isRowMajorMatrix),
49           topLevelArrayStride(topLevelArrayStride)
50     {}
51 
BlockMemberInfoBlockMemberInfo52     constexpr BlockMemberInfo(GLenum type,
53                               int offset,
54                               int arrayStride,
55                               int matrixStride,
56                               int arraySize,
57                               bool isRowMajorMatrix)
58         : type(type),
59           offset(offset),
60           arrayStride(arrayStride),
61           matrixStride(matrixStride),
62           arraySize(arraySize),
63           isRowMajorMatrix(isRowMajorMatrix)
64     {}
65 
BlockMemberInfoBlockMemberInfo66     constexpr BlockMemberInfo(GLenum type,
67                               int offset,
68                               int arrayStride,
69                               int matrixStride,
70                               int arraySize,
71                               bool isRowMajorMatrix,
72                               int topLevelArrayStride)
73         : type(type),
74           offset(offset),
75           arrayStride(arrayStride),
76           matrixStride(matrixStride),
77           arraySize(arraySize),
78           isRowMajorMatrix(isRowMajorMatrix),
79           topLevelArrayStride(topLevelArrayStride)
80     {}
81 
82     GLenum type = GL_INVALID_ENUM;
83 
84     // A single integer identifying the offset of an active variable.
85     int offset = -1;
86 
87     // A single integer identifying the stride between array elements in an active variable.
88     int arrayStride = -1;
89 
90     // A single integer identifying the stride between columns of a column-major matrix or rows of a
91     // row-major matrix.
92     int matrixStride = -1;
93 
94     // A single integer, identifying the length of an array variable.
95     int arraySize = -1;
96 
97     // A single integer identifying whether an active variable is a row-major matrix.
98     bool isRowMajorMatrix = false;
99 
100     // A single integer identifying the number of active array elements of the top-level shader
101     // storage block member containing the active variable.
102     int topLevelArrayStride = -1;
103 };
104 
105 bool operator==(const BlockMemberInfo &lhs, const BlockMemberInfo &rhs);
106 
ComponentAlignment(size_t numComponents)107 constexpr size_t ComponentAlignment(size_t numComponents)
108 {
109     return (numComponents == 3u ? 4u : numComponents);
110 }
111 
112 constexpr BlockMemberInfo kDefaultBlockMemberInfo;
113 
114 class BlockLayoutEncoder
115 {
116   public:
117     BlockLayoutEncoder();
~BlockLayoutEncoder()118     virtual ~BlockLayoutEncoder() {}
119 
120     virtual BlockMemberInfo encodeType(GLenum type,
121                                        const std::vector<unsigned int> &arraySizes,
122                                        bool isRowMajorMatrix);
123     // Advance the offset based on struct size and array dimensions.  Size can be calculated with
124     // getShaderVariableSize() or equivalent.  |enterAggregateType|/|exitAggregateType| is necessary
125     // around this call.
126     virtual BlockMemberInfo encodeArrayOfPreEncodedStructs(
127         size_t size,
128         const std::vector<unsigned int> &arraySizes);
129 
130     virtual size_t getCurrentOffset() const;
131     virtual size_t getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor);
132 
133     // Called when entering/exiting a structure variable.
134     virtual void enterAggregateType(const ShaderVariable &structVar) = 0;
135     virtual void exitAggregateType(const ShaderVariable &structVar)  = 0;
136 
137     static constexpr size_t kBytesPerComponent           = 4u;
138     static constexpr unsigned int kComponentsPerRegister = 4u;
139 
140     static size_t GetBlockRegister(const BlockMemberInfo &info);
141     static size_t GetBlockRegisterElement(const BlockMemberInfo &info);
142 
143   protected:
144     void align(size_t baseAlignment);
145 
146     virtual void getBlockLayoutInfo(GLenum type,
147                                     const std::vector<unsigned int> &arraySizes,
148                                     bool isRowMajorMatrix,
149                                     int *arrayStrideOut,
150                                     int *matrixStrideOut) = 0;
151     virtual void advanceOffset(GLenum type,
152                                const std::vector<unsigned int> &arraySizes,
153                                bool isRowMajorMatrix,
154                                int arrayStride,
155                                int matrixStride)          = 0;
156 
157     size_t mCurrentOffset;
158 };
159 
160 // Will return default values for everything.
161 class StubBlockEncoder : public BlockLayoutEncoder
162 {
163   public:
164     StubBlockEncoder() = default;
165 
enterAggregateType(const ShaderVariable & structVar)166     void enterAggregateType(const ShaderVariable &structVar) override {}
exitAggregateType(const ShaderVariable & structVar)167     void exitAggregateType(const ShaderVariable &structVar) override {}
168 
169   protected:
170     void getBlockLayoutInfo(GLenum type,
171                             const std::vector<unsigned int> &arraySizes,
172                             bool isRowMajorMatrix,
173                             int *arrayStrideOut,
174                             int *matrixStrideOut) override;
175 
advanceOffset(GLenum type,const std::vector<unsigned int> & arraySizes,bool isRowMajorMatrix,int arrayStride,int matrixStride)176     void advanceOffset(GLenum type,
177                        const std::vector<unsigned int> &arraySizes,
178                        bool isRowMajorMatrix,
179                        int arrayStride,
180                        int matrixStride) override
181     {}
182 };
183 
184 // Block layout according to the std140 block layout
185 // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
186 
187 class Std140BlockEncoder : public BlockLayoutEncoder
188 {
189   public:
190     Std140BlockEncoder();
191 
192     void enterAggregateType(const ShaderVariable &structVar) override;
193     void exitAggregateType(const ShaderVariable &structVar) override;
194 
195   protected:
196     void getBlockLayoutInfo(GLenum type,
197                             const std::vector<unsigned int> &arraySizes,
198                             bool isRowMajorMatrix,
199                             int *arrayStrideOut,
200                             int *matrixStrideOut) override;
201     void advanceOffset(GLenum type,
202                        const std::vector<unsigned int> &arraySizes,
203                        bool isRowMajorMatrix,
204                        int arrayStride,
205                        int matrixStride) override;
206 
207     virtual size_t getBaseAlignment(const ShaderVariable &variable) const;
208     virtual size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const;
209 };
210 
211 class Std430BlockEncoder : public Std140BlockEncoder
212 {
213   public:
214     Std430BlockEncoder();
215 
216   protected:
217     size_t getBaseAlignment(const ShaderVariable &variable) const override;
218     size_t getTypeBaseAlignment(GLenum type, bool isRowMajorMatrix) const override;
219 };
220 
221 using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
222 
223 void GetInterfaceBlockInfo(const std::vector<ShaderVariable> &fields,
224                            const std::string &prefix,
225                            BlockLayoutEncoder *encoder,
226                            BlockLayoutMap *blockInfoOut);
227 
228 // Used for laying out the default uniform block on the Vulkan backend.
229 void GetActiveUniformBlockInfo(const std::vector<ShaderVariable> &uniforms,
230                                const std::string &prefix,
231                                BlockLayoutEncoder *encoder,
232                                BlockLayoutMap *blockInfoOut);
233 
234 class ShaderVariableVisitor
235 {
236   public:
~ShaderVariableVisitor()237     virtual ~ShaderVariableVisitor() {}
238 
enterStruct(const ShaderVariable & structVar)239     virtual void enterStruct(const ShaderVariable &structVar) {}
exitStruct(const ShaderVariable & structVar)240     virtual void exitStruct(const ShaderVariable &structVar) {}
241 
enterStructAccess(const ShaderVariable & structVar,bool isRowMajor)242     virtual void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
exitStructAccess(const ShaderVariable & structVar,bool isRowMajor)243     virtual void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) {}
244 
enterArray(const ShaderVariable & arrayVar)245     virtual void enterArray(const ShaderVariable &arrayVar) {}
exitArray(const ShaderVariable & arrayVar)246     virtual void exitArray(const ShaderVariable &arrayVar) {}
247 
enterArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)248     virtual void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {}
exitArrayElement(const ShaderVariable & arrayVar,unsigned int arrayElement)249     virtual void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) {}
250 
visitOpaqueObject(const sh::ShaderVariable & variable)251     virtual void visitOpaqueObject(const sh::ShaderVariable &variable) {}
252 
253     virtual void visitVariable(const ShaderVariable &variable, bool isRowMajor) = 0;
254 
255   protected:
ShaderVariableVisitor()256     ShaderVariableVisitor() {}
257 };
258 
259 class VariableNameVisitor : public ShaderVariableVisitor
260 {
261   public:
262     VariableNameVisitor(const std::string &namePrefix, const std::string &mappedNamePrefix);
263     ~VariableNameVisitor() override;
264 
265     void enterStruct(const ShaderVariable &structVar) override;
266     void exitStruct(const ShaderVariable &structVar) override;
267     void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
268     void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
269     void enterArray(const ShaderVariable &arrayVar) override;
270     void exitArray(const ShaderVariable &arrayVar) override;
271     void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
272     void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
273 
274   protected:
visitNamedOpaqueObject(const sh::ShaderVariable & variable,const std::string & name,const std::string & mappedName,const std::vector<unsigned int> & arraySizes)275     virtual void visitNamedOpaqueObject(const sh::ShaderVariable &variable,
276                                         const std::string &name,
277                                         const std::string &mappedName,
278                                         const std::vector<unsigned int> &arraySizes)
279     {}
280     virtual void visitNamedVariable(const ShaderVariable &variable,
281                                     bool isRowMajor,
282                                     const std::string &name,
283                                     const std::string &mappedName,
284                                     const std::vector<unsigned int> &arraySizes) = 0;
285 
286     std::string collapseNameStack() const;
287     std::string collapseMappedNameStack() const;
288 
289   private:
290     void visitOpaqueObject(const sh::ShaderVariable &variable) final;
291     void visitVariable(const ShaderVariable &variable, bool isRowMajor) final;
292 
293     std::vector<std::string> mNameStack;
294     std::vector<std::string> mMappedNameStack;
295     std::vector<unsigned int> mArraySizeStack;
296 };
297 
298 class BlockEncoderVisitor : public VariableNameVisitor
299 {
300   public:
301     BlockEncoderVisitor(const std::string &namePrefix,
302                         const std::string &mappedNamePrefix,
303                         BlockLayoutEncoder *encoder);
304     ~BlockEncoderVisitor() override;
305 
306     void enterStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
307     void exitStructAccess(const ShaderVariable &structVar, bool isRowMajor) override;
308     void enterArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
309     void exitArrayElement(const ShaderVariable &arrayVar, unsigned int arrayElement) override;
310 
311     void visitNamedVariable(const ShaderVariable &variable,
312                             bool isRowMajor,
313                             const std::string &name,
314                             const std::string &mappedName,
315                             const std::vector<unsigned int> &arraySizes) override;
316 
encodeVariable(const ShaderVariable & variable,const BlockMemberInfo & variableInfo,const std::string & name,const std::string & mappedName)317     virtual void encodeVariable(const ShaderVariable &variable,
318                                 const BlockMemberInfo &variableInfo,
319                                 const std::string &name,
320                                 const std::string &mappedName)
321     {}
322 
323   protected:
324     int mTopLevelArraySize           = 1;
325     int mTopLevelArrayStride         = 0;
326     bool mIsTopLevelArrayStrideReady = true;
327     bool mSkipEnabled                = false;
328 
329   private:
330     BlockLayoutEncoder *mEncoder;
331     unsigned int mStructStackSize = 0;
332 };
333 
334 void TraverseShaderVariable(const ShaderVariable &variable,
335                             bool isRowMajorLayout,
336                             ShaderVariableVisitor *visitor);
337 
338 template <typename T>
TraverseShaderVariables(const std::vector<T> & vars,bool isRowMajorLayout,ShaderVariableVisitor * visitor)339 void TraverseShaderVariables(const std::vector<T> &vars,
340                              bool isRowMajorLayout,
341                              ShaderVariableVisitor *visitor)
342 {
343     for (const T &var : vars)
344     {
345         TraverseShaderVariable(var, isRowMajorLayout, visitor);
346     }
347 }
348 
349 template <typename T>
TraverseActiveShaderVariables(const std::vector<T> & vars,bool isRowMajorLayout,ShaderVariableVisitor * visitor)350 void TraverseActiveShaderVariables(const std::vector<T> &vars,
351                                    bool isRowMajorLayout,
352                                    ShaderVariableVisitor *visitor)
353 {
354     for (const T &var : vars)
355     {
356         if (var.active)
357         {
358             TraverseShaderVariable(var, isRowMajorLayout, visitor);
359         }
360     }
361 }
362 }  // namespace sh
363 
364 #endif  // COMMON_BLOCKLAYOUT_H_
365