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