• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 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 
7 // Program.h: Defines the gl::Program class. Implements GL program objects
8 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9 
10 #ifndef LIBANGLE_PROGRAM_H_
11 #define LIBANGLE_PROGRAM_H_
12 
13 #include <GLES2/gl2.h>
14 #include <GLSLANG/ShaderVars.h>
15 
16 #include <array>
17 #include <map>
18 #include <set>
19 #include <sstream>
20 #include <string>
21 #include <vector>
22 
23 #include "common/Optional.h"
24 #include "common/angleutils.h"
25 #include "common/mathutil.h"
26 #include "common/utilities.h"
27 
28 #include "libANGLE/Constants.h"
29 #include "libANGLE/Debug.h"
30 #include "libANGLE/Error.h"
31 #include "libANGLE/InfoLog.h"
32 #include "libANGLE/ProgramExecutable.h"
33 #include "libANGLE/ProgramLinkedResources.h"
34 #include "libANGLE/RefCountObject.h"
35 #include "libANGLE/Uniform.h"
36 #include "libANGLE/angletypes.h"
37 
38 namespace rx
39 {
40 class GLImplFactory;
41 class ProgramImpl;
42 struct TranslatedAttribute;
43 }  // namespace rx
44 
45 namespace gl
46 {
47 class Buffer;
48 class BinaryInputStream;
49 class BinaryOutputStream;
50 struct Caps;
51 class Context;
52 struct Extensions;
53 class Framebuffer;
54 class Shader;
55 class ShaderProgramManager;
56 class State;
57 struct UnusedUniform;
58 struct Version;
59 
60 extern const char *const g_fakepath;
61 
62 enum class LinkMismatchError
63 {
64     // Shared
65     NO_MISMATCH,
66     TYPE_MISMATCH,
67     ARRAY_SIZE_MISMATCH,
68     PRECISION_MISMATCH,
69     STRUCT_NAME_MISMATCH,
70     FIELD_NUMBER_MISMATCH,
71     FIELD_NAME_MISMATCH,
72 
73     // Varying specific
74     INTERPOLATION_TYPE_MISMATCH,
75     INVARIANCE_MISMATCH,
76 
77     // Uniform specific
78     BINDING_MISMATCH,
79     LOCATION_MISMATCH,
80     OFFSET_MISMATCH,
81     INSTANCE_NAME_MISMATCH,
82     FORMAT_MISMATCH,
83 
84     // Interface block specific
85     LAYOUT_QUALIFIER_MISMATCH,
86     MATRIX_PACKING_MISMATCH,
87 };
88 
89 void LogLinkMismatch(InfoLog &infoLog,
90                      const std::string &variableName,
91                      const char *variableType,
92                      LinkMismatchError linkError,
93                      const std::string &mismatchedStructOrBlockFieldName,
94                      ShaderType shaderType1,
95                      ShaderType shaderType2);
96 
97 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock);
98 
99 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var);
100 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var);
101 
102 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var);
103 void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var);
104 
105 // Struct used for correlating uniforms/elements of uniform arrays to handles
106 struct VariableLocation
107 {
108     static constexpr unsigned int kUnused = GL_INVALID_INDEX;
109 
110     VariableLocation();
111     VariableLocation(unsigned int arrayIndex, unsigned int index);
112 
113     // If used is false, it means this location is only used to fill an empty space in an array,
114     // and there is no corresponding uniform variable for this location. It can also mean the
115     // uniform was optimized out by the implementation.
usedVariableLocation116     bool used() const { return (index != kUnused); }
markUnusedVariableLocation117     void markUnused() { index = kUnused; }
markIgnoredVariableLocation118     void markIgnored() { ignored = true; }
119 
120     bool operator==(const VariableLocation &other) const
121     {
122         return arrayIndex == other.arrayIndex && index == other.index;
123     }
124 
125     // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays.
126     unsigned int arrayIndex;
127     // "index" is an index of the variable. The variable contains the indices for other than the
128     // innermost GLSL arrays.
129     unsigned int index;
130 
131     // If this location was bound to an unreferenced uniform.  Setting data on this uniform is a
132     // no-op.
133     bool ignored;
134 };
135 
136 // Information about a variable binding.
137 // Currently used by CHROMIUM_path_rendering
138 struct BindingInfo
139 {
140     // The type of binding, for example GL_FLOAT_VEC3.
141     // This can be GL_NONE if the variable is optimized away.
142     GLenum type;
143 
144     // This is the name of the variable in
145     // the translated shader program. Note that
146     // this can be empty in the case where the
147     // variable has been optimized away.
148     std::string name;
149 
150     // True if the binding is valid, otherwise false.
151     bool valid;
152 };
153 
154 // A varying with tranform feedback enabled. If it's an array, either the whole array or one of its
155 // elements specified by 'arrayIndex' can set to be enabled.
156 struct TransformFeedbackVarying : public sh::ShaderVariable
157 {
TransformFeedbackVaryingTransformFeedbackVarying158     TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
159         : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
160     {
161         ASSERT(!isArrayOfArrays());
162     }
163 
TransformFeedbackVaryingTransformFeedbackVarying164     TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
165         : arrayIndex(GL_INVALID_INDEX)
166     {
167         sh::ShaderVariable *thisVar = this;
168         *thisVar                    = field;
169         interpolation               = parent.interpolation;
170         isInvariant                 = parent.isInvariant;
171         name                        = parent.name + "." + name;
172         mappedName                  = parent.mappedName + "." + mappedName;
173     }
174 
nameWithArrayIndexTransformFeedbackVarying175     std::string nameWithArrayIndex() const
176     {
177         std::stringstream fullNameStr;
178         fullNameStr << name;
179         if (arrayIndex != GL_INVALID_INDEX)
180         {
181             fullNameStr << "[" << arrayIndex << "]";
182         }
183         return fullNameStr.str();
184     }
sizeTransformFeedbackVarying185     GLsizei size() const
186     {
187         return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
188     }
189 
190     GLuint arrayIndex;
191 };
192 
193 struct ProgramBinding
194 {
ProgramBindingProgramBinding195     ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
ProgramBindingProgramBinding196     ProgramBinding(GLuint index) : location(index), aliased(false) {}
197 
198     GLuint location;
199     // Whether another binding was set that may potentially alias this.
200     bool aliased;
201 };
202 
203 class ProgramBindings final : angle::NonCopyable
204 {
205   public:
206     ProgramBindings();
207     ~ProgramBindings();
208 
209     void bindLocation(GLuint index, const std::string &name);
210     int getBindingByName(const std::string &name) const;
211     int getBinding(const sh::ShaderVariable &variable) const;
212 
213     using const_iterator = std::unordered_map<std::string, GLuint>::const_iterator;
214     const_iterator begin() const;
215     const_iterator end() const;
216 
217   private:
218     std::unordered_map<std::string, GLuint> mBindings;
219 };
220 
221 // Uniforms and Fragment Outputs require special treatment due to array notation (e.g., "[0]")
222 class ProgramAliasedBindings final : angle::NonCopyable
223 {
224   public:
225     ProgramAliasedBindings();
226     ~ProgramAliasedBindings();
227 
228     void bindLocation(GLuint index, const std::string &name);
229     int getBindingByName(const std::string &name) const;
230     int getBindingByLocation(GLuint location) const;
231     int getBinding(const sh::ShaderVariable &variable) const;
232 
233     using const_iterator = std::unordered_map<std::string, ProgramBinding>::const_iterator;
234     const_iterator begin() const;
235     const_iterator end() const;
236 
237   private:
238     std::unordered_map<std::string, ProgramBinding> mBindings;
239 };
240 
241 class ProgramState final : angle::NonCopyable
242 {
243   public:
244     ProgramState();
245     ~ProgramState();
246 
247     const std::string &getLabel();
248 
249     Shader *getAttachedShader(ShaderType shaderType) const;
getAttachedShaders()250     const gl::ShaderMap<Shader *> &getAttachedShaders() const { return mAttachedShaders; }
getTransformFeedbackVaryingNames()251     const std::vector<std::string> &getTransformFeedbackVaryingNames() const
252     {
253         return mTransformFeedbackVaryingNames;
254     }
getTransformFeedbackBufferMode()255     GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
getUniformBlockBinding(GLuint uniformBlockIndex)256     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
257     {
258         ASSERT(uniformBlockIndex < mUniformBlocks.size());
259         return mUniformBlocks[uniformBlockIndex].binding;
260     }
getShaderStorageBlockBinding(GLuint blockIndex)261     GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
262     {
263         ASSERT(blockIndex < mShaderStorageBlocks.size());
264         return mShaderStorageBlocks[blockIndex].binding;
265     }
getActiveUniformBlockBindingsMask()266     const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
267     {
268         return mActiveUniformBlockBindings;
269     }
getProgramInputs()270     const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
getActiveOutputVariables()271     DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
getOutputVariables()272     const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; }
getOutputLocations()273     const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
getSecondaryOutputLocations()274     const std::vector<VariableLocation> &getSecondaryOutputLocations() const
275     {
276         return mSecondaryOutputLocations;
277     }
getUniforms()278     const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
getUniformLocations()279     const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
getUniformBlocks()280     const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
getShaderStorageBlocks()281     const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
282     {
283         return mShaderStorageBlocks;
284     }
getBufferVariables()285     const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
getSamplerBindings()286     const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
getImageBindings()287     const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
getComputeShaderLocalSize()288     const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
getDefaultUniformRange()289     const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; }
getSamplerUniformRange()290     const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
getImageUniformRange()291     const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
getAtomicCounterUniformRange()292     const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
293 
getLinkedTransformFeedbackVaryings()294     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
295     {
296         return mLinkedTransformFeedbackVaryings;
297     }
getTransformFeedbackStrides()298     const std::vector<GLsizei> &getTransformFeedbackStrides() const
299     {
300         return mTransformFeedbackStrides;
301     }
getAtomicCounterBuffers()302     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
303     {
304         return mAtomicCounterBuffers;
305     }
306 
307     // Count the number of uniform and storage buffer declarations, counting arrays as one.
308     size_t getTransformFeedbackBufferCount() const;
309 
310     GLuint getUniformIndexFromName(const std::string &name) const;
311     GLuint getUniformIndexFromLocation(UniformLocation location) const;
312     Optional<GLuint> getSamplerIndex(UniformLocation location) const;
313     bool isSamplerUniformIndex(GLuint index) const;
314     GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
315     GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
316     bool isImageUniformIndex(GLuint index) const;
317     GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
318     GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const;
319     GLuint getAttributeLocation(const std::string &name) const;
320 
321     GLuint getBufferVariableIndexFromName(const std::string &name) const;
322 
getNumViews()323     int getNumViews() const { return mNumViews; }
usesMultiview()324     bool usesMultiview() const { return mNumViews != -1; }
325 
326     bool hasAttachedShader() const;
327 
328     ShaderType getFirstAttachedShaderStageType() const;
329     ShaderType getLastAttachedShaderStageType() const;
330 
getUniformLocationBindings()331     const ProgramAliasedBindings &getUniformLocationBindings() const
332     {
333         return mUniformLocationBindings;
334     }
335 
getProgramExecutable()336     const ProgramExecutable &getProgramExecutable() const { return mExecutable; }
getProgramExecutable()337     ProgramExecutable &getProgramExecutable() { return mExecutable; }
338 
hasDefaultUniforms()339     bool hasDefaultUniforms() const { return !getDefaultUniformRange().empty(); }
hasTextures()340     bool hasTextures() const { return !getSamplerBindings().empty(); }
hasUniformBuffers()341     bool hasUniformBuffers() const { return !getUniformBlocks().empty(); }
hasStorageBuffers()342     bool hasStorageBuffers() const { return !getShaderStorageBlocks().empty(); }
hasAtomicCounterBuffers()343     bool hasAtomicCounterBuffers() const { return !getAtomicCounterBuffers().empty(); }
hasImages()344     bool hasImages() const { return !getImageBindings().empty(); }
hasTransformFeedbackOutput()345     bool hasTransformFeedbackOutput() const
346     {
347         return !getLinkedTransformFeedbackVaryings().empty();
348     }
hasEarlyFragmentTestsOptimization()349     bool hasEarlyFragmentTestsOptimization() const { return mEarlyFramentTestsOptimization; }
350 
isShaderMarkedForDetach(gl::ShaderType shaderType)351     bool isShaderMarkedForDetach(gl::ShaderType shaderType) const
352     {
353         return mAttachedShadersMarkedForDetach[shaderType];
354     }
355 
356   private:
357     friend class MemoryProgramCache;
358     friend class Program;
359 
360     void updateTransformFeedbackStrides();
361     void updateActiveSamplers();
362     void updateActiveImages();
363     void updateProgramInterfaceInputs();
364     void updateProgramInterfaceOutputs();
365 
366     // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
367     void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex);
368 
369     std::string mLabel;
370 
371     sh::WorkGroupSize mComputeShaderLocalSize;
372 
373     ShaderMap<Shader *> mAttachedShaders;
374     ShaderMap<bool> mAttachedShadersMarkedForDetach;
375 
376     uint32_t mLocationsUsedForXfbExtension;
377     std::vector<std::string> mTransformFeedbackVaryingNames;
378     std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
379     GLenum mTransformFeedbackBufferMode;
380 
381     // For faster iteration on the blocks currently being bound.
382     UniformBlockBindingMask mActiveUniformBlockBindings;
383 
384     // Vertex attributes, Fragment input varyings, etc.
385     std::vector<sh::ShaderVariable> mProgramInputs;
386 
387     // Uniforms are sorted in order:
388     //  1. Non-opaque uniforms
389     //  2. Sampler uniforms
390     //  3. Image uniforms
391     //  4. Atomic counter uniforms
392     //  5. Uniform block uniforms
393     // This makes opaque uniform validation easier, since we don't need a separate list.
394     // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
395     // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
396     // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
397     // [0] in the end. This makes implementation of queries simpler.
398     std::vector<LinkedUniform> mUniforms;
399 
400     std::vector<VariableLocation> mUniformLocations;
401     std::vector<InterfaceBlock> mUniformBlocks;
402     std::vector<BufferVariable> mBufferVariables;
403     std::vector<InterfaceBlock> mShaderStorageBlocks;
404     std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
405     RangeUI mDefaultUniformRange;
406     RangeUI mSamplerUniformRange;
407     RangeUI mImageUniformRange;
408     RangeUI mAtomicCounterUniformRange;
409 
410     // An array of the samplers that are used by the program
411     std::vector<SamplerBinding> mSamplerBindings;
412 
413     // An array of the images that are used by the program
414     std::vector<ImageBinding> mImageBindings;
415 
416     // Names and mapped names of output variables that are arrays include [0] in the end, similarly
417     // to uniforms.
418     std::vector<sh::ShaderVariable> mOutputVariables;
419     std::vector<VariableLocation> mOutputLocations;
420 
421     // EXT_blend_func_extended secondary outputs (ones with index 1) in ESSL 3.00 shaders.
422     std::vector<VariableLocation> mSecondaryOutputLocations;
423 
424     DrawBufferMask mActiveOutputVariables;
425 
426     // Fragment output variable base types: FLOAT, INT, or UINT.  Ordered by location.
427     std::vector<GLenum> mOutputVariableTypes;
428     ComponentTypeMask mDrawBufferTypeMask;
429 
430     bool mBinaryRetrieveableHint;
431     bool mSeparable;
432     bool mEarlyFramentTestsOptimization;
433 
434     // ANGLE_multiview.
435     int mNumViews;
436 
437     // GL_EXT_geometry_shader.
438     PrimitiveMode mGeometryShaderInputPrimitiveType;
439     PrimitiveMode mGeometryShaderOutputPrimitiveType;
440     int mGeometryShaderInvocations;
441     int mGeometryShaderMaxVertices;
442 
443     // GL_ANGLE_multi_draw
444     int mDrawIDLocation;
445 
446     // GL_ANGLE_base_vertex_base_instance
447     int mBaseVertexLocation;
448     int mBaseInstanceLocation;
449     // Cached value of base vertex and base instance
450     // need to reset them to zero if using non base vertex or base instance draw calls.
451     GLint mCachedBaseVertex;
452     GLuint mCachedBaseInstance;
453 
454     // The size of the data written to each transform feedback buffer per vertex.
455     std::vector<GLsizei> mTransformFeedbackStrides;
456 
457     // Note that this has nothing to do with binding layout qualifiers that can be set for some
458     // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
459     ProgramAliasedBindings mUniformLocationBindings;
460 
461     ProgramExecutable mExecutable;
462 };
463 
464 struct ProgramVaryingRef
465 {
getProgramVaryingRef466     const sh::ShaderVariable *get(ShaderType stage) const
467     {
468         ASSERT(stage == frontShaderStage || stage == backShaderStage);
469         const sh::ShaderVariable *ref = stage == frontShaderStage ? frontShader : backShader;
470         ASSERT(ref);
471         return ref;
472     }
473 
474     const sh::ShaderVariable *frontShader = nullptr;
475     const sh::ShaderVariable *backShader  = nullptr;
476     ShaderType frontShaderStage           = ShaderType::InvalidEnum;
477     ShaderType backShaderStage            = ShaderType::InvalidEnum;
478 };
479 
480 using ProgramMergedVaryings = std::vector<ProgramVaryingRef>;
481 
482 class Program final : angle::NonCopyable, public LabeledObject
483 {
484   public:
485     Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle);
486     void onDestroy(const Context *context);
487 
488     ShaderProgramID id() const;
489 
490     void setLabel(const Context *context, const std::string &label) override;
491     const std::string &getLabel() const override;
492 
getImplementation()493     ANGLE_INLINE rx::ProgramImpl *getImplementation() const
494     {
495         ASSERT(mLinkResolved);
496         return mProgram;
497     }
498 
499     void attachShader(const Context *context, Shader *shader);
500     void detachShader(const Context *context, Shader *shader);
501     int getAttachedShadersCount() const;
502 
503     const Shader *getAttachedShader(ShaderType shaderType) const;
504 
505     void bindAttributeLocation(GLuint index, const char *name);
506     void bindUniformLocation(UniformLocation location, const char *name);
507 
508     // EXT_blend_func_extended
509     void bindFragmentOutputLocation(GLuint index, const char *name);
510     void bindFragmentOutputIndex(GLuint index, const char *name);
511 
512     angle::Result linkMergedVaryings(const Context *context,
513                                      const ProgramMergedVaryings &mergedVaryings);
514 
515     // KHR_parallel_shader_compile
516     // Try to link the program asynchrously. As a result, background threads may be launched to
517     // execute the linking tasks concurrently.
518     angle::Result link(const Context *context);
519 
520     // Peek whether there is any running linking tasks.
521     bool isLinking() const;
522 
isLinked()523     bool isLinked() const
524     {
525         ASSERT(mLinkResolved);
526         return mLinked;
527     }
528 
529     angle::Result loadBinary(const Context *context,
530                              GLenum binaryFormat,
531                              const void *binary,
532                              GLsizei length);
533     angle::Result saveBinary(Context *context,
534                              GLenum *binaryFormat,
535                              void *binary,
536                              GLsizei bufSize,
537                              GLsizei *length) const;
538     GLint getBinaryLength(Context *context) const;
539     void setBinaryRetrievableHint(bool retrievable);
540     bool getBinaryRetrievableHint() const;
541 
542     void setSeparable(bool separable);
543     bool isSeparable() const;
544 
545     void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const;
546 
547     GLuint getAttributeLocation(const std::string &name) const;
548 
549     void getActiveAttribute(GLuint index,
550                             GLsizei bufsize,
551                             GLsizei *length,
552                             GLint *size,
553                             GLenum *type,
554                             GLchar *name) const;
555     GLint getActiveAttributeCount() const;
556     GLint getActiveAttributeMaxLength() const;
557     const std::vector<sh::ShaderVariable> &getAttributes() const;
558 
559     GLint getFragDataLocation(const std::string &name) const;
560     size_t getOutputResourceCount() const;
561     const std::vector<GLenum> &getOutputVariableTypes() const;
getActiveOutputVariables()562     DrawBufferMask getActiveOutputVariables() const
563     {
564         ASSERT(mLinkResolved);
565         return mState.mActiveOutputVariables;
566     }
567 
568     // EXT_blend_func_extended
569     GLint getFragDataIndex(const std::string &name) const;
570 
571     void getActiveUniform(GLuint index,
572                           GLsizei bufsize,
573                           GLsizei *length,
574                           GLint *size,
575                           GLenum *type,
576                           GLchar *name) const;
577     GLint getActiveUniformCount() const;
578     size_t getActiveBufferVariableCount() const;
579     GLint getActiveUniformMaxLength() const;
580     bool isValidUniformLocation(UniformLocation location) const;
581     const LinkedUniform &getUniformByLocation(UniformLocation location) const;
582     const VariableLocation &getUniformLocation(UniformLocation location) const;
583 
getUniformLocations()584     const std::vector<VariableLocation> &getUniformLocations() const
585     {
586         ASSERT(mLinkResolved);
587         return mState.mUniformLocations;
588     }
589 
getUniformByIndex(GLuint index)590     const LinkedUniform &getUniformByIndex(GLuint index) const
591     {
592         ASSERT(mLinkResolved);
593         ASSERT(index < static_cast<size_t>(mState.mUniforms.size()));
594         return mState.mUniforms[index];
595     }
596 
597     const BufferVariable &getBufferVariableByIndex(GLuint index) const;
598 
599     enum SetUniformResult
600     {
601         SamplerChanged,
602         NoSamplerChange,
603     };
604 
605     UniformLocation getUniformLocation(const std::string &name) const;
606     GLuint getUniformIndex(const std::string &name) const;
607     void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v);
608     void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v);
609     void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v);
610     void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v);
611     void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v);
612     void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v);
613     void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v);
614     void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v);
615     void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v);
616     void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v);
617     void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v);
618     void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v);
619     void setUniformMatrix2fv(UniformLocation location,
620                              GLsizei count,
621                              GLboolean transpose,
622                              const GLfloat *value);
623     void setUniformMatrix3fv(UniformLocation location,
624                              GLsizei count,
625                              GLboolean transpose,
626                              const GLfloat *value);
627     void setUniformMatrix4fv(UniformLocation location,
628                              GLsizei count,
629                              GLboolean transpose,
630                              const GLfloat *value);
631     void setUniformMatrix2x3fv(UniformLocation location,
632                                GLsizei count,
633                                GLboolean transpose,
634                                const GLfloat *value);
635     void setUniformMatrix3x2fv(UniformLocation location,
636                                GLsizei count,
637                                GLboolean transpose,
638                                const GLfloat *value);
639     void setUniformMatrix2x4fv(UniformLocation location,
640                                GLsizei count,
641                                GLboolean transpose,
642                                const GLfloat *value);
643     void setUniformMatrix4x2fv(UniformLocation location,
644                                GLsizei count,
645                                GLboolean transpose,
646                                const GLfloat *value);
647     void setUniformMatrix3x4fv(UniformLocation location,
648                                GLsizei count,
649                                GLboolean transpose,
650                                const GLfloat *value);
651     void setUniformMatrix4x3fv(UniformLocation location,
652                                GLsizei count,
653                                GLboolean transpose,
654                                const GLfloat *value);
655 
656     void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const;
657     void getUniformiv(const Context *context, UniformLocation location, GLint *params) const;
658     void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const;
659 
660     void getActiveUniformBlockName(const GLuint blockIndex,
661                                    GLsizei bufSize,
662                                    GLsizei *length,
663                                    GLchar *blockName) const;
664     void getActiveShaderStorageBlockName(const GLuint blockIndex,
665                                          GLsizei bufSize,
666                                          GLsizei *length,
667                                          GLchar *blockName) const;
668 
getActiveUniformBlockCount()669     ANGLE_INLINE GLuint getActiveUniformBlockCount() const
670     {
671         ASSERT(mLinkResolved);
672         return static_cast<GLuint>(mState.mUniformBlocks.size());
673     }
674 
getActiveAtomicCounterBufferCount()675     ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
676     {
677         ASSERT(mLinkResolved);
678         return static_cast<GLuint>(mState.mAtomicCounterBuffers.size());
679     }
680 
getActiveShaderStorageBlockCount()681     ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
682     {
683         ASSERT(mLinkResolved);
684         return static_cast<GLuint>(mState.mShaderStorageBlocks.size());
685     }
686 
687     GLint getActiveUniformBlockMaxNameLength() const;
688     GLint getActiveShaderStorageBlockMaxNameLength() const;
689 
690     GLuint getUniformBlockIndex(const std::string &name) const;
691     GLuint getShaderStorageBlockIndex(const std::string &name) const;
692 
693     void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
694     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
695     GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
696 
697     const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
698     const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const;
699 
700     void setTransformFeedbackVaryings(GLsizei count,
701                                       const GLchar *const *varyings,
702                                       GLenum bufferMode);
703     void getTransformFeedbackVarying(GLuint index,
704                                      GLsizei bufSize,
705                                      GLsizei *length,
706                                      GLsizei *size,
707                                      GLenum *type,
708                                      GLchar *name) const;
709     GLsizei getTransformFeedbackVaryingCount() const;
710     GLsizei getTransformFeedbackVaryingMaxLength() const;
711     GLenum getTransformFeedbackBufferMode() const;
712     GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
713     const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
714 
715     bool hasDrawIDUniform() const;
716     void setDrawIDUniform(GLint drawid);
717 
718     bool hasBaseVertexUniform() const;
719     void setBaseVertexUniform(GLint baseVertex);
720     bool hasBaseInstanceUniform() const;
721     void setBaseInstanceUniform(GLuint baseInstance);
722 
addRef()723     ANGLE_INLINE void addRef()
724     {
725         ASSERT(mLinkResolved);
726         mRefCount++;
727     }
728 
release(const Context * context)729     ANGLE_INLINE void release(const Context *context)
730     {
731         ASSERT(mLinkResolved);
732         mRefCount--;
733 
734         if (mRefCount == 0 && mDeleteStatus)
735         {
736             deleteSelf(context);
737         }
738     }
739 
740     unsigned int getRefCount() const;
isInUse()741     bool isInUse() const { return getRefCount() != 0; }
742     void flagForDeletion();
743     bool isFlaggedForDeletion() const;
744 
745     void validate(const Caps &caps);
validateSamplers(InfoLog * infoLog,const Caps & caps)746     bool validateSamplers(InfoLog *infoLog, const Caps &caps)
747     {
748         // Skip cache if we're using an infolog, so we get the full error.
749         // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
750         if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
751         {
752             return mCachedValidateSamplersResult.value();
753         }
754 
755         return validateSamplersImpl(infoLog, caps);
756     }
757 
758     bool isValidated() const;
759 
getCachedValidateSamplersResult()760     Optional<bool> getCachedValidateSamplersResult() { return mCachedValidateSamplersResult; }
setCachedValidateSamplersResult(bool result)761     void setCachedValidateSamplersResult(bool result) { mCachedValidateSamplersResult = result; }
762 
763     const std::vector<SamplerBinding> &getSamplerBindings() const;
getImageBindings()764     const std::vector<ImageBinding> &getImageBindings() const
765     {
766         ASSERT(mLinkResolved);
767         return mState.mImageBindings;
768     }
769     const sh::WorkGroupSize &getComputeShaderLocalSize() const;
770     PrimitiveMode getGeometryShaderInputPrimitiveType() const;
771     PrimitiveMode getGeometryShaderOutputPrimitiveType() const;
772     GLint getGeometryShaderInvocations() const;
773     GLint getGeometryShaderMaxVertices() const;
774 
getState()775     const ProgramState &getState() const
776     {
777         ASSERT(mLinkResolved);
778         return mState;
779     }
780 
781     static LinkMismatchError LinkValidateVariablesBase(
782         const sh::ShaderVariable &variable1,
783         const sh::ShaderVariable &variable2,
784         bool validatePrecision,
785         bool validateArraySize,
786         std::string *mismatchedStructOrBlockMemberName);
787 
788     GLuint getInputResourceIndex(const GLchar *name) const;
789     GLuint getOutputResourceIndex(const GLchar *name) const;
790     void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
791     void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
792     void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
793     void getBufferVariableResourceName(GLuint index,
794                                        GLsizei bufSize,
795                                        GLsizei *length,
796                                        GLchar *name) const;
797     const sh::ShaderVariable &getInputResource(size_t index) const;
798     GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const;
799     GLuint getInputResourceMaxNameSize() const;
800     GLuint getOutputResourceMaxNameSize() const;
801     GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const;
802     GLuint getInputResourceLocation(const GLchar *name) const;
803     GLuint getOutputResourceLocation(const GLchar *name) const;
804     const std::string getResourceName(const sh::ShaderVariable &resource) const;
805     const std::string getInputResourceName(GLuint index) const;
806     const std::string getOutputResourceName(GLuint index) const;
807     const sh::ShaderVariable &getOutputResource(size_t index) const;
808 
809     const ProgramBindings &getAttributeBindings() const;
810     const ProgramAliasedBindings &getUniformLocationBindings() const;
811     const ProgramAliasedBindings &getFragmentOutputLocations() const;
812     const ProgramAliasedBindings &getFragmentOutputIndexes() const;
813 
getNumViews()814     int getNumViews() const
815     {
816         ASSERT(mLinkResolved);
817         return mState.getNumViews();
818     }
819 
usesMultiview()820     bool usesMultiview() const { return mState.usesMultiview(); }
821 
822     ComponentTypeMask getDrawBufferTypeMask() const;
823 
824     const std::vector<GLsizei> &getTransformFeedbackStrides() const;
825 
826     // Program dirty bits.
827     enum DirtyBitType
828     {
829         DIRTY_BIT_UNIFORM_BLOCK_BINDING_0,
830         DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX =
831             DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS,
832 
833         DIRTY_BIT_COUNT = DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX,
834     };
835 
836     using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
837 
838     angle::Result syncState(const Context *context);
839 
840     // Try to resolve linking. Inlined to make sure its overhead is as low as possible.
resolveLink(const Context * context)841     void resolveLink(const Context *context)
842     {
843         if (!mLinkResolved)
844         {
845             resolveLinkImpl(context);
846         }
847     }
848 
hasAnyDirtyBit()849     ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
850 
getResources()851     gl::ProgramLinkedResources &getResources() const
852     {
853         ASSERT(mResources);
854         return *mResources;
855     }
856 
857     // Writes a program's binary to the output memory buffer.
858     angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
859 
serial()860     rx::Serial serial() const { return mSerial; }
861 
getExecutable()862     const ProgramExecutable &getExecutable() const { return mState.getProgramExecutable(); }
getExecutable()863     ProgramExecutable &getExecutable() { return mState.getProgramExecutable(); }
864 
865     const char *validateDrawStates(const State &state, const gl::Extensions &extensions) const;
866 
867     static void getFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings,
868                                     std::vector<const sh::ShaderVariable *> *filteredVaryingsOut);
869     static bool doShaderVariablesMatch(gl::Shader *generatingShader,
870                                        gl::Shader *consumingShader,
871                                        const sh::ShaderVariable &input,
872                                        const sh::ShaderVariable &output,
873                                        bool validateGeometryShaderInputs,
874                                        bool isSeparable,
875                                        gl::InfoLog &infoLog);
876     static bool linkValidateShaderInterfaceMatching(Shader *generatingShader,
877                                                     Shader *consumingShader,
878                                                     bool isSeparable,
879                                                     InfoLog &infoLog);
880     static bool linkValidateBuiltInVaryings(Shader *vertexShader,
881                                             Shader *fragmentShader,
882                                             InfoLog &infoLog);
883 
884   private:
885     struct LinkingState;
886 
887     ~Program() override;
888 
889     // Loads program state according to the specified binary blob.
890     angle::Result deserialize(const Context *context, BinaryInputStream &stream, InfoLog &infoLog);
891 
892     void unlink();
893     void deleteSelf(const Context *context);
894 
895     bool linkValidateShaders(InfoLog &infoLog);
896     bool linkAttributes(const Context *context, InfoLog &infoLog);
897     bool linkInterfaceBlocks(const Caps &caps,
898                              const Version &version,
899                              bool webglCompatibility,
900                              InfoLog &infoLog,
901                              GLuint *combinedShaderStorageBlocksCount);
902     bool linkVaryings(InfoLog &infoLog) const;
903 
904     bool linkUniforms(const Caps &caps,
905                       const Version &version,
906                       InfoLog &infoLog,
907                       const ProgramAliasedBindings &uniformLocationBindings,
908                       GLuint *combinedImageUniformsCount,
909                       std::vector<UnusedUniform> *unusedUniforms);
910     void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount);
911     bool linkAtomicCounterBuffers();
912 
913     void updateLinkedShaderStages();
914 
915     static LinkMismatchError LinkValidateVaryings(const sh::ShaderVariable &outputVarying,
916                                                   const sh::ShaderVariable &inputVarying,
917                                                   int shaderVersion,
918                                                   bool validateGeometryShaderInputVarying,
919                                                   bool isSeparable,
920                                                   std::string *mismatchedStructFieldName);
921 
922     bool linkValidateTransformFeedback(const Version &version,
923                                        InfoLog &infoLog,
924                                        const ProgramMergedVaryings &linkedVaryings,
925                                        ShaderType stage,
926                                        const Caps &caps) const;
927 
928     void gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings, ShaderType stage);
929 
930     ProgramMergedVaryings getMergedVaryings() const;
931     int getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const;
932     bool isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const;
933     bool linkOutputVariables(const Caps &caps,
934                              const Extensions &extensions,
935                              const Version &version,
936                              GLuint combinedImageUniformsCount,
937                              GLuint combinedShaderStorageBlocksCount);
938 
939     void setUniformValuesFromBindingQualifiers();
940     bool shouldIgnoreUniform(UniformLocation location) const;
941 
942     void initInterfaceBlockBindings();
943 
944     // Both these function update the cached uniform values and return a modified "count"
945     // so that the uniform update doesn't overflow the uniform.
946     template <typename T>
947     GLsizei clampUniformCount(const VariableLocation &locationInfo,
948                               GLsizei count,
949                               int vectorSize,
950                               const T *v);
951     template <size_t cols, size_t rows, typename T>
952     GLsizei clampMatrixUniformCount(UniformLocation location,
953                                     GLsizei count,
954                                     GLboolean transpose,
955                                     const T *v);
956 
957     void updateSamplerUniform(Context *context,
958                               const VariableLocation &locationInfo,
959                               GLsizei clampedCount,
960                               const GLint *v);
961 
962     template <typename DestT>
963     void getUniformInternal(const Context *context,
964                             DestT *dataOut,
965                             UniformLocation location,
966                             GLenum nativeType,
967                             int components) const;
968 
969     void getResourceName(const std::string name,
970                          GLsizei bufSize,
971                          GLsizei *length,
972                          GLchar *dest) const;
973 
974     template <typename T>
975     GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const;
976 
977     GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
978     GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const;
979 
980     bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps);
981 
982     // Block until linking is finished and resolve it.
983     void resolveLinkImpl(const gl::Context *context);
984 
985     void postResolveLink(const gl::Context *context);
986 
987     rx::Serial mSerial;
988     ProgramState mState;
989     rx::ProgramImpl *mProgram;
990 
991     bool mValidated;
992 
993     ProgramBindings mAttributeBindings;
994 
995     // EXT_blend_func_extended
996     ProgramAliasedBindings mFragmentOutputLocations;
997     ProgramAliasedBindings mFragmentOutputIndexes;
998 
999     bool mLinked;
1000     bool mLinkResolved;
1001     std::unique_ptr<LinkingState> mLinkingState;
1002     bool mDeleteStatus;  // Flag to indicate that the program can be deleted when no longer in use
1003 
1004     unsigned int mRefCount;
1005 
1006     ShaderProgramManager *mResourceManager;
1007     const ShaderProgramID mHandle;
1008 
1009     // Cache for sampler validation
1010     Optional<bool> mCachedValidateSamplersResult;
1011 
1012     DirtyBits mDirtyBits;
1013 
1014     // TODO: http://anglebug.com/4514: Remove
1015     std::unique_ptr<gl::ProgramLinkedResources> mResources;
1016 };
1017 }  // namespace gl
1018 
1019 #endif  // LIBANGLE_PROGRAM_H_
1020