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