• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 };
33 
34 // Validate link & SSO consistency of interpolation qualifiers
35 bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
36 
37 // Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
38 enum 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
48 enum 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(jiawei.shao@intel.com): 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
62 struct 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 
isArrayOfArraysShaderVariable71     bool isArrayOfArrays() const { return arraySizes.size() >= 2u; }
isArrayShaderVariable72     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.
getOutermostArraySizeShaderVariable83     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 
isStructShaderVariable100     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.
parentArrayIndexShaderVariable134     int parentArrayIndex() const
135     {
136         return hasParentArrayIndex() ? flattenedOffsetInParentArrays : 0;
137     }
138 
setParentArrayIndexShaderVariable139     void setParentArrayIndex(int index) { flattenedOffsetInParentArrays = index; }
140 
hasParentArrayIndexShaderVariable141     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.
168 struct 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 
180 struct 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 
202 struct 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 
212 struct 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 
225 struct 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 
241 struct 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 
264 struct 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 
isArrayInterfaceBlock280     bool isArray() const { return arraySize > 0; }
elementCountInterfaceBlock281     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 
300 struct 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 
WorkGroupSize(int initialSize)330 inline constexpr WorkGroupSize::WorkGroupSize(int initialSize)
331     : localSizeQualifiers{initialSize, initialSize, initialSize}
332 {}
333 
334 }  // namespace sh
335 
336 #endif  // GLSLANG_SHADERVARS_H_
337