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