• 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 { return mAtomicCounterUniformRange; }
getFragmentInoutRange()291     const RangeUI &getFragmentInoutRange() const { return mExecutable->getFragmentInoutRange(); }
292 
getLinkedTransformFeedbackVaryings()293     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
294     {
295         return mExecutable->getLinkedTransformFeedbackVaryings();
296     }
getTransformFeedbackStrides()297     const std::vector<GLsizei> &getTransformFeedbackStrides() const
298     {
299         return mExecutable->getTransformFeedbackStrides();
300     }
getAtomicCounterBuffers()301     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
302     {
303         return mExecutable->getAtomicCounterBuffers();
304     }
305 
306     GLuint getUniformIndexFromName(const std::string &name) const;
307     GLuint getUniformIndexFromLocation(UniformLocation location) const;
308     Optional<GLuint> getSamplerIndex(UniformLocation location) const;
309     bool isSamplerUniformIndex(GLuint index) const;
310     GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
311     GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
312     bool isImageUniformIndex(GLuint index) const;
313     GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
314     GLuint getAttributeLocation(const std::string &name) const;
315 
316     GLuint getBufferVariableIndexFromName(const std::string &name) const;
317 
getNumViews()318     int getNumViews() const { return mNumViews; }
usesMultiview()319     bool usesMultiview() const { return mNumViews != -1; }
320 
321     bool hasAttachedShader() const;
322 
323     ShaderType getFirstAttachedShaderStageType() const;
324     ShaderType getLastAttachedShaderStageType() const;
325 
getUniformLocationBindings()326     const ProgramAliasedBindings &getUniformLocationBindings() const
327     {
328         return mUniformLocationBindings;
329     }
330 
getExecutable()331     const ProgramExecutable &getExecutable() const
332     {
333         ASSERT(mExecutable);
334         return *mExecutable;
335     }
getExecutable()336     ProgramExecutable &getExecutable()
337     {
338         ASSERT(mExecutable);
339         return *mExecutable;
340     }
341 
hasImages()342     bool hasImages() const { return !getImageBindings().empty(); }
hasEarlyFragmentTestsOptimization()343     bool hasEarlyFragmentTestsOptimization() const { return mEarlyFramentTestsOptimization; }
getSpecConstUsageBits()344     rx::SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; }
345 
346     // A Program can only either be graphics or compute, but never both, so it
347     // can answer isCompute() based on which shaders it has.
isCompute()348     bool isCompute() const { return mExecutable->hasLinkedShaderStage(ShaderType::Compute); }
349 
getLabel()350     const std::string &getLabel() const { return mLabel; }
351 
getLocationsUsedForXfbExtension()352     uint32_t getLocationsUsedForXfbExtension() const { return mLocationsUsedForXfbExtension; }
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     bool mBinaryRetrieveableHint;
391     bool mSeparable;
392     bool mEarlyFramentTestsOptimization;
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 
633     GLuint getUniformBlockIndex(const std::string &name) const;
634     GLuint getShaderStorageBlockIndex(const std::string &name) const;
635 
636     void bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding);
637     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
638     GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
639 
640     const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
641     const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const;
642 
643     void setTransformFeedbackVaryings(GLsizei count,
644                                       const GLchar *const *varyings,
645                                       GLenum bufferMode);
646     void getTransformFeedbackVarying(GLuint index,
647                                      GLsizei bufSize,
648                                      GLsizei *length,
649                                      GLsizei *size,
650                                      GLenum *type,
651                                      GLchar *name) const;
652     GLsizei getTransformFeedbackVaryingCount() const;
653     GLsizei getTransformFeedbackVaryingMaxLength() const;
654     GLenum getTransformFeedbackBufferMode() const;
655     GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
656     const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
657 
658     bool hasDrawIDUniform() const;
659     void setDrawIDUniform(GLint drawid);
660 
661     bool hasBaseVertexUniform() const;
662     void setBaseVertexUniform(GLint baseVertex);
663     bool hasBaseInstanceUniform() const;
664     void setBaseInstanceUniform(GLuint baseInstance);
665 
addRef()666     ANGLE_INLINE void addRef()
667     {
668         ASSERT(!mLinkingState);
669         mRefCount++;
670     }
671 
release(const Context * context)672     ANGLE_INLINE void release(const Context *context)
673     {
674         ASSERT(!mLinkingState);
675         mRefCount--;
676 
677         if (mRefCount == 0 && mDeleteStatus)
678         {
679             deleteSelf(context);
680         }
681     }
682 
683     unsigned int getRefCount() const;
isInUse()684     bool isInUse() const { return getRefCount() != 0; }
685     void flagForDeletion();
686     bool isFlaggedForDeletion() const;
687 
688     void validate(const Caps &caps);
689     bool isValidated() const;
690 
getImageBindings()691     const std::vector<ImageBinding> &getImageBindings() const
692     {
693         ASSERT(!mLinkingState);
694         return getExecutable().getImageBindings();
695     }
696     const sh::WorkGroupSize &getComputeShaderLocalSize() const;
697     PrimitiveMode getGeometryShaderInputPrimitiveType() const;
698     PrimitiveMode getGeometryShaderOutputPrimitiveType() const;
699     GLint getGeometryShaderInvocations() const;
700     GLint getGeometryShaderMaxVertices() const;
701 
702     GLint getTessControlShaderVertices() const;
703     GLenum getTessGenMode() const;
704     GLenum getTessGenPointMode() const;
705     GLenum getTessGenSpacing() const;
706     GLenum getTessGenVertexOrder() const;
707 
getState()708     const ProgramState &getState() const
709     {
710         ASSERT(!mLinkingState);
711         return mState;
712     }
713 
714     GLuint getInputResourceIndex(const GLchar *name) const;
715     GLuint getOutputResourceIndex(const GLchar *name) const;
716     void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
717     void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
718     void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
719     void getBufferVariableResourceName(GLuint index,
720                                        GLsizei bufSize,
721                                        GLsizei *length,
722                                        GLchar *name) const;
723     const sh::ShaderVariable &getInputResource(size_t index) const;
724     GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const;
725     GLuint getInputResourceMaxNameSize() const;
726     GLuint getOutputResourceMaxNameSize() const;
727     GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const;
728     GLuint getInputResourceLocation(const GLchar *name) const;
729     GLuint getOutputResourceLocation(const GLchar *name) const;
730     const std::string getResourceName(const sh::ShaderVariable &resource) const;
731     const std::string getInputResourceName(GLuint index) const;
732     const std::string getOutputResourceName(GLuint index) const;
733     const sh::ShaderVariable &getOutputResource(size_t index) const;
734 
735     const ProgramBindings &getAttributeBindings() const;
736     const ProgramAliasedBindings &getUniformLocationBindings() const;
737     const ProgramAliasedBindings &getFragmentOutputLocations() const;
738     const ProgramAliasedBindings &getFragmentOutputIndexes() const;
739 
getNumViews()740     int getNumViews() const
741     {
742         ASSERT(!mLinkingState);
743         return mState.getNumViews();
744     }
745 
usesMultiview()746     bool usesMultiview() const { return mState.usesMultiview(); }
747 
748     const std::vector<GLsizei> &getTransformFeedbackStrides() const;
749 
750     // Program dirty bits.
751     enum DirtyBitType
752     {
753         DIRTY_BIT_UNIFORM_BLOCK_BINDING_0,
754         DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX =
755             DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS,
756 
757         DIRTY_BIT_COUNT = DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX,
758     };
759 
760     using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
761 
762     angle::Result syncState(const Context *context);
763 
764     // Try to resolve linking. Inlined to make sure its overhead is as low as possible.
resolveLink(const Context * context)765     void resolveLink(const Context *context)
766     {
767         if (mLinkingState)
768         {
769             resolveLinkImpl(context);
770         }
771     }
772 
hasAnyDirtyBit()773     ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
774 
775     // Writes a program's binary to the output memory buffer.
776     angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
777 
serial()778     rx::Serial serial() const { return mSerial; }
779 
getExecutable()780     const ProgramExecutable &getExecutable() const { return mState.getExecutable(); }
getExecutable()781     ProgramExecutable &getExecutable() { return mState.getExecutable(); }
782 
783   private:
784     struct LinkingState;
785 
786     ~Program() override;
787 
788     // Loads program state according to the specified binary blob.
789     angle::Result deserialize(const Context *context, BinaryInputStream &stream, InfoLog &infoLog);
790 
791     void unlink();
792     void deleteSelf(const Context *context);
793 
794     angle::Result linkImpl(const Context *context);
795 
796     bool linkValidateShaders(InfoLog &infoLog);
797     bool linkAttributes(const Context *context, InfoLog &infoLog);
798     bool linkInterfaceBlocks(const Caps &caps,
799                              const Version &version,
800                              bool webglCompatibility,
801                              InfoLog &infoLog,
802                              GLuint *combinedShaderStorageBlocksCount);
803     bool linkVaryings(InfoLog &infoLog) const;
804 
805     bool linkUniforms(const Caps &caps,
806                       const Version &version,
807                       InfoLog &infoLog,
808                       const ProgramAliasedBindings &uniformLocationBindings,
809                       GLuint *combinedImageUniformsCount,
810                       std::vector<UnusedUniform> *unusedUniforms);
811     void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount);
812     bool linkAtomicCounterBuffers();
813 
814     void updateLinkedShaderStages();
815 
816     void setUniformValuesFromBindingQualifiers();
817     bool shouldIgnoreUniform(UniformLocation location) const;
818 
819     void initInterfaceBlockBindings();
820 
821     // Both these function update the cached uniform values and return a modified "count"
822     // so that the uniform update doesn't overflow the uniform.
823     template <typename T>
824     GLsizei clampUniformCount(const VariableLocation &locationInfo,
825                               GLsizei count,
826                               int vectorSize,
827                               const T *v);
828     template <size_t cols, size_t rows, typename T>
829     GLsizei clampMatrixUniformCount(UniformLocation location,
830                                     GLsizei count,
831                                     GLboolean transpose,
832                                     const T *v);
833 
834     void updateSamplerUniform(Context *context,
835                               const VariableLocation &locationInfo,
836                               GLsizei clampedCount,
837                               const GLint *v);
838 
839     template <typename DestT>
840     void getUniformInternal(const Context *context,
841                             DestT *dataOut,
842                             UniformLocation location,
843                             GLenum nativeType,
844                             int components) const;
845 
846     void getResourceName(const std::string name,
847                          GLsizei bufSize,
848                          GLsizei *length,
849                          GLchar *dest) const;
850 
851     template <typename T>
852     GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const;
853 
854     GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
855     GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const;
856 
857     // Block until linking is finished and resolve it.
858     void resolveLinkImpl(const gl::Context *context);
859 
860     void postResolveLink(const gl::Context *context);
861 
862     rx::Serial mSerial;
863     ProgramState mState;
864     rx::ProgramImpl *mProgram;
865 
866     bool mValidated;
867 
868     ProgramBindings mAttributeBindings;
869 
870     // EXT_blend_func_extended
871     ProgramAliasedBindings mFragmentOutputLocations;
872     ProgramAliasedBindings mFragmentOutputIndexes;
873 
874     bool mLinked;
875     std::unique_ptr<LinkingState> mLinkingState;
876     bool mDeleteStatus;  // Flag to indicate that the program can be deleted when no longer in use
877 
878     unsigned int mRefCount;
879 
880     ShaderProgramManager *mResourceManager;
881     const ShaderProgramID mHandle;
882 
883     DirtyBits mDirtyBits;
884 };
885 }  // namespace gl
886 
887 #endif  // LIBANGLE_PROGRAM_H_
888