summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/Program.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/Program.h')
-rw-r--r--gfx/angle/checkout/src/libANGLE/Program.h1070
1 files changed, 1070 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/Program.h b/gfx/angle/checkout/src/libANGLE/Program.h
new file mode 100644
index 0000000000..c1191f2159
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Program.h
@@ -0,0 +1,1070 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Program.h: Defines the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#ifndef LIBANGLE_PROGRAM_H_
+#define LIBANGLE_PROGRAM_H_
+
+#include <GLES2/gl2.h>
+#include <GLSLANG/ShaderVars.h>
+
+#include <array>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ProgramImpl;
+struct TranslatedAttribute;
+} // namespace rx
+
+namespace gl
+{
+class Buffer;
+class BinaryInputStream;
+class BinaryOutputStream;
+struct Caps;
+class Context;
+struct Extensions;
+class Framebuffer;
+class InfoLog;
+class Shader;
+class ShaderProgramManager;
+class State;
+struct UnusedUniform;
+struct Version;
+
+extern const char *const g_fakepath;
+
+enum class LinkMismatchError
+{
+ // Shared
+ NO_MISMATCH,
+ TYPE_MISMATCH,
+ ARRAY_SIZE_MISMATCH,
+ PRECISION_MISMATCH,
+ STRUCT_NAME_MISMATCH,
+ FIELD_NUMBER_MISMATCH,
+ FIELD_NAME_MISMATCH,
+
+ // Varying specific
+ INTERPOLATION_TYPE_MISMATCH,
+ INVARIANCE_MISMATCH,
+
+ // Uniform specific
+ BINDING_MISMATCH,
+ LOCATION_MISMATCH,
+ OFFSET_MISMATCH,
+ INSTANCE_NAME_MISMATCH,
+
+ // Interface block specific
+ LAYOUT_QUALIFIER_MISMATCH,
+ MATRIX_PACKING_MISMATCH
+};
+
+class InfoLog : angle::NonCopyable
+{
+ public:
+ InfoLog();
+ ~InfoLog();
+
+ size_t getLength() const;
+ void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+
+ void appendSanitized(const char *message);
+ void reset();
+
+ // This helper class ensures we append a newline after writing a line.
+ class StreamHelper : angle::NonCopyable
+ {
+ public:
+ StreamHelper(StreamHelper &&rhs) : mStream(rhs.mStream) { rhs.mStream = nullptr; }
+
+ StreamHelper &operator=(StreamHelper &&rhs)
+ {
+ std::swap(mStream, rhs.mStream);
+ return *this;
+ }
+
+ ~StreamHelper()
+ {
+ // Write newline when destroyed on the stack
+ if (mStream)
+ {
+ (*mStream) << std::endl;
+ }
+ }
+
+ template <typename T>
+ StreamHelper &operator<<(const T &value)
+ {
+ (*mStream) << value;
+ return *this;
+ }
+
+ private:
+ friend class InfoLog;
+
+ StreamHelper(std::stringstream *stream) : mStream(stream) { ASSERT(stream); }
+
+ std::stringstream *mStream;
+ };
+
+ template <typename T>
+ StreamHelper operator<<(const T &value)
+ {
+ ensureInitialized();
+ StreamHelper helper(mLazyStream.get());
+ helper << value;
+ return helper;
+ }
+
+ std::string str() const { return mLazyStream ? mLazyStream->str() : ""; }
+
+ bool empty() const;
+
+ private:
+ void ensureInitialized()
+ {
+ if (!mLazyStream)
+ {
+ mLazyStream.reset(new std::stringstream());
+ }
+ }
+
+ std::unique_ptr<std::stringstream> mLazyStream;
+};
+
+void LogLinkMismatch(InfoLog &infoLog,
+ const std::string &variableName,
+ const char *variableType,
+ LinkMismatchError linkError,
+ const std::string &mismatchedStructOrBlockFieldName,
+ ShaderType shaderType1,
+ ShaderType shaderType2);
+
+bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock);
+
+void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var);
+void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var);
+
+// Struct used for correlating uniforms/elements of uniform arrays to handles
+struct VariableLocation
+{
+ static constexpr unsigned int kUnused = GL_INVALID_INDEX;
+
+ VariableLocation();
+ VariableLocation(unsigned int arrayIndex, unsigned int index);
+
+ // If used is false, it means this location is only used to fill an empty space in an array,
+ // and there is no corresponding uniform variable for this location. It can also mean the
+ // uniform was optimized out by the implementation.
+ bool used() const { return (index != kUnused); }
+ void markUnused() { index = kUnused; }
+ void markIgnored() { ignored = true; }
+
+ bool operator==(const VariableLocation &other) const
+ {
+ return arrayIndex == other.arrayIndex && index == other.index;
+ }
+
+ // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays.
+ unsigned int arrayIndex;
+ // "index" is an index of the variable. The variable contains the indices for other than the
+ // innermost GLSL arrays.
+ unsigned int index;
+
+ // If this location was bound to an unreferenced uniform. Setting data on this uniform is a
+ // no-op.
+ bool ignored;
+};
+
+// Information about a variable binding.
+// Currently used by CHROMIUM_path_rendering
+struct BindingInfo
+{
+ // The type of binding, for example GL_FLOAT_VEC3.
+ // This can be GL_NONE if the variable is optimized away.
+ GLenum type;
+
+ // This is the name of the variable in
+ // the translated shader program. Note that
+ // this can be empty in the case where the
+ // variable has been optimized away.
+ std::string name;
+
+ // True if the binding is valid, otherwise false.
+ bool valid;
+};
+
+// This small structure encapsulates binding sampler uniforms to active GL textures.
+struct SamplerBinding
+{
+ SamplerBinding(TextureType textureTypeIn,
+ SamplerFormat formatIn,
+ size_t elementCount,
+ bool unreferenced);
+ SamplerBinding(const SamplerBinding &other);
+ ~SamplerBinding();
+
+ // Necessary for retrieving active textures from the GL state.
+ TextureType textureType;
+
+ SamplerFormat format;
+
+ // List of all textures bound to this sampler, of type textureType.
+ std::vector<GLuint> boundTextureUnits;
+
+ // A note if this sampler is an unreferenced uniform.
+ bool unreferenced;
+};
+
+// A varying with tranform feedback enabled. If it's an array, either the whole array or one of its
+// elements specified by 'arrayIndex' can set to be enabled.
+struct TransformFeedbackVarying : public sh::Varying
+{
+ TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index)
+ : sh::Varying(varyingIn), arrayIndex(index)
+ {
+ ASSERT(!isArrayOfArrays());
+ }
+
+ TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::Varying &parent)
+ : arrayIndex(GL_INVALID_INDEX)
+ {
+ sh::ShaderVariable *thisVar = this;
+ *thisVar = field;
+ interpolation = parent.interpolation;
+ isInvariant = parent.isInvariant;
+ name = parent.name + "." + name;
+ mappedName = parent.mappedName + "." + mappedName;
+ }
+
+ std::string nameWithArrayIndex() const
+ {
+ std::stringstream fullNameStr;
+ fullNameStr << name;
+ if (arrayIndex != GL_INVALID_INDEX)
+ {
+ fullNameStr << "[" << arrayIndex << "]";
+ }
+ return fullNameStr.str();
+ }
+ GLsizei size() const
+ {
+ return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
+ }
+
+ GLuint arrayIndex;
+};
+
+struct ImageBinding
+{
+ ImageBinding(size_t count);
+ ImageBinding(GLuint imageUnit, size_t count, bool unreferenced);
+ ImageBinding(const ImageBinding &other);
+ ~ImageBinding();
+
+ std::vector<GLuint> boundImageUnits;
+
+ // A note if this image unit is an unreferenced uniform.
+ bool unreferenced;
+};
+
+class ProgramState final : angle::NonCopyable
+{
+ public:
+ ProgramState();
+ ~ProgramState();
+
+ const std::string &getLabel();
+
+ Shader *getAttachedShader(ShaderType shaderType) const;
+ const gl::ShaderMap<Shader *> &getAttachedShaders() const { return mAttachedShaders; }
+ const std::vector<std::string> &getTransformFeedbackVaryingNames() const
+ {
+ return mTransformFeedbackVaryingNames;
+ }
+ GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
+ {
+ ASSERT(uniformBlockIndex < mUniformBlocks.size());
+ return mUniformBlocks[uniformBlockIndex].binding;
+ }
+ GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
+ {
+ ASSERT(blockIndex < mShaderStorageBlocks.size());
+ return mShaderStorageBlocks[blockIndex].binding;
+ }
+ const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
+ {
+ return mActiveUniformBlockBindings;
+ }
+ const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; }
+ const AttributesMask &getActiveAttribLocationsMask() const
+ {
+ return mActiveAttribLocationsMask;
+ }
+ const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
+ unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
+ DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; }
+ const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; }
+ const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
+ const std::vector<VariableLocation> &getSecondaryOutputLocations() const
+ {
+ return mSecondaryOutputLocations;
+ }
+ const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
+ const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
+ const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
+ const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
+ {
+ return mShaderStorageBlocks;
+ }
+ const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
+ const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
+ const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
+ const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
+ const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
+ const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
+ const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
+ const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
+
+ const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
+ {
+ return mLinkedTransformFeedbackVaryings;
+ }
+ const std::vector<GLsizei> &getTransformFeedbackStrides() const
+ {
+ return mTransformFeedbackStrides;
+ }
+ size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
+ const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
+ {
+ return mAtomicCounterBuffers;
+ }
+
+ // Count the number of uniform and storage buffer declarations, counting arrays as one.
+ size_t getUniqueUniformBlockCount() const;
+ size_t getUniqueStorageBlockCount() const;
+
+ GLuint getUniformIndexFromName(const std::string &name) const;
+ GLuint getUniformIndexFromLocation(GLint location) const;
+ Optional<GLuint> getSamplerIndex(GLint location) const;
+ bool isSamplerUniformIndex(GLuint index) const;
+ GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
+ GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
+ bool isImageUniformIndex(GLuint index) const;
+ GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
+ GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const;
+ GLuint getAttributeLocation(const std::string &name) const;
+
+ GLuint getBufferVariableIndexFromName(const std::string &name) const;
+
+ int getNumViews() const { return mNumViews; }
+ bool usesMultiview() const { return mNumViews != -1; }
+
+ const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
+ bool hasLinkedShaderStage(ShaderType shaderType) const
+ {
+ return mLinkedShaderStages[shaderType];
+ }
+ size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
+ bool isCompute() const { return hasLinkedShaderStage(ShaderType::Compute); }
+
+ bool hasAttachedShader() const;
+
+ const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
+ SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
+ {
+ return mActiveSamplerFormats[textureUnitIndex];
+ }
+
+ private:
+ friend class MemoryProgramCache;
+ friend class Program;
+
+ void updateTransformFeedbackStrides();
+ void updateActiveSamplers();
+ void updateActiveImages();
+
+ // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
+ void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex);
+
+ std::string mLabel;
+
+ sh::WorkGroupSize mComputeShaderLocalSize;
+
+ ShaderMap<Shader *> mAttachedShaders;
+
+ std::vector<std::string> mTransformFeedbackVaryingNames;
+ std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
+ GLenum mTransformFeedbackBufferMode;
+
+ // For faster iteration on the blocks currently being bound.
+ UniformBlockBindingMask mActiveUniformBlockBindings;
+
+ std::vector<sh::Attribute> mAttributes;
+ angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
+ unsigned int mMaxActiveAttribLocation;
+ ComponentTypeMask mAttributesTypeMask;
+ // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
+ AttributesMask mAttributesMask;
+
+ // Uniforms are sorted in order:
+ // 1. Non-opaque uniforms
+ // 2. Sampler uniforms
+ // 3. Image uniforms
+ // 4. Atomic counter uniforms
+ // 5. Uniform block uniforms
+ // This makes opaque uniform validation easier, since we don't need a separate list.
+ // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
+ // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
+ // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
+ // [0] in the end. This makes implementation of queries simpler.
+ std::vector<LinkedUniform> mUniforms;
+
+ std::vector<VariableLocation> mUniformLocations;
+ std::vector<InterfaceBlock> mUniformBlocks;
+ std::vector<BufferVariable> mBufferVariables;
+ std::vector<InterfaceBlock> mShaderStorageBlocks;
+ std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
+ RangeUI mSamplerUniformRange;
+ RangeUI mImageUniformRange;
+ RangeUI mAtomicCounterUniformRange;
+
+ // An array of the samplers that are used by the program
+ std::vector<SamplerBinding> mSamplerBindings;
+
+ // An array of the images that are used by the program
+ std::vector<ImageBinding> mImageBindings;
+
+ // Names and mapped names of output variables that are arrays include [0] in the end, similarly
+ // to uniforms.
+ std::vector<sh::OutputVariable> mOutputVariables;
+ std::vector<VariableLocation> mOutputLocations;
+
+ // EXT_blend_func_extended secondary outputs (ones with index 1) in ESSL 3.00 shaders.
+ std::vector<VariableLocation> mSecondaryOutputLocations;
+
+ DrawBufferMask mActiveOutputVariables;
+
+ // Fragment output variable base types: FLOAT, INT, or UINT. Ordered by location.
+ std::vector<GLenum> mOutputVariableTypes;
+ ComponentTypeMask mDrawBufferTypeMask;
+
+ bool mBinaryRetrieveableHint;
+ bool mSeparable;
+ ShaderBitSet mLinkedShaderStages;
+
+ // ANGLE_multiview.
+ int mNumViews;
+
+ // GL_EXT_geometry_shader.
+ PrimitiveMode mGeometryShaderInputPrimitiveType;
+ PrimitiveMode mGeometryShaderOutputPrimitiveType;
+ int mGeometryShaderInvocations;
+ int mGeometryShaderMaxVertices;
+
+ // GL_ANGLE_multi_draw
+ int mDrawIDLocation;
+
+ // The size of the data written to each transform feedback buffer per vertex.
+ std::vector<GLsizei> mTransformFeedbackStrides;
+
+ // Cached mask of active samplers and sampler types.
+ ActiveTextureMask mActiveSamplersMask;
+ ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
+ ActiveTextureArray<TextureType> mActiveSamplerTypes;
+ ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
+
+ // Cached mask of active images.
+ ActiveTextureMask mActiveImagesMask;
+};
+
+struct ProgramBinding
+{
+ ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
+ ProgramBinding(GLuint index) : location(index), aliased(false) {}
+
+ GLuint location;
+ // Whether another binding was set that may potentially alias this.
+ bool aliased;
+};
+
+class ProgramBindings final : angle::NonCopyable
+{
+ public:
+ ProgramBindings();
+ ~ProgramBindings();
+
+ void bindLocation(GLuint index, const std::string &name);
+ int getBindingByName(const std::string &name) const;
+ int getBinding(const sh::VariableWithLocation &variable) const;
+
+ using const_iterator = std::unordered_map<std::string, ProgramBinding>::const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ private:
+ std::unordered_map<std::string, ProgramBinding> mBindings;
+};
+
+struct ProgramVaryingRef
+{
+ const sh::Varying *get() const { return vertex ? vertex : fragment; }
+
+ const sh::Varying *vertex = nullptr;
+ const sh::Varying *fragment = nullptr;
+};
+
+using ProgramMergedVaryings = std::map<std::string, ProgramVaryingRef>;
+
+class Program final : angle::NonCopyable, public LabeledObject
+{
+ public:
+ Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle);
+ void onDestroy(const Context *context);
+
+ GLuint id() const;
+
+ void setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ ANGLE_INLINE rx::ProgramImpl *getImplementation() const
+ {
+ ASSERT(mLinkResolved);
+ return mProgram;
+ }
+
+ void attachShader(Shader *shader);
+ void detachShader(const Context *context, Shader *shader);
+ int getAttachedShadersCount() const;
+
+ const Shader *getAttachedShader(ShaderType shaderType) const;
+
+ void bindAttributeLocation(GLuint index, const char *name);
+ void bindUniformLocation(GLuint index, const char *name);
+
+ // CHROMIUM_path_rendering
+ BindingInfo getFragmentInputBindingInfo(GLint index) const;
+ void bindFragmentInputLocation(GLint index, const char *name);
+ void pathFragmentInputGen(GLint index, GLenum genMode, GLint components, const GLfloat *coeffs);
+
+ // EXT_blend_func_extended
+ void bindFragmentOutputLocation(GLuint index, const char *name);
+ void bindFragmentOutputIndex(GLuint index, const char *name);
+
+ // KHR_parallel_shader_compile
+ // Try to link the program asynchrously. As a result, background threads may be launched to
+ // execute the linking tasks concurrently.
+ angle::Result link(const Context *context);
+
+ // Peek whether there is any running linking tasks.
+ bool isLinking() const;
+
+ bool isLinked() const
+ {
+ ASSERT(mLinkResolved);
+ return mLinked;
+ }
+
+ bool hasLinkedShaderStage(ShaderType shaderType) const
+ {
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+ return mState.hasLinkedShaderStage(shaderType);
+ }
+ bool isCompute() const { return mState.isCompute(); }
+
+ angle::Result loadBinary(const Context *context,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+ angle::Result saveBinary(Context *context,
+ GLenum *binaryFormat,
+ void *binary,
+ GLsizei bufSize,
+ GLsizei *length) const;
+ GLint getBinaryLength(Context *context) const;
+ void setBinaryRetrievableHint(bool retrievable);
+ bool getBinaryRetrievableHint() const;
+
+ void setSeparable(bool separable);
+ bool isSeparable() const;
+
+ int getInfoLogLength() const;
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+ void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const;
+
+ GLuint getAttributeLocation(const std::string &name) const;
+ bool isAttribLocationActive(size_t attribLocation) const;
+
+ void getActiveAttribute(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const;
+ GLint getActiveAttributeCount() const;
+ GLint getActiveAttributeMaxLength() const;
+ const std::vector<sh::Attribute> &getAttributes() const;
+
+ GLint getFragDataLocation(const std::string &name) const;
+ size_t getOutputResourceCount() const;
+ const std::vector<GLenum> &getOutputVariableTypes() const;
+ DrawBufferMask getActiveOutputVariables() const
+ {
+ ASSERT(mLinkResolved);
+ return mState.mActiveOutputVariables;
+ }
+
+ // EXT_blend_func_extended
+ GLint getFragDataIndex(const std::string &name) const;
+
+ void getActiveUniform(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const;
+ GLint getActiveUniformCount() const;
+ size_t getActiveBufferVariableCount() const;
+ GLint getActiveUniformMaxLength() const;
+ bool isValidUniformLocation(GLint location) const;
+ const LinkedUniform &getUniformByLocation(GLint location) const;
+ const VariableLocation &getUniformLocation(GLint location) const;
+
+ const std::vector<VariableLocation> &getUniformLocations() const
+ {
+ ASSERT(mLinkResolved);
+ return mState.mUniformLocations;
+ }
+
+ const LinkedUniform &getUniformByIndex(GLuint index) const
+ {
+ ASSERT(mLinkResolved);
+ ASSERT(index < static_cast<size_t>(mState.mUniforms.size()));
+ return mState.mUniforms[index];
+ }
+
+ const BufferVariable &getBufferVariableByIndex(GLuint index) const;
+
+ enum SetUniformResult
+ {
+ SamplerChanged,
+ NoSamplerChange,
+ };
+
+ GLint getUniformLocation(const std::string &name) const;
+ GLuint getUniformIndex(const std::string &name) const;
+ void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
+ void setUniform1iv(Context *context, GLint location, GLsizei count, const GLint *v);
+ void setUniform2iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform3iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform4iv(GLint location, GLsizei count, const GLint *v);
+ void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
+ void setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void getUniformfv(const Context *context, GLint location, GLfloat *params) const;
+ void getUniformiv(const Context *context, GLint location, GLint *params) const;
+ void getUniformuiv(const Context *context, GLint location, GLuint *params) const;
+
+ void getActiveUniformBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const;
+ void getActiveShaderStorageBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const;
+
+ ANGLE_INLINE GLuint getActiveUniformBlockCount() const
+ {
+ ASSERT(mLinkResolved);
+ return static_cast<GLuint>(mState.mUniformBlocks.size());
+ }
+
+ ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
+ {
+ ASSERT(mLinkResolved);
+ return static_cast<GLuint>(mState.mAtomicCounterBuffers.size());
+ }
+
+ ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
+ {
+ ASSERT(mLinkResolved);
+ return static_cast<GLuint>(mState.mShaderStorageBlocks.size());
+ }
+
+ GLint getActiveUniformBlockMaxNameLength() const;
+ GLint getActiveShaderStorageBlockMaxNameLength() const;
+
+ GLuint getUniformBlockIndex(const std::string &name) const;
+ GLuint getShaderStorageBlockIndex(const std::string &name) const;
+
+ void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
+ GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
+
+ const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
+ const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const;
+
+ void setTransformFeedbackVaryings(GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+ void getTransformFeedbackVarying(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name) const;
+ GLsizei getTransformFeedbackVaryingCount() const;
+ GLsizei getTransformFeedbackVaryingMaxLength() const;
+ GLenum getTransformFeedbackBufferMode() const;
+ GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
+ const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
+
+ bool hasDrawIDUniform() const;
+ void setDrawIDUniform(GLint drawid);
+
+ ANGLE_INLINE void addRef()
+ {
+ ASSERT(mLinkResolved);
+ mRefCount++;
+ }
+
+ ANGLE_INLINE void release(const Context *context)
+ {
+ ASSERT(mLinkResolved);
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ deleteSelf(context);
+ }
+ }
+
+ unsigned int getRefCount() const;
+ bool isInUse() const { return getRefCount() != 0; }
+ void flagForDeletion();
+ bool isFlaggedForDeletion() const;
+
+ void validate(const Caps &caps);
+ bool validateSamplers(InfoLog *infoLog, const Caps &caps)
+ {
+ // Skip cache if we're using an infolog, so we get the full error.
+ // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
+ if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
+ {
+ return mCachedValidateSamplersResult.value();
+ }
+
+ return validateSamplersImpl(infoLog, caps);
+ }
+
+ bool isValidated() const;
+
+ const AttributesMask &getActiveAttribLocationsMask() const
+ {
+ ASSERT(mLinkResolved);
+ return mState.mActiveAttribLocationsMask;
+ }
+
+ const std::vector<SamplerBinding> &getSamplerBindings() const;
+ const std::vector<ImageBinding> &getImageBindings() const
+ {
+ ASSERT(mLinkResolved);
+ return mState.mImageBindings;
+ }
+ const sh::WorkGroupSize &getComputeShaderLocalSize() const;
+ PrimitiveMode getGeometryShaderInputPrimitiveType() const;
+ PrimitiveMode getGeometryShaderOutputPrimitiveType() const;
+ GLint getGeometryShaderInvocations() const;
+ GLint getGeometryShaderMaxVertices() const;
+
+ const ProgramState &getState() const
+ {
+ ASSERT(mLinkResolved);
+ return mState;
+ }
+
+ static LinkMismatchError LinkValidateVariablesBase(
+ const sh::ShaderVariable &variable1,
+ const sh::ShaderVariable &variable2,
+ bool validatePrecision,
+ bool validateArraySize,
+ std::string *mismatchedStructOrBlockMemberName);
+
+ GLuint getInputResourceIndex(const GLchar *name) const;
+ GLuint getOutputResourceIndex(const GLchar *name) const;
+ void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getBufferVariableResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const;
+ const sh::Attribute &getInputResource(GLuint index) const;
+ const sh::OutputVariable &getOutputResource(GLuint index) const;
+
+ const ProgramBindings &getAttributeBindings() const;
+ const ProgramBindings &getUniformLocationBindings() const;
+ const ProgramBindings &getFragmentInputBindings() const;
+
+ int getNumViews() const
+ {
+ ASSERT(mLinkResolved);
+ return mState.getNumViews();
+ }
+
+ bool usesMultiview() const { return mState.usesMultiview(); }
+
+ ComponentTypeMask getDrawBufferTypeMask() const;
+ ComponentTypeMask getAttributesTypeMask() const;
+ AttributesMask getAttributesMask() const;
+
+ const std::vector<GLsizei> &getTransformFeedbackStrides() const;
+
+ const ActiveTextureMask &getActiveSamplersMask() const { return mState.mActiveSamplersMask; }
+ const ActiveTextureMask &getActiveImagesMask() const { return mState.mActiveImagesMask; }
+
+ const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
+ {
+ return mState.mActiveSamplerTypes;
+ }
+
+ // Program dirty bits.
+ enum DirtyBitType
+ {
+ DIRTY_BIT_UNIFORM_BLOCK_BINDING_0,
+ DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX =
+ DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS,
+
+ DIRTY_BIT_COUNT = DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX,
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
+
+ angle::Result syncState(const Context *context);
+
+ // Try to resolve linking. Inlined to make sure its overhead is as low as possible.
+ void resolveLink(const Context *context)
+ {
+ if (!mLinkResolved)
+ {
+ resolveLinkImpl(context);
+ }
+ }
+
+ ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+ // Writes a program's binary to the output memory buffer.
+ void serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
+
+ private:
+ struct LinkingState;
+
+ ~Program() override;
+
+ // Loads program state according to the specified binary blob.
+ angle::Result deserialize(const Context *context, BinaryInputStream &stream, InfoLog &infoLog);
+
+ void unlink();
+ void deleteSelf(const Context *context);
+
+ bool linkValidateShaders(InfoLog &infoLog);
+ bool linkAttributes(const Context *context, InfoLog &infoLog);
+ bool linkInterfaceBlocks(const Caps &caps,
+ const Version &version,
+ bool webglCompatibility,
+ InfoLog &infoLog,
+ GLuint *combinedShaderStorageBlocksCount);
+ bool linkVaryings(InfoLog &infoLog) const;
+
+ bool linkUniforms(const Caps &caps,
+ InfoLog &infoLog,
+ const ProgramBindings &uniformLocationBindings,
+ GLuint *combinedImageUniformsCount,
+ std::vector<UnusedUniform> *unusedUniforms);
+ void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount);
+ bool linkAtomicCounterBuffers();
+
+ void updateLinkedShaderStages();
+
+ static LinkMismatchError LinkValidateVaryings(const sh::Varying &outputVarying,
+ const sh::Varying &inputVarying,
+ int shaderVersion,
+ bool validateGeometryShaderInputVarying,
+ std::string *mismatchedStructFieldName);
+
+ bool linkValidateShaderInterfaceMatching(Shader *generatingShader,
+ Shader *consumingShader,
+ InfoLog &infoLog) const;
+
+ // Check for aliased path rendering input bindings (if any).
+ // If more than one binding refer statically to the same location the link must fail.
+ bool linkValidateFragmentInputBindings(InfoLog &infoLog) const;
+
+ bool linkValidateBuiltInVaryings(InfoLog &infoLog) const;
+ bool linkValidateTransformFeedback(const Version &version,
+ InfoLog &infoLog,
+ const ProgramMergedVaryings &linkedVaryings,
+ const Caps &caps) const;
+ bool linkValidateGlobalNames(InfoLog &infoLog) const;
+
+ void gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings);
+
+ ProgramMergedVaryings getMergedVaryings() const;
+ int getOutputLocationForLink(const sh::OutputVariable &outputVariable) const;
+ bool isOutputSecondaryForLink(const sh::OutputVariable &outputVariable) const;
+ bool linkOutputVariables(const Caps &caps,
+ const Extensions &extensions,
+ const Version &version,
+ GLuint combinedImageUniformsCount,
+ GLuint combinedShaderStorageBlocksCount);
+
+ void setUniformValuesFromBindingQualifiers();
+
+ void initInterfaceBlockBindings();
+
+ // Both these function update the cached uniform values and return a modified "count"
+ // so that the uniform update doesn't overflow the uniform.
+ template <typename T>
+ GLsizei clampUniformCount(const VariableLocation &locationInfo,
+ GLsizei count,
+ int vectorSize,
+ const T *v);
+ template <size_t cols, size_t rows, typename T>
+ GLsizei clampMatrixUniformCount(GLint location, GLsizei count, GLboolean transpose, const T *v);
+
+ void updateSamplerUniform(Context *context,
+ const VariableLocation &locationInfo,
+ GLsizei clampedCount,
+ const GLint *v);
+
+ template <typename DestT>
+ void getUniformInternal(const Context *context,
+ DestT *dataOut,
+ GLint location,
+ GLenum nativeType,
+ int components) const;
+
+ template <typename T>
+ void getResourceName(GLuint index,
+ const std::vector<T> &resources,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const;
+
+ template <typename T>
+ GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const;
+
+ GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
+
+ bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps);
+
+ // Block until linking is finished and resolve it.
+ void resolveLinkImpl(const gl::Context *context);
+
+ void postResolveLink(const gl::Context *context);
+
+ ProgramState mState;
+ rx::ProgramImpl *mProgram;
+
+ bool mValidated;
+
+ ProgramBindings mAttributeBindings;
+
+ // Note that this has nothing to do with binding layout qualifiers that can be set for some
+ // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
+ ProgramBindings mUniformLocationBindings;
+
+ // CHROMIUM_path_rendering
+ ProgramBindings mFragmentInputBindings;
+
+ // EXT_blend_func_extended
+ ProgramBindings mFragmentOutputLocations;
+ ProgramBindings mFragmentOutputIndexes;
+
+ bool mLinked;
+ bool mLinkResolved;
+ std::unique_ptr<LinkingState> mLinkingState;
+ bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
+
+ unsigned int mRefCount;
+
+ ShaderProgramManager *mResourceManager;
+ const GLuint mHandle;
+
+ InfoLog mInfoLog;
+
+ // Cache for sampler validation
+ Optional<bool> mCachedValidateSamplersResult;
+
+ DirtyBits mDirtyBits;
+};
+} // namespace gl
+
+#endif // LIBANGLE_PROGRAM_H_