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 ProgramExecutable;
55 class Shader;
56 class ShaderProgramManager;
57 class State;
58 struct UnusedUniform;
59 struct Version;
60 
61 extern const char *const g_fakepath;
62 
63 enum class LinkMismatchError
64 {
65     // Shared
66     NO_MISMATCH,
67     TYPE_MISMATCH,
68     ARRAYNESS_MISMATCH,
69     ARRAY_SIZE_MISMATCH,
70     PRECISION_MISMATCH,
71     STRUCT_NAME_MISMATCH,
72     FIELD_NUMBER_MISMATCH,
73     FIELD_NAME_MISMATCH,
74 
75     // Varying specific
76     INTERPOLATION_TYPE_MISMATCH,
77     INVARIANCE_MISMATCH,
78 
79     // Uniform specific
80     BINDING_MISMATCH,
81     LOCATION_MISMATCH,
82     OFFSET_MISMATCH,
83     INSTANCE_NAME_MISMATCH,
84     FORMAT_MISMATCH,
85 
86     // Interface block specific
87     LAYOUT_QUALIFIER_MISMATCH,
88     MATRIX_PACKING_MISMATCH,
89 
90     // I/O block specific
91     FIELD_LOCATION_MISMATCH,
92     FIELD_STRUCT_NAME_MISMATCH,
93 };
94 
95 void LogLinkMismatch(InfoLog &infoLog,
96                      const std::string &variableName,
97                      const char *variableType,
98                      LinkMismatchError linkError,
99                      const std::string &mismatchedStructOrBlockFieldName,
100                      ShaderType shaderType1,
101                      ShaderType shaderType2);
102 
103 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock);
104 
105 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var);
106 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var);
107 
108 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var);
109 void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var);
110 
111 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block);
112 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block);
113 
114 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var);
115 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var);
116 
117 // Struct used for correlating uniforms/elements of uniform arrays to handles
118 struct VariableLocation
119 {
120     static constexpr unsigned int kUnused = GL_INVALID_INDEX;
121 
122     VariableLocation();
123     VariableLocation(unsigned int arrayIndex, unsigned int index);
124 
125     // If used is false, it means this location is only used to fill an empty space in an array,
126     // and there is no corresponding uniform variable for this location. It can also mean the
127     // uniform was optimized out by the implementation.
usedVariableLocation128     bool used() const { return (index != kUnused); }
markUnusedVariableLocation129     void markUnused() { index = kUnused; }
markIgnoredVariableLocation130     void markIgnored() { ignored = true; }
131 
132     bool operator==(const VariableLocation &other) const
133     {
134         return arrayIndex == other.arrayIndex && index == other.index;
135     }
136 
137     // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays.
138     unsigned int arrayIndex;
139     // "index" is an index of the variable. The variable contains the indices for other than the
140     // innermost GLSL arrays.
141     unsigned int index;
142 
143     // If this location was bound to an unreferenced uniform.  Setting data on this uniform is a
144     // no-op.
145     bool ignored;
146 };
147 
148 // Information about a variable binding.
149 // Currently used by CHROMIUM_path_rendering
150 struct BindingInfo
151 {
152     // The type of binding, for example GL_FLOAT_VEC3.
153     // This can be GL_NONE if the variable is optimized away.
154     GLenum type;
155 
156     // This is the name of the variable in
157     // the translated shader program. Note that
158     // this can be empty in the case where the
159     // variable has been optimized away.
160     std::string name;
161 
162     // True if the binding is valid, otherwise false.
163     bool valid;
164 };
165 
166 struct ProgramBinding
167 {
ProgramBindingProgramBinding168     ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
ProgramBindingProgramBinding169     ProgramBinding(GLuint index) : location(index), aliased(false) {}
170 
171     GLuint location;
172     // Whether another binding was set that may potentially alias this.
173     bool aliased;
174 };
175 
176 class ProgramBindings final : angle::NonCopyable
177 {
178   public:
179     ProgramBindings();
180     ~ProgramBindings();
181 
182     void bindLocation(GLuint index, const std::string &name);
183     int getBindingByName(const std::string &name) const;
184     int getBinding(const sh::ShaderVariable &variable) const;
185 
186     using const_iterator = angle::HashMap<std::string, GLuint>::const_iterator;
187     const_iterator begin() const;
188     const_iterator end() const;
189 
190     std::map<std::string, GLuint> getStableIterationMap() const;
191 
192   private:
193     angle::HashMap<std::string, GLuint> mBindings;
194 };
195 
196 // Uniforms and Fragment Outputs require special treatment due to array notation (e.g., "[0]")
197 class ProgramAliasedBindings final : angle::NonCopyable
198 {
199   public:
200     ProgramAliasedBindings();
201     ~ProgramAliasedBindings();
202 
203     void bindLocation(GLuint index, const std::string &name);
204     int getBindingByName(const std::string &name) const;
205     int getBindingByLocation(GLuint location) const;
206     int getBinding(const sh::ShaderVariable &variable) const;
207 
208     using const_iterator = angle::HashMap<std::string, ProgramBinding>::const_iterator;
209     const_iterator begin() const;
210     const_iterator end() const;
211 
212     std::map<std::string, ProgramBinding> getStableIterationMap() const;
213 
214   private:
215     angle::HashMap<std::string, ProgramBinding> mBindings;
216 };
217 
218 class ProgramState final : angle::NonCopyable
219 {
220   public:
221     ProgramState();
222     ~ProgramState();
223 
224     const std::string &getLabel();
225 
226     Shader *getAttachedShader(ShaderType shaderType) const;
getAttachedShaders()227     const gl::ShaderMap<Shader *> &getAttachedShaders() const { return mAttachedShaders; }
getTransformFeedbackVaryingNames()228     const std::vector<std::string> &getTransformFeedbackVaryingNames() const
229     {
230         return mTransformFeedbackVaryingNames;
231     }
getTransformFeedbackBufferMode()232     GLint getTransformFeedbackBufferMode() const
233     {
234         return mExecutable->getTransformFeedbackBufferMode();
235     }
getUniformBlockBinding(GLuint uniformBlockIndex)236     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
237     {
238         return mExecutable->getUniformBlockBinding(uniformBlockIndex);
239     }
getShaderStorageBlockBinding(GLuint blockIndex)240     GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
241     {
242         return mExecutable->getShaderStorageBlockBinding(blockIndex);
243     }
getActiveUniformBlockBindingsMask()244     const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
245     {
246         return mExecutable->getActiveUniformBlockBindings();
247     }
getProgramInputs()248     const std::vector<sh::ShaderVariable> &getProgramInputs() const
249     {
250         return mExecutable->getProgramInputs();
251     }
getActiveOutputVariables()252     DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
getOutputVariables()253     const std::vector<sh::ShaderVariable> &getOutputVariables() const
254     {
255         return mExecutable->getOutputVariables();
256     }
getOutputLocations()257     const std::vector<VariableLocation> &getOutputLocations() const
258     {
259         return mExecutable->getOutputLocations();
260     }
getSecondaryOutputLocations()261     const std::vector<VariableLocation> &getSecondaryOutputLocations() const
262     {
263         return mExecutable->getSecondaryOutputLocations();
264     }
getUniforms()265     const std::vector<LinkedUniform> &getUniforms() const { return mExecutable->getUniforms(); }
getUniformLocations()266     const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
getUniformBlocks()267     const std::vector<InterfaceBlock> &getUniformBlocks() const
268     {
269         return mExecutable->getUniformBlocks();
270     }
getShaderStorageBlocks()271     const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
272     {
273         return mExecutable->getShaderStorageBlocks();
274     }
getBufferVariables()275     const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
getSamplerBindings()276     const std::vector<SamplerBinding> &getSamplerBindings() const
277     {
278         return mExecutable->getSamplerBindings();
279     }
getImageBindings()280     const std::vector<ImageBinding> &getImageBindings() const
281     {
282         return getExecutable().getImageBindings();
283     }
getComputeShaderLocalSize()284     const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
getDefaultUniformRange()285     const RangeUI &getDefaultUniformRange() const { return mExecutable->getDefaultUniformRange(); }
getSamplerUniformRange()286     const RangeUI &getSamplerUniformRange() const { return mExecutable->getSamplerUniformRange(); }
getImageUniformRange()287     const RangeUI &getImageUniformRange() const { return mExecutable->getImageUniformRange(); }
getAtomicCounterUniformRange()288     const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
getFragmentInoutRange()289     const RangeUI &getFragmentInoutRange() const { return mExecutable->getFragmentInoutRange(); }
290 
getLinkedTransformFeedbackVaryings()291     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
292     {
293         return mExecutable->getLinkedTransformFeedbackVaryings();
294     }
getTransformFeedbackStrides()295     const std::vector<GLsizei> &getTransformFeedbackStrides() const
296     {
297         return mExecutable->getTransformFeedbackStrides();
298     }
getAtomicCounterBuffers()299     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
300     {
301         return mExecutable->getAtomicCounterBuffers();
302     }
303 
304     GLuint getUniformIndexFromName(const std::string &name) const;
305     GLuint getUniformIndexFromLocation(UniformLocation location) const;
306     Optional<GLuint> getSamplerIndex(UniformLocation location) const;
307     bool isSamplerUniformIndex(GLuint index) const;
308     GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
309     GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
310     bool isImageUniformIndex(GLuint index) const;
311     GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
312     GLuint getAttributeLocation(const std::string &name) const;
313 
314     GLuint getBufferVariableIndexFromName(const std::string &name) const;
315 
getNumViews()316     int getNumViews() const { return mNumViews; }
usesMultiview()317     bool usesMultiview() const { return mNumViews != -1; }
318 
319     bool hasAttachedShader() const;
320 
321     ShaderType getFirstAttachedShaderStageType() const;
322     ShaderType getLastAttachedShaderStageType() const;
323 
getUniformLocationBindings()324     const ProgramAliasedBindings &getUniformLocationBindings() const
325     {
326         return mUniformLocationBindings;
327     }
328 
getExecutable()329     const ProgramExecutable &getExecutable() const
330     {
331         ASSERT(mExecutable);
332         return *mExecutable;
333     }
getExecutable()334     ProgramExecutable &getExecutable()
335     {
336         ASSERT(mExecutable);
337         return *mExecutable;
338     }
339 
hasImages()340     bool hasImages() const { return !getImageBindings().empty(); }
hasEarlyFragmentTestsOptimization()341     bool hasEarlyFragmentTestsOptimization() const { return mEarlyFramentTestsOptimization; }
getSpecConstUsageBits()342     rx::SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; }
343 
344     // A Program can only either be graphics or compute, but never both, so it
345     // can answer isCompute() based on which shaders it has.
isCompute()346     bool isCompute() const { return mExecutable->hasLinkedShaderStage(ShaderType::Compute); }
347 
getLabel()348     const std::string &getLabel() const { return mLabel; }
349 
getLocationsUsedForXfbExtension()350     uint32_t getLocationsUsedForXfbExtension() const { return mLocationsUsedForXfbExtension; }
351 
getOutputVariableTypes()352     const std::vector<GLenum> &getOutputVariableTypes() const { return mOutputVariableTypes; }
353 
getDrawBufferTypeMask()354     ComponentTypeMask getDrawBufferTypeMask() const { return mDrawBufferTypeMask; }
355 
isYUVOutput()356     bool isYUVOutput() const { return mYUVOutput; }
357 
hasBinaryRetrieveableHint()358     bool hasBinaryRetrieveableHint() const { return mBinaryRetrieveableHint; }
359 
isSeparable()360     bool isSeparable() const { return mSeparable; }
361 
getDrawIDLocation()362     int getDrawIDLocation() const { return mDrawIDLocation; }
363 
getBaseVertexLocation()364     int getBaseVertexLocation() const { return mBaseVertexLocation; }
365 
getBaseInstanceLocation()366     int getBaseInstanceLocation() const { return mBaseInstanceLocation; }
367 
368     ShaderType getAttachedTransformFeedbackStage() const;
369 
370   private:
371     friend class MemoryProgramCache;
372     friend class Program;
373 
374     void updateActiveSamplers();
375     void updateProgramInterfaceInputs();
376     void updateProgramInterfaceOutputs();
377 
378     // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
379     void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex);
380 
381     std::string mLabel;
382 
383     sh::WorkGroupSize mComputeShaderLocalSize;
384 
385     ShaderMap<Shader *> mAttachedShaders;
386 
387     uint32_t mLocationsUsedForXfbExtension;
388     std::vector<std::string> mTransformFeedbackVaryingNames;
389 
390     std::vector<VariableLocation> mUniformLocations;
391     std::vector<BufferVariable> mBufferVariables;
392     RangeUI mAtomicCounterUniformRange;
393 
394     DrawBufferMask mActiveOutputVariables;
395 
396     // Fragment output variable base types: FLOAT, INT, or UINT.  Ordered by location.
397     std::vector<GLenum> mOutputVariableTypes;
398     ComponentTypeMask mDrawBufferTypeMask;
399 
400     // GL_EXT_YUV_target. YUV output shaders can only have one ouput and can only write to YUV
401     // framebuffers.
402     bool mYUVOutput;
403 
404     bool mBinaryRetrieveableHint;
405     bool mSeparable;
406     bool mEarlyFramentTestsOptimization;
407     rx::SpecConstUsageBits mSpecConstUsageBits;
408 
409     // ANGLE_multiview.
410     int mNumViews;
411 
412     // GL_ANGLE_multi_draw
413     int mDrawIDLocation;
414 
415     // GL_ANGLE_base_vertex_base_instance
416     int mBaseVertexLocation;
417     int mBaseInstanceLocation;
418     // Cached value of base vertex and base instance
419     // need to reset them to zero if using non base vertex or base instance draw calls.
420     GLint mCachedBaseVertex;
421     GLuint mCachedBaseInstance;
422 
423     // Note that this has nothing to do with binding layout qualifiers that can be set for some
424     // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
425     ProgramAliasedBindings mUniformLocationBindings;
426 
427     std::shared_ptr<ProgramExecutable> mExecutable;
428 };
429 
430 struct ProgramVaryingRef
431 {
getProgramVaryingRef432     const sh::ShaderVariable *get(ShaderType stage) const
433     {
434         ASSERT(stage == frontShaderStage || stage == backShaderStage);
435         const sh::ShaderVariable *ref = stage == frontShaderStage ? frontShader : backShader;
436         ASSERT(ref);
437         return ref;
438     }
439 
440     const sh::ShaderVariable *frontShader = nullptr;
441     const sh::ShaderVariable *backShader  = nullptr;
442     ShaderType frontShaderStage           = ShaderType::InvalidEnum;
443     ShaderType backShaderStage            = ShaderType::InvalidEnum;
444 };
445 
446 using ProgramMergedVaryings = std::vector<ProgramVaryingRef>;
447 
448 // TODO: Copy necessary shader state into Program. http://anglebug.com/5506
449 class HasAttachedShaders
450 {
451   public:
452     virtual Shader *getAttachedShader(ShaderType shaderType) const = 0;
453 
454     ShaderType getTransformFeedbackStage() const;
455 
456   protected:
~HasAttachedShaders()457     virtual ~HasAttachedShaders() {}
458 };
459 
460 class Program final : public LabeledObject, public angle::Subject, public HasAttachedShaders
461 {
462   public:
463     Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle);
464     void onDestroy(const Context *context);
465 
466     ShaderProgramID id() const;
467 
468     void setLabel(const Context *context, const std::string &label) override;
469     const std::string &getLabel() const override;
470 
getImplementation()471     ANGLE_INLINE rx::ProgramImpl *getImplementation() const
472     {
473         ASSERT(!mLinkingState);
474         return mProgram;
475     }
476 
477     void attachShader(Shader *shader);
478     void detachShader(const Context *context, Shader *shader);
479     int getAttachedShadersCount() const;
480 
481     // HasAttachedShaders implementation
482     Shader *getAttachedShader(ShaderType shaderType) const override;
483 
484     void bindAttributeLocation(GLuint index, const char *name);
485     void bindUniformLocation(UniformLocation location, const char *name);
486 
487     // EXT_blend_func_extended
488     void bindFragmentOutputLocation(GLuint index, const char *name);
489     void bindFragmentOutputIndex(GLuint index, const char *name);
490 
491     // KHR_parallel_shader_compile
492     // Try to link the program asynchrously. As a result, background threads may be launched to
493     // execute the linking tasks concurrently.
494     angle::Result link(const Context *context);
495 
496     // Peek whether there is any running linking tasks.
497     bool isLinking() const;
hasLinkingState()498     bool hasLinkingState() const { return mLinkingState != nullptr; }
499 
isLinked()500     bool isLinked() const
501     {
502         ASSERT(!mLinkingState);
503         return mLinked;
504     }
505 
506     angle::Result loadBinary(const Context *context,
507                              GLenum binaryFormat,
508                              const void *binary,
509                              GLsizei length);
510     angle::Result saveBinary(Context *context,
511                              GLenum *binaryFormat,
512                              void *binary,
513                              GLsizei bufSize,
514                              GLsizei *length) const;
515     GLint getBinaryLength(Context *context) const;
516     void setBinaryRetrievableHint(bool retrievable);
517     bool getBinaryRetrievableHint() const;
518 
519     void setSeparable(bool separable);
520     bool isSeparable() const;
521 
522     void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const;
523 
524     GLuint getAttributeLocation(const std::string &name) const;
525 
526     void getActiveAttribute(GLuint index,
527                             GLsizei bufsize,
528                             GLsizei *length,
529                             GLint *size,
530                             GLenum *type,
531                             GLchar *name) const;
532     GLint getActiveAttributeCount() const;
533     GLint getActiveAttributeMaxLength() const;
534     const std::vector<sh::ShaderVariable> &getAttributes() const;
535 
536     GLint getFragDataLocation(const std::string &name) const;
537     size_t getOutputResourceCount() const;
538     const std::vector<GLenum> &getOutputVariableTypes() const;
getActiveOutputVariables()539     DrawBufferMask getActiveOutputVariables() const
540     {
541         ASSERT(!mLinkingState);
542         return mState.mActiveOutputVariables;
543     }
544 
545     // EXT_blend_func_extended
546     GLint getFragDataIndex(const std::string &name) const;
547 
548     void getActiveUniform(GLuint index,
549                           GLsizei bufsize,
550                           GLsizei *length,
551                           GLint *size,
552                           GLenum *type,
553                           GLchar *name) const;
554     GLint getActiveUniformCount() const;
555     size_t getActiveBufferVariableCount() const;
556     GLint getActiveUniformMaxLength() const;
557     bool isValidUniformLocation(UniformLocation location) const;
558     const LinkedUniform &getUniformByLocation(UniformLocation location) const;
559     const VariableLocation &getUniformLocation(UniformLocation location) const;
560 
getUniformLocations()561     const std::vector<VariableLocation> &getUniformLocations() const
562     {
563         ASSERT(!mLinkingState);
564         return mState.mUniformLocations;
565     }
566 
getUniformByIndex(GLuint index)567     const LinkedUniform &getUniformByIndex(GLuint index) const
568     {
569         ASSERT(!mLinkingState);
570         return mState.mExecutable->getUniformByIndex(index);
571     }
572 
573     const BufferVariable &getBufferVariableByIndex(GLuint index) const;
574 
575     enum SetUniformResult
576     {
577         SamplerChanged,
578         NoSamplerChange,
579     };
580 
581     UniformLocation getUniformLocation(const std::string &name) const;
582     GLuint getUniformIndex(const std::string &name) const;
583     void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v);
584     void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v);
585     void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v);
586     void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v);
587     void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v);
588     void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v);
589     void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v);
590     void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v);
591     void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v);
592     void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v);
593     void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v);
594     void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v);
595     void setUniformMatrix2fv(UniformLocation location,
596                              GLsizei count,
597                              GLboolean transpose,
598                              const GLfloat *value);
599     void setUniformMatrix3fv(UniformLocation location,
600                              GLsizei count,
601                              GLboolean transpose,
602                              const GLfloat *value);
603     void setUniformMatrix4fv(UniformLocation location,
604                              GLsizei count,
605                              GLboolean transpose,
606                              const GLfloat *value);
607     void setUniformMatrix2x3fv(UniformLocation location,
608                                GLsizei count,
609                                GLboolean transpose,
610                                const GLfloat *value);
611     void setUniformMatrix3x2fv(UniformLocation location,
612                                GLsizei count,
613                                GLboolean transpose,
614                                const GLfloat *value);
615     void setUniformMatrix2x4fv(UniformLocation location,
616                                GLsizei count,
617                                GLboolean transpose,
618                                const GLfloat *value);
619     void setUniformMatrix4x2fv(UniformLocation location,
620                                GLsizei count,
621                                GLboolean transpose,
622                                const GLfloat *value);
623     void setUniformMatrix3x4fv(UniformLocation location,
624                                GLsizei count,
625                                GLboolean transpose,
626                                const GLfloat *value);
627     void setUniformMatrix4x3fv(UniformLocation location,
628                                GLsizei count,
629                                GLboolean transpose,
630                                const GLfloat *value);
631 
632     void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const;
633     void getUniformiv(const Context *context, UniformLocation location, GLint *params) const;
634     void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const;
635 
636     void getActiveUniformBlockName(const UniformBlockIndex blockIndex,
637                                    GLsizei bufSize,
638                                    GLsizei *length,
639                                    GLchar *blockName) const;
640     void getActiveShaderStorageBlockName(const GLuint blockIndex,
641                                          GLsizei bufSize,
642                                          GLsizei *length,
643                                          GLchar *blockName) const;
644 
getActiveUniformBlockCount()645     ANGLE_INLINE GLuint getActiveUniformBlockCount() const
646     {
647         ASSERT(!mLinkingState);
648         return static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount());
649     }
650 
getActiveAtomicCounterBufferCount()651     ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
652     {
653         ASSERT(!mLinkingState);
654         return static_cast<GLuint>(mState.mExecutable->getActiveAtomicCounterBufferCount());
655     }
656 
getActiveShaderStorageBlockCount()657     ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
658     {
659         ASSERT(!mLinkingState);
660         return static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount());
661     }
662 
663     GLint getActiveUniformBlockMaxNameLength() const;
664     GLint getActiveShaderStorageBlockMaxNameLength() const;
665 
666     GLuint getUniformBlockIndex(const std::string &name) const;
667     GLuint getShaderStorageBlockIndex(const std::string &name) const;
668 
669     void bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding);
670     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
671     GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
672 
673     const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
674     const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const;
675 
676     void setTransformFeedbackVaryings(GLsizei count,
677                                       const GLchar *const *varyings,
678                                       GLenum bufferMode);
679     void getTransformFeedbackVarying(GLuint index,
680                                      GLsizei bufSize,
681                                      GLsizei *length,
682                                      GLsizei *size,
683                                      GLenum *type,
684                                      GLchar *name) const;
685     GLsizei getTransformFeedbackVaryingCount() const;
686     GLsizei getTransformFeedbackVaryingMaxLength() const;
687     GLenum getTransformFeedbackBufferMode() const;
688     GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
689     const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
690 
691     bool hasDrawIDUniform() const;
692     void setDrawIDUniform(GLint drawid);
693 
694     bool hasBaseVertexUniform() const;
695     void setBaseVertexUniform(GLint baseVertex);
696     bool hasBaseInstanceUniform() const;
697     void setBaseInstanceUniform(GLuint baseInstance);
698 
addRef()699     ANGLE_INLINE void addRef()
700     {
701         ASSERT(!mLinkingState);
702         mRefCount++;
703     }
704 
release(const Context * context)705     ANGLE_INLINE void release(const Context *context)
706     {
707         ASSERT(!mLinkingState);
708         mRefCount--;
709 
710         if (mRefCount == 0 && mDeleteStatus)
711         {
712             deleteSelf(context);
713         }
714     }
715 
716     unsigned int getRefCount() const;
isInUse()717     bool isInUse() const { return getRefCount() != 0; }
718     void flagForDeletion();
719     bool isFlaggedForDeletion() const;
720 
721     void validate(const Caps &caps);
722     bool isValidated() const;
723 
getImageBindings()724     const std::vector<ImageBinding> &getImageBindings() const
725     {
726         ASSERT(!mLinkingState);
727         return getExecutable().getImageBindings();
728     }
729     const sh::WorkGroupSize &getComputeShaderLocalSize() const;
730     PrimitiveMode getGeometryShaderInputPrimitiveType() const;
731     PrimitiveMode getGeometryShaderOutputPrimitiveType() const;
732     GLint getGeometryShaderInvocations() const;
733     GLint getGeometryShaderMaxVertices() const;
734 
735     GLint getTessControlShaderVertices() const;
736     GLenum getTessGenMode() const;
737     GLenum getTessGenPointMode() const;
738     GLenum getTessGenSpacing() const;
739     GLenum getTessGenVertexOrder() const;
740 
getState()741     const ProgramState &getState() const
742     {
743         ASSERT(!mLinkingState);
744         return mState;
745     }
746 
747     GLuint getInputResourceIndex(const GLchar *name) const;
748     GLuint getOutputResourceIndex(const GLchar *name) const;
749     void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
750     void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
751     void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
752     void getBufferVariableResourceName(GLuint index,
753                                        GLsizei bufSize,
754                                        GLsizei *length,
755                                        GLchar *name) const;
756     const sh::ShaderVariable &getInputResource(size_t index) const;
757     GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const;
758     GLuint getInputResourceMaxNameSize() const;
759     GLuint getOutputResourceMaxNameSize() const;
760     GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const;
761     GLuint getInputResourceLocation(const GLchar *name) const;
762     GLuint getOutputResourceLocation(const GLchar *name) const;
763     const std::string getResourceName(const sh::ShaderVariable &resource) const;
764     const std::string getInputResourceName(GLuint index) const;
765     const std::string getOutputResourceName(GLuint index) const;
766     const sh::ShaderVariable &getOutputResource(size_t index) const;
767 
768     const ProgramBindings &getAttributeBindings() const;
769     const ProgramAliasedBindings &getUniformLocationBindings() const;
770     const ProgramAliasedBindings &getFragmentOutputLocations() const;
771     const ProgramAliasedBindings &getFragmentOutputIndexes() const;
772 
getNumViews()773     int getNumViews() const
774     {
775         ASSERT(!mLinkingState);
776         return mState.getNumViews();
777     }
778 
usesMultiview()779     bool usesMultiview() const { return mState.usesMultiview(); }
780 
781     ComponentTypeMask getDrawBufferTypeMask() const;
782 
isYUVOutput()783     bool isYUVOutput() const
784     {
785         ASSERT(!mLinkingState);
786         return mState.isYUVOutput();
787     }
788 
789     const std::vector<GLsizei> &getTransformFeedbackStrides() const;
790 
791     // Program dirty bits.
792     enum DirtyBitType
793     {
794         DIRTY_BIT_UNIFORM_BLOCK_BINDING_0,
795         DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX =
796             DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS,
797 
798         DIRTY_BIT_COUNT = DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX,
799     };
800 
801     using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
802 
803     angle::Result syncState(const Context *context);
804 
805     // Try to resolve linking. Inlined to make sure its overhead is as low as possible.
resolveLink(const Context * context)806     void resolveLink(const Context *context)
807     {
808         if (mLinkingState)
809         {
810             resolveLinkImpl(context);
811         }
812     }
813 
hasAnyDirtyBit()814     ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
815 
816     // Writes a program's binary to the output memory buffer.
817     angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
818 
serial()819     rx::Serial serial() const { return mSerial; }
820 
getExecutable()821     const ProgramExecutable &getExecutable() const { return mState.getExecutable(); }
getExecutable()822     ProgramExecutable &getExecutable() { return mState.getExecutable(); }
823 
824   private:
825     struct LinkingState;
826 
827     ~Program() override;
828 
829     // Loads program state according to the specified binary blob.
830     angle::Result deserialize(const Context *context, BinaryInputStream &stream, InfoLog &infoLog);
831 
832     void unlink();
833     void deleteSelf(const Context *context);
834 
835     angle::Result linkImpl(const Context *context);
836 
837     bool linkValidateShaders(InfoLog &infoLog);
838     bool linkAttributes(const Context *context, InfoLog &infoLog);
839     bool linkInterfaceBlocks(const Caps &caps,
840                              const Version &version,
841                              bool webglCompatibility,
842                              InfoLog &infoLog,
843                              GLuint *combinedShaderStorageBlocksCount);
844     bool linkVaryings(InfoLog &infoLog) const;
845 
846     bool linkUniforms(const Caps &caps,
847                       const Version &version,
848                       InfoLog &infoLog,
849                       const ProgramAliasedBindings &uniformLocationBindings,
850                       GLuint *combinedImageUniformsCount,
851                       std::vector<UnusedUniform> *unusedUniforms);
852     void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount);
853     bool linkAtomicCounterBuffers();
854 
855     void updateLinkedShaderStages();
856 
857     int getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const;
858     bool isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const;
859     bool linkOutputVariables(const Caps &caps,
860                              const Extensions &extensions,
861                              const Version &version,
862                              GLuint combinedImageUniformsCount,
863                              GLuint combinedShaderStorageBlocksCount);
864 
865     void setUniformValuesFromBindingQualifiers();
866     bool shouldIgnoreUniform(UniformLocation location) const;
867 
868     void initInterfaceBlockBindings();
869 
870     // Both these function update the cached uniform values and return a modified "count"
871     // so that the uniform update doesn't overflow the uniform.
872     template <typename T>
873     GLsizei clampUniformCount(const VariableLocation &locationInfo,
874                               GLsizei count,
875                               int vectorSize,
876                               const T *v);
877     template <size_t cols, size_t rows, typename T>
878     GLsizei clampMatrixUniformCount(UniformLocation location,
879                                     GLsizei count,
880                                     GLboolean transpose,
881                                     const T *v);
882 
883     void updateSamplerUniform(Context *context,
884                               const VariableLocation &locationInfo,
885                               GLsizei clampedCount,
886                               const GLint *v);
887 
888     template <typename DestT>
889     void getUniformInternal(const Context *context,
890                             DestT *dataOut,
891                             UniformLocation location,
892                             GLenum nativeType,
893                             int components) const;
894 
895     void getResourceName(const std::string name,
896                          GLsizei bufSize,
897                          GLsizei *length,
898                          GLchar *dest) const;
899 
900     template <typename T>
901     GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const;
902 
903     GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
904     GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const;
905 
906     // Block until linking is finished and resolve it.
907     void resolveLinkImpl(const gl::Context *context);
908 
909     void postResolveLink(const gl::Context *context);
910 
911     rx::Serial mSerial;
912     ProgramState mState;
913     rx::ProgramImpl *mProgram;
914 
915     bool mValidated;
916 
917     ProgramBindings mAttributeBindings;
918 
919     // EXT_blend_func_extended
920     ProgramAliasedBindings mFragmentOutputLocations;
921     ProgramAliasedBindings mFragmentOutputIndexes;
922 
923     bool mLinked;
924     std::unique_ptr<LinkingState> mLinkingState;
925     bool mDeleteStatus;  // Flag to indicate that the program can be deleted when no longer in use
926 
927     unsigned int mRefCount;
928 
929     ShaderProgramManager *mResourceManager;
930     const ShaderProgramID mHandle;
931 
932     DirtyBits mDirtyBits;
933 };
934 }  // namespace gl
935 
936 #endif  // LIBANGLE_PROGRAM_H_
937