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