1 //
2 // Copyright (c) 2013-2014 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 "angle_gl.h"
18 #include <GLSLANG/ShaderLang.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 {
BlockMemberInfoBlockMemberInfo30     BlockMemberInfo()
31         : offset(-1),
32           arrayStride(-1),
33           matrixStride(-1),
34           isRowMajorMatrix(false),
35           topLevelArrayStride(-1)
36     {
37     }
38 
BlockMemberInfoBlockMemberInfo39     BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
40         : offset(offset),
41           arrayStride(arrayStride),
42           matrixStride(matrixStride),
43           isRowMajorMatrix(isRowMajorMatrix),
44           topLevelArrayStride(-1)
45     {
46     }
47 
BlockMemberInfoBlockMemberInfo48     BlockMemberInfo(int offset,
49                     int arrayStride,
50                     int matrixStride,
51                     bool isRowMajorMatrix,
52                     int topLevelArrayStride)
53         : offset(offset),
54           arrayStride(arrayStride),
55           matrixStride(matrixStride),
56           isRowMajorMatrix(isRowMajorMatrix),
57           topLevelArrayStride(topLevelArrayStride)
58     {
59     }
60 
getDefaultBlockInfoBlockMemberInfo61     static BlockMemberInfo getDefaultBlockInfo() { return BlockMemberInfo(-1, -1, -1, false, -1); }
62 
63     int offset;
64     int arrayStride;
65     int matrixStride;
66     bool isRowMajorMatrix;
67     int topLevelArrayStride;  // Only used for shader storage block members.
68 };
69 
70 class BlockLayoutEncoder
71 {
72   public:
73     BlockLayoutEncoder();
~BlockLayoutEncoder()74     virtual ~BlockLayoutEncoder() {}
75 
76     BlockMemberInfo encodeType(GLenum type,
77                                const std::vector<unsigned int> &arraySizes,
78                                bool isRowMajorMatrix);
79 
getBlockSize()80     size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
81 
82     virtual void enterAggregateType() = 0;
83     virtual void exitAggregateType()  = 0;
84 
85     static const size_t BytesPerComponent           = 4u;
86     static const unsigned int ComponentsPerRegister = 4u;
87 
88     static size_t getBlockRegister(const BlockMemberInfo &info);
89     static size_t getBlockRegisterElement(const BlockMemberInfo &info);
90 
91   protected:
92     size_t mCurrentOffset;
93 
94     void nextRegister();
95 
96     virtual void getBlockLayoutInfo(GLenum type,
97                                     const std::vector<unsigned int> &arraySizes,
98                                     bool isRowMajorMatrix,
99                                     int *arrayStrideOut,
100                                     int *matrixStrideOut) = 0;
101     virtual void advanceOffset(GLenum type,
102                                const std::vector<unsigned int> &arraySizes,
103                                bool isRowMajorMatrix,
104                                int arrayStride,
105                                int matrixStride)          = 0;
106 };
107 
108 // Block layout according to the std140 block layout
109 // See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification
110 
111 class Std140BlockEncoder : public BlockLayoutEncoder
112 {
113   public:
114     Std140BlockEncoder();
115 
116     void enterAggregateType() override;
117     void exitAggregateType() override;
118 
119   protected:
120     void getBlockLayoutInfo(GLenum type,
121                             const std::vector<unsigned int> &arraySizes,
122                             bool isRowMajorMatrix,
123                             int *arrayStrideOut,
124                             int *matrixStrideOut) override;
125     void advanceOffset(GLenum type,
126                        const std::vector<unsigned int> &arraySizes,
127                        bool isRowMajorMatrix,
128                        int arrayStride,
129                        int matrixStride) override;
130 };
131 
132 using BlockLayoutMap = std::map<std::string, BlockMemberInfo>;
133 
134 // Only valid to call with ShaderVariable, InterfaceBlockField and Uniform.
135 template <typename VarT>
136 void GetUniformBlockInfo(const std::vector<VarT> &fields,
137                          const std::string &prefix,
138                          sh::BlockLayoutEncoder *encoder,
139                          bool inRowMajorLayout,
140                          BlockLayoutMap *blockLayoutMap);
141 
142 }  // namespace sh
143 
144 #endif  // COMMON_BLOCKLAYOUT_H_
145