| // | |
| // 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 "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 gl | |
| { | |
| struct UnusedUniform; | |
| struct Caps; | |
| class Context; | |
| class ContextState; | |
| class Shader; | |
| class ShaderProgramManager; | |
| class State; | |
| class InfoLog; | |
| class Buffer; | |
| class Framebuffer; | |
| 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, | |
| // 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); | |
| // 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; } | |
| // "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, size_t elementCount, bool unreferenced); | |
| SamplerBinding(const SamplerBinding &other); | |
| ~SamplerBinding(); | |
| // Necessary for retrieving active textures from the GL state. | |
| TextureType textureType; | |
| // 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; | |
| } | |
| 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; | |
| } | |
| 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<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 std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const | |
| { | |
| return mLinkedTransformFeedbackVaryings; | |
| } | |
| const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const | |
| { | |
| return mAtomicCounterBuffers; | |
| } | |
| 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; | |
| bool isImageUniformIndex(GLuint index) const; | |
| GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) 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 hasAttachedShader() const; | |
| const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; } | |
| private: | |
| friend class MemoryProgramCache; | |
| friend class Program; | |
| void updateTransformFeedbackStrides(); | |
| void updateActiveSamplers(); | |
| void updateActiveImages(); | |
| // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. | |
| TextureType getSamplerUniformTextureType(size_t textureUnitIndex) const; | |
| 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; | |
| 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; | |
| // 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; | |
| // Cached mask of active images. | |
| ActiveTextureMask mActiveImagesMask; | |
| }; | |
| class ProgramBindings final : angle::NonCopyable | |
| { | |
| public: | |
| ProgramBindings(); | |
| ~ProgramBindings(); | |
| void bindLocation(GLuint index, const std::string &name); | |
| int getBinding(const std::string &name) const; | |
| using const_iterator = std::unordered_map<std::string, GLuint>::const_iterator; | |
| const_iterator begin() const; | |
| const_iterator end() const; | |
| private: | |
| std::unordered_map<std::string, GLuint> 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 std::string &label) override; | |
| const std::string &getLabel() const override; | |
| rx::ProgramImpl *getImplementation() const; | |
| 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); | |
| // KHR_parallel_shader_compile | |
| // Try to link the program asynchrously. As a result, background threads may be launched to | |
| // execute the linking tasks concurrently. | |
| Error link(const Context *context); | |
| // Peek whether there is any running linking tasks. | |
| bool isLinking() const; | |
| bool isLinked() const; | |
| bool hasLinkedShaderStage(ShaderType shaderType) const | |
| { | |
| ASSERT(shaderType != ShaderType::InvalidEnum); | |
| return mState.mLinkedShaderStages[shaderType]; | |
| } | |
| Error loadBinary(const Context *context, | |
| GLenum binaryFormat, | |
| const void *binary, | |
| GLsizei length); | |
| Error saveBinary(const Context *context, | |
| GLenum *binaryFormat, | |
| void *binary, | |
| GLsizei bufSize, | |
| GLsizei *length) const; | |
| GLint getBinaryLength(const 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; | |
| 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; | |
| const LinkedUniform &getUniformByIndex(GLuint index) const; | |
| 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); | |
| SetUniformResult setUniform1iv(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; | |
| GLuint getActiveUniformBlockCount() const | |
| { | |
| return static_cast<GLuint>(mState.mUniformBlocks.size()); | |
| } | |
| GLuint getActiveAtomicCounterBufferCount() const; | |
| GLuint getActiveShaderStorageBlockCount() const; | |
| 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; | |
| void addRef(); | |
| void release(const Context *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; | |
| bool samplesFromTexture(const State &state, GLuint textureID) const; | |
| const AttributesMask &getActiveAttribLocationsMask() const | |
| { | |
| resolveLink(); | |
| return mState.mActiveAttribLocationsMask; | |
| } | |
| const std::vector<SamplerBinding> &getSamplerBindings() const; | |
| const std::vector<ImageBinding> &getImageBindings() const | |
| { | |
| resolveLink(); | |
| return mState.mImageBindings; | |
| } | |
| const sh::WorkGroupSize &getComputeShaderLocalSize() const; | |
| PrimitiveMode getGeometryShaderInputPrimitiveType() const; | |
| PrimitiveMode getGeometryShaderOutputPrimitiveType() const; | |
| GLint getGeometryShaderInvocations() const; | |
| GLint getGeometryShaderMaxVertices() const; | |
| const ProgramState &getState() const | |
| { | |
| resolveLink(); | |
| 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; | |
| 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>; | |
| Error syncState(const Context *context); | |
| private: | |
| struct LinkingState; | |
| ~Program() override; | |
| void unlink(); | |
| bool linkValidateShaders(InfoLog &infoLog); | |
| bool linkAttributes(const Caps &caps, 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; | |
| bool linkOutputVariables(const Caps &caps, | |
| 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(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); | |
| // Try to resolve linking. | |
| // Note: this method is frequently called in each draw call. Please make sure its overhead | |
| // is as low as possible. | |
| void resolveLink() const | |
| { | |
| if (!mLinkResolved) | |
| { | |
| return const_cast<Program *>(this)->resolveLinkImpl(); | |
| } | |
| } | |
| // Block until linking is finished and resolve it. | |
| void resolveLinkImpl(); | |
| 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; | |
| 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_ |