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