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