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