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 // ShaderVars.h:
7 // Types to represent GL variables (varyings, uniforms, etc)
8 //
9
10 #ifndef GLSLANG_SHADERVARS_H_
11 #define GLSLANG_SHADERVARS_H_
12
13 #include <algorithm>
14 #include <array>
15 #include <string>
16 #include <vector>
17
18 // This type is defined here to simplify ANGLE's integration with glslang for SPIRv.
19 using ShCompileOptions = uint64_t;
20
21 namespace sh
22 {
23 // GLenum alias
24 typedef unsigned int GLenum;
25
26 // Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec
27 enum InterpolationType
28 {
29 INTERPOLATION_SMOOTH,
30 INTERPOLATION_CENTROID,
31 INTERPOLATION_FLAT,
32 INTERPOLATION_NOPERSPECTIVE
33 };
34
35 // Validate link & SSO consistency of interpolation qualifiers
36 bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
37
38 // Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
39 enum BlockLayoutType
40 {
41 BLOCKLAYOUT_STANDARD,
42 BLOCKLAYOUT_STD140 = BLOCKLAYOUT_STANDARD,
43 BLOCKLAYOUT_STD430, // Shader storage block layout qualifier
44 BLOCKLAYOUT_PACKED,
45 BLOCKLAYOUT_SHARED
46 };
47
48 // Interface Blocks, see section 4.3.9 of the ESSL 3.10 spec
49 enum class BlockType
50 {
51 BLOCK_UNIFORM,
52 BLOCK_BUFFER,
53
54 // Required in OpenGL ES 3.1 extension GL_OES_shader_io_blocks.
55 // TODO(jiawei.shao@intel.com): add BLOCK_OUT.
56 // Also used in GLSL
57 BLOCK_IN
58 };
59
60 // Base class for all variables defined in shaders, including Varyings, Uniforms, etc
61 // Note: we must override the copy constructor and assignment operator so we can
62 // work around excessive GCC binary bloating:
63 // See https://code.google.com/p/angleproject/issues/detail?id=697
64 struct ShaderVariable
65 {
66 ShaderVariable();
67 ShaderVariable(GLenum typeIn);
68 ShaderVariable(GLenum typeIn, unsigned int arraySizeIn);
69 ~ShaderVariable();
70 ShaderVariable(const ShaderVariable &other);
71 ShaderVariable &operator=(const ShaderVariable &other);
72 bool operator==(const ShaderVariable &other) const;
73 bool operator!=(const ShaderVariable &other) const { return !operator==(other); }
74
isArrayOfArraysShaderVariable75 bool isArrayOfArrays() const { return arraySizes.size() >= 2u; }
isArrayShaderVariable76 bool isArray() const { return !arraySizes.empty(); }
77 unsigned int getArraySizeProduct() const;
78 // Return the inner array size product.
79 // For example, if there's a variable declared as size 3 array of size 4 array of size 5 array
80 // of int:
81 // int a[3][4][5];
82 // then getInnerArraySizeProduct of a would be 4*5.
83 unsigned int getInnerArraySizeProduct() const;
84
85 // Array size 0 means not an array when passed to or returned from these functions.
86 // Note that setArraySize() is deprecated and should not be used inside ANGLE.
getOutermostArraySizeShaderVariable87 unsigned int getOutermostArraySize() const { return isArray() ? arraySizes.back() : 0; }
88 void setArraySize(unsigned int size);
89
90 // Turn this ShaderVariable from an array into a specific element in that array. Will update
91 // flattenedOffsetInParentArrays.
92 void indexIntoArray(unsigned int arrayIndex);
93
94 // Get the nth nested array size from the top. Caller is responsible for range checking
95 // arrayNestingIndex.
96 unsigned int getNestedArraySize(unsigned int arrayNestingIndex) const;
97
98 // This function should only be used with variables that are of a basic type or an array of a
99 // basic type. Shader interface variables that are enumerated according to rules in GLES 3.1
100 // spec section 7.3.1.1 page 77 are fine. For those variables the return value should match the
101 // ARRAY_SIZE value that can be queried through the API.
102 unsigned int getBasicTypeElementCount() const;
103
104 unsigned int getExternalSize() const;
105
isStructShaderVariable106 bool isStruct() const { return !fields.empty(); }
107
108 // All of the shader's variables are described using nested data
109 // structures. This is needed in order to disambiguate similar looking
110 // types, such as two structs containing the same fields, but in
111 // different orders. "findInfoByMappedName" provides an easy query for
112 // users to dive into the data structure and fetch the unique variable
113 // instance corresponding to a dereferencing chain of the top-level
114 // variable.
115 // Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
116 // that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
117 // in |originalName|, based on the assumption that |this| defines 'a'.
118 // If no match is found, return false.
119 bool findInfoByMappedName(const std::string &mappedFullName,
120 const ShaderVariable **leafVar,
121 std::string *originalFullName) const;
122
123 bool isBuiltIn() const;
124 bool isEmulatedBuiltIn() const;
125
126 GLenum type;
127 GLenum precision;
128 std::string name;
129 std::string mappedName;
130
131 // Used to make an array type. Outermost array size is stored at the end of the vector.
132 std::vector<unsigned int> arraySizes;
133
134 // Offset of this variable in parent arrays. In case the parent is an array of arrays, the
135 // offset is outerArrayElement * innerArraySize + innerArrayElement.
136 // For example, if there's a variable declared as size 3 array of size 4 array of int:
137 // int a[3][4];
138 // then the flattenedOffsetInParentArrays of a[2] would be 2.
139 // and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
parentArrayIndexShaderVariable140 int parentArrayIndex() const
141 {
142 return hasParentArrayIndex() ? flattenedOffsetInParentArrays : 0;
143 }
144
setParentArrayIndexShaderVariable145 void setParentArrayIndex(int indexIn) { flattenedOffsetInParentArrays = indexIn; }
146
hasParentArrayIndexShaderVariable147 bool hasParentArrayIndex() const { return flattenedOffsetInParentArrays != -1; }
148
149 // Static use means that the variable is accessed somewhere in the shader source.
150 bool staticUse;
151 // A variable is active unless the compiler determined that it is not accessed by the shader.
152 // All active variables are statically used, but not all statically used variables are
153 // necessarily active. GLES 3.0.5 section 2.12.6. GLES 3.1 section 7.3.1.
154 bool active;
155 std::vector<ShaderVariable> fields;
156 std::string structName;
157
158 // Only applies to interface block fields. Kept here for simplicity.
159 bool isRowMajorLayout;
160
161 // VariableWithLocation
162 int location;
163
164 // Uniform
165 int binding;
166 // Decide whether two uniforms are the same at shader link time,
167 // assuming one from vertex shader and the other from fragment shader.
168 // GLSL ES Spec 3.00.3, section 4.3.5.
169 // GLSL ES Spec 3.10.4, section 4.4.5
170 bool isSameUniformAtLinkTime(const ShaderVariable &other) const;
171 GLenum imageUnitFormat;
172 int offset;
173 bool readonly;
174 bool writeonly;
175
176 // OutputVariable
177 // From EXT_blend_func_extended.
178 int index;
179
180 // InterfaceBlockField
181 // Decide whether two InterfaceBlock fields are the same at shader
182 // link time, assuming one from vertex shader and the other from
183 // fragment shader.
184 // See GLSL ES Spec 3.00.3, sec 4.3.7.
185 bool isSameInterfaceBlockFieldAtLinkTime(const ShaderVariable &other) const;
186
187 // Varying
188 InterpolationType interpolation;
189 bool isInvariant;
190 // Decide whether two varyings are the same at shader link time,
191 // assuming one from vertex shader and the other from fragment shader.
192 // Invariance needs to match only in ESSL1. Relevant spec sections:
193 // GLSL ES 3.00.4, sections 4.6.1 and 4.3.9.
194 // GLSL ES 1.00.17, section 4.6.4.
195 bool isSameVaryingAtLinkTime(const ShaderVariable &other, int shaderVersion) const;
196 // Deprecated version of isSameVaryingAtLinkTime, which assumes ESSL1.
197 bool isSameVaryingAtLinkTime(const ShaderVariable &other) const;
198
199 protected:
200 bool isSameVariableAtLinkTime(const ShaderVariable &other,
201 bool matchPrecision,
202 bool matchName) const;
203
204 int flattenedOffsetInParentArrays;
205 };
206
207 // TODO: anglebug.com/3899
208 // For backwards compatibility for other codebases (e.g., chromium/src/gpu/command_buffer/service)
209 using Uniform = ShaderVariable;
210 using Attribute = ShaderVariable;
211 using OutputVariable = ShaderVariable;
212 using InterfaceBlockField = ShaderVariable;
213 using Varying = ShaderVariable;
214
215 struct InterfaceBlock
216 {
217 InterfaceBlock();
218 ~InterfaceBlock();
219 InterfaceBlock(const InterfaceBlock &other);
220 InterfaceBlock &operator=(const InterfaceBlock &other);
221
222 // Fields from blocks with non-empty instance names are prefixed with the block name.
223 std::string fieldPrefix() const;
224 std::string fieldMappedPrefix() const;
225
226 // Decide whether two interface blocks are the same at shader link time.
227 bool isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const;
228
229 bool isBuiltIn() const;
230
isArrayInterfaceBlock231 bool isArray() const { return arraySize > 0; }
elementCountInterfaceBlock232 unsigned int elementCount() const { return std::max(1u, arraySize); }
233
234 std::string name;
235 std::string mappedName;
236 std::string instanceName;
237 unsigned int arraySize;
238 BlockLayoutType layout;
239
240 // Deprecated. Matrix packing should only be queried from individual fields of the block.
241 // TODO(oetuaho): Remove this once it is no longer used in Chromium.
242 bool isRowMajorLayout;
243
244 int binding;
245 bool staticUse;
246 bool active;
247 BlockType blockType;
248 std::vector<ShaderVariable> fields;
249 };
250
251 struct WorkGroupSize
252 {
253 // Must have a trivial default constructor since it is used in YYSTYPE.
254 inline WorkGroupSize() = default;
255 inline explicit constexpr WorkGroupSize(int initialSize);
256
257 void fill(int fillValue);
258 void setLocalSize(int localSizeX, int localSizeY, int localSizeZ);
259
260 int &operator[](size_t index);
261 int operator[](size_t index) const;
262 size_t size() const;
263
264 // Checks whether two work group size declarations match.
265 // Two work group size declarations are the same if the explicitly specified elements are the
266 // same or if one of them is specified as one and the other one is not specified
267 bool isWorkGroupSizeMatching(const WorkGroupSize &right) const;
268
269 // Checks whether any of the values are set.
270 bool isAnyValueSet() const;
271
272 // Checks whether all of the values are set.
273 bool isDeclared() const;
274
275 // Checks whether either all of the values are set, or none of them are.
276 bool isLocalSizeValid() const;
277
278 int localSizeQualifiers[3];
279 };
280
WorkGroupSize(int initialSize)281 inline constexpr WorkGroupSize::WorkGroupSize(int initialSize)
282 : localSizeQualifiers{initialSize, initialSize, initialSize}
283 {}
284
285 } // namespace sh
286
287 #endif // GLSLANG_SHADERVARS_H_
288