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