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