1 //
2 // Copyright (c) 2002-2014 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/angleutils.h"
24 #include "common/mathutil.h"
25 #include "common/Optional.h"
26 
27 #include "libANGLE/Constants.h"
28 #include "libANGLE/Debug.h"
29 #include "libANGLE/Error.h"
30 #include "libANGLE/RefCountObject.h"
31 #include "libANGLE/Uniform.h"
32 #include "libANGLE/angletypes.h"
33 
34 namespace rx
35 {
36 class GLImplFactory;
37 class ProgramImpl;
38 struct TranslatedAttribute;
39 }
40 
41 namespace gl
42 {
43 struct Caps;
44 class Context;
45 class ContextState;
46 class Shader;
47 class ShaderProgramManager;
48 class State;
49 class InfoLog;
50 class Buffer;
51 class Framebuffer;
52 
53 extern const char * const g_fakepath;
54 
55 class InfoLog : angle::NonCopyable
56 {
57   public:
58     InfoLog();
59     ~InfoLog();
60 
61     size_t getLength() const;
62     void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
63 
64     void appendSanitized(const char *message);
65     void reset();
66 
67     // This helper class ensures we append a newline after writing a line.
68     class StreamHelper : angle::NonCopyable
69     {
70       public:
StreamHelper(StreamHelper && rhs)71         StreamHelper(StreamHelper &&rhs)
72             : mStream(rhs.mStream)
73         {
74             rhs.mStream = nullptr;
75         }
76 
77         StreamHelper &operator=(StreamHelper &&rhs)
78         {
79             std::swap(mStream, rhs.mStream);
80             return *this;
81         }
82 
~StreamHelper()83         ~StreamHelper()
84         {
85             // Write newline when destroyed on the stack
86             if (mStream)
87             {
88                 (*mStream) << std::endl;
89             }
90         }
91 
92         template <typename T>
93         StreamHelper &operator<<(const T &value)
94         {
95             (*mStream) << value;
96             return *this;
97         }
98 
99       private:
100         friend class InfoLog;
101 
StreamHelper(std::stringstream * stream)102         StreamHelper(std::stringstream *stream)
103             : mStream(stream)
104         {
105             ASSERT(stream);
106         }
107 
108         std::stringstream *mStream;
109     };
110 
111     template <typename T>
112     StreamHelper operator<<(const T &value)
113     {
114         ensureInitialized();
115         StreamHelper helper(mLazyStream.get());
116         helper << value;
117         return helper;
118     }
119 
str()120     std::string str() const { return mLazyStream ? mLazyStream->str() : ""; }
121 
122   private:
ensureInitialized()123     void ensureInitialized()
124     {
125         if (!mLazyStream)
126         {
127             mLazyStream.reset(new std::stringstream());
128         }
129     }
130 
131     std::unique_ptr<std::stringstream> mLazyStream;
132 };
133 
134 // Struct used for correlating uniforms/elements of uniform arrays to handles
135 struct VariableLocation
136 {
137     static constexpr unsigned int kUnused = GL_INVALID_INDEX;
138 
139     VariableLocation();
140     VariableLocation(unsigned int arrayIndex, unsigned int index);
141 
142     // If used is false, it means this location is only used to fill an empty space in an array,
143     // and there is no corresponding uniform variable for this location. It can also mean the
144     // uniform was optimized out by the implementation.
usedVariableLocation145     bool used() const { return (index != kUnused); }
markUnusedVariableLocation146     void markUnused() { index = kUnused; }
markIgnoredVariableLocation147     void markIgnored() { ignored = true; }
148 
149     // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays.
150     unsigned int arrayIndex;
151     // "index" is an index of the variable. The variable contains the indices for other than the
152     // innermost GLSL arrays.
153     unsigned int index;
154 
155     // If this location was bound to an unreferenced uniform.  Setting data on this uniform is a
156     // no-op.
157     bool ignored;
158 };
159 
160 // Information about a variable binding.
161 // Currently used by CHROMIUM_path_rendering
162 struct BindingInfo
163 {
164     // The type of binding, for example GL_FLOAT_VEC3.
165     // This can be GL_NONE if the variable is optimized away.
166     GLenum type;
167 
168     // This is the name of the variable in
169     // the translated shader program. Note that
170     // this can be empty in the case where the
171     // variable has been optimized away.
172     std::string name;
173 
174     // True if the binding is valid, otherwise false.
175     bool valid;
176 };
177 
178 // This small structure encapsulates binding sampler uniforms to active GL textures.
179 struct SamplerBinding
180 {
181     SamplerBinding(GLenum textureTypeIn, size_t elementCount, bool unreferenced);
182     SamplerBinding(const SamplerBinding &other);
183     ~SamplerBinding();
184 
185     // Necessary for retrieving active textures from the GL state.
186     GLenum textureType;
187 
188     // List of all textures bound to this sampler, of type textureType.
189     std::vector<GLuint> boundTextureUnits;
190 
191     // A note if this sampler is an unreferenced uniform.
192     bool unreferenced;
193 };
194 
195 // A varying with tranform feedback enabled. If it's an array, either the whole array or one of its
196 // elements specified by 'arrayIndex' can set to be enabled.
197 struct TransformFeedbackVarying : public sh::Varying
198 {
TransformFeedbackVaryingTransformFeedbackVarying199     TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index)
200         : sh::Varying(varyingIn), arrayIndex(index)
201     {
202         ASSERT(!isArrayOfArrays());
203     }
nameWithArrayIndexTransformFeedbackVarying204     std::string nameWithArrayIndex() const
205     {
206         std::stringstream fullNameStr;
207         fullNameStr << name;
208         if (arrayIndex != GL_INVALID_INDEX)
209         {
210             fullNameStr << "[" << arrayIndex << "]";
211         }
212         return fullNameStr.str();
213     }
sizeTransformFeedbackVarying214     GLsizei size() const
215     {
216         return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
217     }
218 
219     GLuint arrayIndex;
220 };
221 
222 struct ImageBinding
223 {
224     ImageBinding(size_t count);
225     ImageBinding(GLuint imageUnit, size_t count);
226     ImageBinding(const ImageBinding &other);
227     ~ImageBinding();
228 
229     std::vector<GLuint> boundImageUnits;
230 };
231 
232 using ShaderStagesMask = angle::BitSet<SHADER_TYPE_MAX>;
233 
234 class ProgramState final : angle::NonCopyable
235 {
236   public:
237     ProgramState();
238     ~ProgramState();
239 
240     const std::string &getLabel();
241 
getAttachedVertexShader()242     Shader *getAttachedVertexShader() const { return mAttachedVertexShader; }
getAttachedFragmentShader()243     Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; }
getAttachedComputeShader()244     Shader *getAttachedComputeShader() const { return mAttachedComputeShader; }
getAttachedGeometryShader()245     Shader *getAttachedGeometryShader() const { return mAttachedGeometryShader; }
getTransformFeedbackVaryingNames()246     const std::vector<std::string> &getTransformFeedbackVaryingNames() const
247     {
248         return mTransformFeedbackVaryingNames;
249     }
getTransformFeedbackBufferMode()250     GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
getUniformBlockBinding(GLuint uniformBlockIndex)251     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
252     {
253         ASSERT(uniformBlockIndex < mUniformBlocks.size());
254         return mUniformBlocks[uniformBlockIndex].binding;
255     }
getShaderStorageBlockBinding(GLuint blockIndex)256     GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
257     {
258         ASSERT(blockIndex < mShaderStorageBlocks.size());
259         return mShaderStorageBlocks[blockIndex].binding;
260     }
getActiveUniformBlockBindingsMask()261     const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
262     {
263         return mActiveUniformBlockBindings;
264     }
getAttributes()265     const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
getActiveAttribLocationsMask()266     const AttributesMask &getActiveAttribLocationsMask() const
267     {
268         return mActiveAttribLocationsMask;
269     }
getMaxActiveAttribLocation()270     unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
getActiveOutputVariables()271     DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
getOutputVariables()272     const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; }
getOutputLocations()273     const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
getUniforms()274     const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
getUniformLocations()275     const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
getUniformBlocks()276     const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
getShaderStorageBlocks()277     const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
278     {
279         return mShaderStorageBlocks;
280     }
getBufferVariables()281     const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
getSamplerBindings()282     const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
getImageBindings()283     const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
getComputeShaderLocalSize()284     const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
getSamplerUniformRange()285     const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
getImageUniformRange()286     const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
getAtomicCounterUniformRange()287     const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
288 
getLinkedTransformFeedbackVaryings()289     const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
290     {
291         return mLinkedTransformFeedbackVaryings;
292     }
getAtomicCounterBuffers()293     const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
294     {
295         return mAtomicCounterBuffers;
296     }
297 
298     GLuint getUniformIndexFromName(const std::string &name) const;
299     GLuint getUniformIndexFromLocation(GLint location) const;
300     Optional<GLuint> getSamplerIndex(GLint location) const;
301     bool isSamplerUniformIndex(GLuint index) const;
302     GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
303     GLuint getAttributeLocation(const std::string &name) const;
304 
305     GLuint getBufferVariableIndexFromName(const std::string &name) const;
306 
getNumViews()307     int getNumViews() const { return mNumViews; }
usesMultiview()308     bool usesMultiview() const { return mNumViews != -1; }
309 
getLinkedShaderStages()310     const ShaderStagesMask &getLinkedShaderStages() const { return mLinkedShaderStages; }
311 
312   private:
313     friend class MemoryProgramCache;
314     friend class Program;
315 
316     std::string mLabel;
317 
318     sh::WorkGroupSize mComputeShaderLocalSize;
319 
320     Shader *mAttachedFragmentShader;
321     Shader *mAttachedVertexShader;
322     Shader *mAttachedComputeShader;
323     Shader *mAttachedGeometryShader;
324 
325     std::vector<std::string> mTransformFeedbackVaryingNames;
326     std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
327     GLenum mTransformFeedbackBufferMode;
328 
329     // For faster iteration on the blocks currently being bound.
330     UniformBlockBindingMask mActiveUniformBlockBindings;
331 
332     std::vector<sh::Attribute> mAttributes;
333     angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
334     unsigned int mMaxActiveAttribLocation;
335 
336     // Uniforms are sorted in order:
337     //  1. Non-opaque uniforms
338     //  2. Sampler uniforms
339     //  3. Image uniforms
340     //  4. Atomic counter uniforms
341     //  5. Uniform block uniforms
342     // This makes opaque uniform validation easier, since we don't need a separate list.
343     // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
344     // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
345     // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
346     // [0] in the end. This makes implementation of queries simpler.
347     std::vector<LinkedUniform> mUniforms;
348 
349     std::vector<VariableLocation> mUniformLocations;
350     std::vector<InterfaceBlock> mUniformBlocks;
351     std::vector<BufferVariable> mBufferVariables;
352     std::vector<InterfaceBlock> mShaderStorageBlocks;
353     std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
354     RangeUI mSamplerUniformRange;
355     RangeUI mImageUniformRange;
356     RangeUI mAtomicCounterUniformRange;
357 
358     // An array of the samplers that are used by the program
359     std::vector<gl::SamplerBinding> mSamplerBindings;
360 
361     // An array of the images that are used by the program
362     std::vector<gl::ImageBinding> mImageBindings;
363 
364     // Names and mapped names of output variables that are arrays include [0] in the end, similarly
365     // to uniforms.
366     std::vector<sh::OutputVariable> mOutputVariables;
367     std::vector<VariableLocation> mOutputLocations;
368     DrawBufferMask mActiveOutputVariables;
369 
370     // Fragment output variable base types: FLOAT, INT, or UINT.  Ordered by location.
371     std::vector<GLenum> mOutputVariableTypes;
372 
373     bool mBinaryRetrieveableHint;
374     bool mSeparable;
375     ShaderStagesMask mLinkedShaderStages;
376 
377     // ANGLE_multiview.
378     int mNumViews;
379 };
380 
381 class Program final : angle::NonCopyable, public LabeledObject
382 {
383   public:
384     Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle);
385     void onDestroy(const Context *context);
386 
id()387     GLuint id() const { return mHandle; }
388 
389     void setLabel(const std::string &label) override;
390     const std::string &getLabel() const override;
391 
getImplementation()392     rx::ProgramImpl *getImplementation() const { return mProgram; }
393 
394     void attachShader(Shader *shader);
395     void detachShader(const Context *context, Shader *shader);
396     int getAttachedShadersCount() const;
397 
getAttachedVertexShader()398     const Shader *getAttachedVertexShader() const { return mState.mAttachedVertexShader; }
getAttachedFragmentShader()399     const Shader *getAttachedFragmentShader() const { return mState.mAttachedFragmentShader; }
getAttachedComputeShader()400     const Shader *getAttachedComputeShader() const { return mState.mAttachedComputeShader; }
getAttachedGeometryShader()401     const Shader *getAttachedGeometryShader() const { return mState.mAttachedGeometryShader; }
402 
403     void bindAttributeLocation(GLuint index, const char *name);
404     void bindUniformLocation(GLuint index, const char *name);
405 
406     // CHROMIUM_path_rendering
407     BindingInfo getFragmentInputBindingInfo(const Context *context, GLint index) const;
408     void bindFragmentInputLocation(GLint index, const char *name);
409     void pathFragmentInputGen(const Context *context,
410                               GLint index,
411                               GLenum genMode,
412                               GLint components,
413                               const GLfloat *coeffs);
414 
415     Error link(const gl::Context *context);
416     bool isLinked() const;
417 
hasLinkedVertexShader()418     bool hasLinkedVertexShader() const { return mState.mLinkedShaderStages[SHADER_VERTEX]; }
hasLinkedFragmentShader()419     bool hasLinkedFragmentShader() const { return mState.mLinkedShaderStages[SHADER_FRAGMENT]; }
hasLinkedComputeShader()420     bool hasLinkedComputeShader() const { return mState.mLinkedShaderStages[SHADER_COMPUTE]; }
421 
422     Error loadBinary(const Context *context,
423                      GLenum binaryFormat,
424                      const void *binary,
425                      GLsizei length);
426     Error saveBinary(const Context *context,
427                      GLenum *binaryFormat,
428                      void *binary,
429                      GLsizei bufSize,
430                      GLsizei *length) const;
431     GLint getBinaryLength(const Context *context) const;
432     void setBinaryRetrievableHint(bool retrievable);
433     bool getBinaryRetrievableHint() const;
434 
435     void setSeparable(bool separable);
436     bool isSeparable() const;
437 
438     int getInfoLogLength() const;
439     void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
440     void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const;
441 
442     GLuint getAttributeLocation(const std::string &name) const;
443     bool isAttribLocationActive(size_t attribLocation) const;
444 
445     void getActiveAttribute(GLuint index,
446                             GLsizei bufsize,
447                             GLsizei *length,
448                             GLint *size,
449                             GLenum *type,
450                             GLchar *name) const;
451     GLint getActiveAttributeCount() const;
452     GLint getActiveAttributeMaxLength() const;
getAttributes()453     const std::vector<sh::Attribute> &getAttributes() const { return mState.mAttributes; }
454 
455     GLint getFragDataLocation(const std::string &name) const;
456     size_t getOutputResourceCount() const;
getOutputVariableTypes()457     const std::vector<GLenum> &getOutputVariableTypes() const
458     {
459         return mState.mOutputVariableTypes;
460     }
getActiveOutputVariables()461     DrawBufferMask getActiveOutputVariables() const { return mState.mActiveOutputVariables; }
462 
463     void getActiveUniform(GLuint index,
464                           GLsizei bufsize,
465                           GLsizei *length,
466                           GLint *size,
467                           GLenum *type,
468                           GLchar *name) const;
469     GLint getActiveUniformCount() const;
470     size_t getActiveBufferVariableCount() const;
471     GLint getActiveUniformMaxLength() const;
472     bool isValidUniformLocation(GLint location) const;
473     const LinkedUniform &getUniformByLocation(GLint location) const;
474     const VariableLocation &getUniformLocation(GLint location) const;
475     const std::vector<VariableLocation> &getUniformLocations() const;
476     const LinkedUniform &getUniformByIndex(GLuint index) const;
477 
478     const BufferVariable &getBufferVariableByIndex(GLuint index) const;
479 
480     enum SetUniformResult
481     {
482         SamplerChanged,
483         NoSamplerChange,
484     };
485 
486     GLint getUniformLocation(const std::string &name) const;
487     GLuint getUniformIndex(const std::string &name) const;
488     void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
489     void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
490     void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
491     void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
492     SetUniformResult setUniform1iv(GLint location, GLsizei count, const GLint *v);
493     void setUniform2iv(GLint location, GLsizei count, const GLint *v);
494     void setUniform3iv(GLint location, GLsizei count, const GLint *v);
495     void setUniform4iv(GLint location, GLsizei count, const GLint *v);
496     void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
497     void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
498     void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
499     void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
500     void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
501     void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
502     void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
503     void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
504     void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
505     void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
506     void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
507     void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
508     void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
509 
510     void getUniformfv(const Context *context, GLint location, GLfloat *params) const;
511     void getUniformiv(const Context *context, GLint location, GLint *params) const;
512     void getUniformuiv(const Context *context, GLint location, GLuint *params) const;
513 
514     void getActiveUniformBlockName(const GLuint blockIndex,
515                                    GLsizei bufSize,
516                                    GLsizei *length,
517                                    GLchar *blockName) const;
518     void getActiveShaderStorageBlockName(const GLuint blockIndex,
519                                          GLsizei bufSize,
520                                          GLsizei *length,
521                                          GLchar *blockName) const;
522     GLuint getActiveUniformBlockCount() const;
523     GLuint getActiveAtomicCounterBufferCount() const;
524     GLuint getActiveShaderStorageBlockCount() const;
525     GLint getActiveUniformBlockMaxLength() const;
526 
527     GLuint getUniformBlockIndex(const std::string &name) const;
528     GLuint getShaderStorageBlockIndex(const std::string &name) const;
529 
530     void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
531     GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
532     GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
533 
534     const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
535     const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const;
536 
537     void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
538     void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
539     GLsizei getTransformFeedbackVaryingCount() const;
540     GLsizei getTransformFeedbackVaryingMaxLength() const;
541     GLenum getTransformFeedbackBufferMode() const;
542 
543     static bool linkValidateInterfaceBlockFields(InfoLog &infoLog,
544                                                  const std::string &uniformName,
545                                                  const sh::InterfaceBlockField &vertexUniform,
546                                                  const sh::InterfaceBlockField &fragmentUniform,
547                                                  bool webglCompatibility);
548 
549     void addRef();
550     void release(const Context *context);
551     unsigned int getRefCount() const;
552     void flagForDeletion();
553     bool isFlaggedForDeletion() const;
554 
555     void validate(const Caps &caps);
556     bool validateSamplers(InfoLog *infoLog, const Caps &caps);
557     bool isValidated() const;
558     bool samplesFromTexture(const gl::State &state, GLuint textureID) const;
559 
getActiveAttribLocationsMask()560     const AttributesMask &getActiveAttribLocationsMask() const
561     {
562         return mState.mActiveAttribLocationsMask;
563     }
564 
getSamplerBindings()565     const std::vector<SamplerBinding> &getSamplerBindings() const
566     {
567         return mState.mSamplerBindings;
568     }
569 
getImageBindings()570     const std::vector<ImageBinding> &getImageBindings() const { return mState.mImageBindings; }
getComputeShaderLocalSize()571     const sh::WorkGroupSize &getComputeShaderLocalSize() const
572     {
573         return mState.mComputeShaderLocalSize;
574     }
575 
getState()576     const ProgramState &getState() const { return mState; }
577 
578     static bool linkValidateVariablesBase(InfoLog &infoLog,
579                                           const std::string &variableName,
580                                           const sh::ShaderVariable &vertexVariable,
581                                           const sh::ShaderVariable &fragmentVariable,
582                                           bool validatePrecision);
583 
584     GLuint getInputResourceIndex(const GLchar *name) const;
585     GLuint getOutputResourceIndex(const GLchar *name) const;
586     void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
587     void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
588     void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
589     void getBufferVariableResourceName(GLuint index,
590                                        GLsizei bufSize,
591                                        GLsizei *length,
592                                        GLchar *name) const;
593     const sh::Attribute &getInputResource(GLuint index) const;
594     const sh::OutputVariable &getOutputResource(GLuint index) const;
595 
596     class Bindings final : angle::NonCopyable
597     {
598       public:
599         Bindings();
600         ~Bindings();
601         void bindLocation(GLuint index, const std::string &name);
602         int getBinding(const std::string &name) const;
603 
604         typedef std::unordered_map<std::string, GLuint>::const_iterator const_iterator;
605         const_iterator begin() const;
606         const_iterator end() const;
607 
608       private:
609         std::unordered_map<std::string, GLuint> mBindings;
610     };
611 
getAttributeBindings()612     const Bindings &getAttributeBindings() const { return mAttributeBindings; }
getUniformLocationBindings()613     const Bindings &getUniformLocationBindings() const { return mUniformLocationBindings; }
getFragmentInputBindings()614     const Bindings &getFragmentInputBindings() const { return mFragmentInputBindings; }
615 
getNumViews()616     int getNumViews() const { return mState.getNumViews(); }
usesMultiview()617     bool usesMultiview() const { return mState.usesMultiview(); }
618 
619     struct VaryingRef
620     {
getVaryingRef621         const sh::Varying *get() const { return vertex ? vertex : fragment; }
622 
623         const sh::Varying *vertex   = nullptr;
624         const sh::Varying *fragment = nullptr;
625     };
626     using MergedVaryings = std::map<std::string, VaryingRef>;
627 
628   private:
629     ~Program() override;
630 
631     void unlink();
632 
633     bool linkAttributes(const Context *context, InfoLog &infoLog);
634     bool validateVertexAndFragmentInterfaceBlocks(
635         const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
636         const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
637         InfoLog &infoLog,
638         bool webglCompatibility) const;
639     bool linkInterfaceBlocks(const Context *context, InfoLog &infoLog);
640     bool linkVaryings(const Context *context, InfoLog &infoLog) const;
641 
642     bool linkUniforms(const Context *context,
643                       InfoLog &infoLog,
644                       const Bindings &uniformLocationBindings);
645     void linkSamplerAndImageBindings();
646     bool linkAtomicCounterBuffers();
647 
648     void updateLinkedShaderStages();
649 
650     bool areMatchingInterfaceBlocks(InfoLog &infoLog,
651                                     const sh::InterfaceBlock &vertexInterfaceBlock,
652                                     const sh::InterfaceBlock &fragmentInterfaceBlock,
653                                     bool webglCompatibility) const;
654 
655     static bool linkValidateVaryings(InfoLog &infoLog,
656                                      const std::string &varyingName,
657                                      const sh::Varying &vertexVarying,
658                                      const sh::Varying &fragmentVarying,
659                                      int shaderVersion);
660     bool linkValidateBuiltInVaryings(const Context *context, InfoLog &infoLog) const;
661     bool linkValidateTransformFeedback(const gl::Context *context,
662                                        InfoLog &infoLog,
663                                        const MergedVaryings &linkedVaryings,
664                                        const Caps &caps) const;
665     bool linkValidateGlobalNames(const Context *context, InfoLog &infoLog) const;
666 
667     void gatherTransformFeedbackVaryings(const MergedVaryings &varyings);
668 
669     MergedVaryings getMergedVaryings(const Context *context) const;
670     void linkOutputVariables(const Context *context);
671 
672     void setUniformValuesFromBindingQualifiers();
673 
674     void gatherAtomicCounterBuffers();
675     void initInterfaceBlockBindings();
676 
677     // Both these function update the cached uniform values and return a modified "count"
678     // so that the uniform update doesn't overflow the uniform.
679     template <typename T>
680     GLsizei clampUniformCount(const VariableLocation &locationInfo,
681                               GLsizei count,
682                               int vectorSize,
683                               const T *v);
684     template <size_t cols, size_t rows, typename T>
685     GLsizei clampMatrixUniformCount(GLint location, GLsizei count, GLboolean transpose, const T *v);
686 
687     void updateSamplerUniform(const VariableLocation &locationInfo,
688                               GLsizei clampedCount,
689                               const GLint *v);
690 
691     template <typename DestT>
692     void getUniformInternal(const Context *context,
693                             DestT *dataOut,
694                             GLint location,
695                             GLenum nativeType,
696                             int components) const;
697 
698     template <typename T>
699     void getResourceName(GLuint index,
700                          const std::vector<T> &resources,
701                          GLsizei bufSize,
702                          GLsizei *length,
703                          GLchar *name) const;
704 
705     ProgramState mState;
706     rx::ProgramImpl *mProgram;
707 
708     bool mValidated;
709 
710     Bindings mAttributeBindings;
711 
712     // Note that this has nothing to do with binding layout qualifiers that can be set for some
713     // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
714     Bindings mUniformLocationBindings;
715 
716     // CHROMIUM_path_rendering
717     Bindings mFragmentInputBindings;
718 
719     bool mLinked;
720     bool mDeleteStatus;   // Flag to indicate that the program can be deleted when no longer in use
721 
722     unsigned int mRefCount;
723 
724     ShaderProgramManager *mResourceManager;
725     const GLuint mHandle;
726 
727     InfoLog mInfoLog;
728 
729     // Cache for sampler validation
730     Optional<bool> mCachedValidateSamplersResult;
731     std::vector<GLenum> mTextureUnitTypesCache;
732 };
733 }  // namespace gl
734 
735 #endif   // LIBANGLE_PROGRAM_H_
736