| // | |
| // Copyright 2002 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/InfoLog.h" | |
| #include "libANGLE/ProgramExecutable.h" | |
| #include "libANGLE/ProgramLinkedResources.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 ProgramExecutable; | |
| class Shader; | |
| class ShaderProgramManager; | |
| class State; | |
| struct UnusedUniform; | |
| struct Version; | |
| extern const char *const g_fakepath; | |
| enum class LinkMismatchError | |
| { | |
| // Shared | |
| NO_MISMATCH, | |
| TYPE_MISMATCH, | |
| ARRAYNESS_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, | |
| FORMAT_MISMATCH, | |
| // Interface block specific | |
| LAYOUT_QUALIFIER_MISMATCH, | |
| MATRIX_PACKING_MISMATCH, | |
| // I/O block specific | |
| FIELD_LOCATION_MISMATCH, | |
| FIELD_STRUCT_NAME_MISMATCH, | |
| }; | |
| 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); | |
| void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var); | |
| void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var); | |
| void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block); | |
| void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block); | |
| void WriteShInterfaceBlock(BinaryOutputStream *stream, const sh::InterfaceBlock &block); | |
| void LoadShInterfaceBlock(BinaryInputStream *stream, sh::InterfaceBlock *block); | |
| void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var); | |
| void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *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; | |
| }; | |
| 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::ShaderVariable &variable) const; | |
| using const_iterator = angle::HashMap<std::string, GLuint>::const_iterator; | |
| const_iterator begin() const; | |
| const_iterator end() const; | |
| std::map<std::string, GLuint> getStableIterationMap() const; | |
| private: | |
| angle::HashMap<std::string, GLuint> mBindings; | |
| }; | |
| // Uniforms and Fragment Outputs require special treatment due to array notation (e.g., "[0]") | |
| class ProgramAliasedBindings final : angle::NonCopyable | |
| { | |
| public: | |
| ProgramAliasedBindings(); | |
| ~ProgramAliasedBindings(); | |
| void bindLocation(GLuint index, const std::string &name); | |
| int getBindingByName(const std::string &name) const; | |
| int getBindingByLocation(GLuint location) const; | |
| int getBinding(const sh::ShaderVariable &variable) const; | |
| using const_iterator = angle::HashMap<std::string, ProgramBinding>::const_iterator; | |
| const_iterator begin() const; | |
| const_iterator end() const; | |
| std::map<std::string, ProgramBinding> getStableIterationMap() const; | |
| private: | |
| angle::HashMap<std::string, ProgramBinding> mBindings; | |
| }; | |
| 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 mExecutable->getTransformFeedbackBufferMode(); | |
| } | |
| GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const | |
| { | |
| return mExecutable->getUniformBlockBinding(uniformBlockIndex); | |
| } | |
| GLuint getShaderStorageBlockBinding(GLuint blockIndex) const | |
| { | |
| return mExecutable->getShaderStorageBlockBinding(blockIndex); | |
| } | |
| const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const | |
| { | |
| return mExecutable->getActiveUniformBlockBindings(); | |
| } | |
| const std::vector<sh::ShaderVariable> &getProgramInputs() const | |
| { | |
| return mExecutable->getProgramInputs(); | |
| } | |
| const std::vector<sh::ShaderVariable> &getOutputVariables() const | |
| { | |
| return mExecutable->getOutputVariables(); | |
| } | |
| const std::vector<VariableLocation> &getOutputLocations() const | |
| { | |
| return mExecutable->getOutputLocations(); | |
| } | |
| const std::vector<VariableLocation> &getSecondaryOutputLocations() const | |
| { | |
| return mExecutable->getSecondaryOutputLocations(); | |
| } | |
| const std::vector<LinkedUniform> &getUniforms() const { return mExecutable->getUniforms(); } | |
| const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; } | |
| const std::vector<InterfaceBlock> &getUniformBlocks() const | |
| { | |
| return mExecutable->getUniformBlocks(); | |
| } | |
| const std::vector<InterfaceBlock> &getShaderStorageBlocks() const | |
| { | |
| return mExecutable->getShaderStorageBlocks(); | |
| } | |
| const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; } | |
| const std::vector<SamplerBinding> &getSamplerBindings() const | |
| { | |
| return mExecutable->getSamplerBindings(); | |
| } | |
| const std::vector<ImageBinding> &getImageBindings() const | |
| { | |
| return getExecutable().getImageBindings(); | |
| } | |
| const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } | |
| const RangeUI &getDefaultUniformRange() const { return mExecutable->getDefaultUniformRange(); } | |
| const RangeUI &getSamplerUniformRange() const { return mExecutable->getSamplerUniformRange(); } | |
| const RangeUI &getImageUniformRange() const { return mExecutable->getImageUniformRange(); } | |
| const RangeUI &getAtomicCounterUniformRange() const | |
| { | |
| return mExecutable->getAtomicCounterUniformRange(); | |
| } | |
| const RangeUI &getFragmentInoutRange() const { return mExecutable->getFragmentInoutRange(); } | |
| const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const | |
| { | |
| return mExecutable->getLinkedTransformFeedbackVaryings(); | |
| } | |
| const std::vector<GLsizei> &getTransformFeedbackStrides() const | |
| { | |
| return mExecutable->getTransformFeedbackStrides(); | |
| } | |
| const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const | |
| { | |
| return mExecutable->getAtomicCounterBuffers(); | |
| } | |
| GLuint getUniformIndexFromName(const std::string &name) const; | |
| GLuint getUniformIndexFromLocation(UniformLocation location) const; | |
| Optional<GLuint> getSamplerIndex(UniformLocation 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 getAttributeLocation(const std::string &name) const; | |
| GLuint getBufferVariableIndexFromName(const std::string &name) const; | |
| int getNumViews() const { return mNumViews; } | |
| bool usesMultiview() const { return mNumViews != -1; } | |
| bool hasAttachedShader() const; | |
| ShaderType getFirstAttachedShaderStageType() const; | |
| ShaderType getLastAttachedShaderStageType() const; | |
| const ProgramAliasedBindings &getUniformLocationBindings() const | |
| { | |
| return mUniformLocationBindings; | |
| } | |
| const ProgramExecutable &getExecutable() const | |
| { | |
| ASSERT(mExecutable); | |
| return *mExecutable; | |
| } | |
| ProgramExecutable &getExecutable() | |
| { | |
| ASSERT(mExecutable); | |
| return *mExecutable; | |
| } | |
| bool hasImages() const { return !getImageBindings().empty(); } | |
| rx::SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; } | |
| // A Program can only either be graphics or compute, but never both, so it | |
| // can answer isCompute() based on which shaders it has. | |
| bool isCompute() const { return mExecutable->hasLinkedShaderStage(ShaderType::Compute); } | |
| const std::string &getLabel() const { return mLabel; } | |
| uint32_t getLocationsUsedForXfbExtension() const { return mLocationsUsedForXfbExtension; } | |
| bool hasBinaryRetrieveableHint() const { return mBinaryRetrieveableHint; } | |
| bool isSeparable() const { return mSeparable; } | |
| int getDrawIDLocation() const { return mDrawIDLocation; } | |
| int getBaseVertexLocation() const { return mBaseVertexLocation; } | |
| int getBaseInstanceLocation() const { return mBaseInstanceLocation; } | |
| ShaderType getAttachedTransformFeedbackStage() const; | |
| private: | |
| friend class MemoryProgramCache; | |
| friend class Program; | |
| void updateActiveSamplers(); | |
| void updateProgramInterfaceInputs(); | |
| void updateProgramInterfaceOutputs(); | |
| // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. | |
| void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex); | |
| std::string mLabel; | |
| sh::WorkGroupSize mComputeShaderLocalSize; | |
| ShaderMap<Shader *> mAttachedShaders; | |
| uint32_t mLocationsUsedForXfbExtension; | |
| std::vector<std::string> mTransformFeedbackVaryingNames; | |
| std::vector<VariableLocation> mUniformLocations; | |
| std::vector<BufferVariable> mBufferVariables; | |
| bool mBinaryRetrieveableHint; | |
| bool mSeparable; | |
| rx::SpecConstUsageBits mSpecConstUsageBits; | |
| // ANGLE_multiview. | |
| int mNumViews; | |
| // GL_ANGLE_multi_draw | |
| int mDrawIDLocation; | |
| // GL_ANGLE_base_vertex_base_instance_shader_builtin | |
| int mBaseVertexLocation; | |
| int mBaseInstanceLocation; | |
| // Cached value of base vertex and base instance | |
| // need to reset them to zero if using non base vertex or base instance draw calls. | |
| GLint mCachedBaseVertex; | |
| GLuint mCachedBaseInstance; | |
| // 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. | |
| ProgramAliasedBindings mUniformLocationBindings; | |
| std::shared_ptr<ProgramExecutable> mExecutable; | |
| }; | |
| struct ProgramVaryingRef | |
| { | |
| const sh::ShaderVariable *get(ShaderType stage) const | |
| { | |
| ASSERT(stage == frontShaderStage || stage == backShaderStage); | |
| const sh::ShaderVariable *ref = stage == frontShaderStage ? frontShader : backShader; | |
| ASSERT(ref); | |
| return ref; | |
| } | |
| const sh::ShaderVariable *frontShader = nullptr; | |
| const sh::ShaderVariable *backShader = nullptr; | |
| ShaderType frontShaderStage = ShaderType::InvalidEnum; | |
| ShaderType backShaderStage = ShaderType::InvalidEnum; | |
| }; | |
| using ProgramMergedVaryings = std::vector<ProgramVaryingRef>; | |
| class Program final : public LabeledObject, public angle::Subject | |
| { | |
| public: | |
| Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle); | |
| void onDestroy(const Context *context); | |
| ShaderProgramID 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(!mLinkingState); | |
| return mProgram; | |
| } | |
| void attachShader(Shader *shader); | |
| void detachShader(const Context *context, Shader *shader); | |
| int getAttachedShadersCount() const; | |
| Shader *getAttachedShader(ShaderType shaderType) const; | |
| void bindAttributeLocation(GLuint index, const char *name); | |
| void bindUniformLocation(UniformLocation location, const char *name); | |
| // 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 asynchronously. 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 hasLinkingState() const { return mLinkingState != nullptr; } | |
| bool isLinked() const | |
| { | |
| ASSERT(!mLinkingState); | |
| return mLinked; | |
| } | |
| 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; | |
| void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const; | |
| GLuint getAttributeLocation(const std::string &name) 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::ShaderVariable> &getAttributes() const; | |
| GLint getFragDataLocation(const std::string &name) const; | |
| size_t getOutputResourceCount() const; | |
| // 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(UniformLocation location) const; | |
| const LinkedUniform &getUniformByLocation(UniformLocation location) const; | |
| const VariableLocation &getUniformLocation(UniformLocation location) const; | |
| const std::vector<VariableLocation> &getUniformLocations() const | |
| { | |
| ASSERT(!mLinkingState); | |
| return mState.mUniformLocations; | |
| } | |
| const LinkedUniform &getUniformByIndex(GLuint index) const | |
| { | |
| ASSERT(!mLinkingState); | |
| return mState.mExecutable->getUniformByIndex(index); | |
| } | |
| const BufferVariable &getBufferVariableByIndex(GLuint index) const; | |
| enum SetUniformResult | |
| { | |
| SamplerChanged, | |
| NoSamplerChange, | |
| }; | |
| UniformLocation getUniformLocation(const std::string &name) const; | |
| GLuint getUniformIndex(const std::string &name) const; | |
| void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v); | |
| void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v); | |
| void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v); | |
| void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v); | |
| void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v); | |
| void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v); | |
| void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v); | |
| void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v); | |
| void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v); | |
| void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v); | |
| void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v); | |
| void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v); | |
| void setUniformMatrix2fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix3fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix4fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix2x3fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix3x2fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix2x4fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix4x2fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix3x4fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void setUniformMatrix4x3fv(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const GLfloat *value); | |
| void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const; | |
| void getUniformiv(const Context *context, UniformLocation location, GLint *params) const; | |
| void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const; | |
| void getActiveUniformBlockName(const UniformBlockIndex 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(!mLinkingState); | |
| return static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()); | |
| } | |
| ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const | |
| { | |
| ASSERT(!mLinkingState); | |
| return static_cast<GLuint>(mState.mExecutable->getActiveAtomicCounterBufferCount()); | |
| } | |
| ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const | |
| { | |
| ASSERT(!mLinkingState); | |
| return static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()); | |
| } | |
| GLint getActiveUniformBlockMaxNameLength() const; | |
| GLint getActiveShaderStorageBlockMaxNameLength() const; | |
| const std::vector<LinkedUniform> &getUniforms() const { return mState.getUniforms(); } | |
| GLuint getUniformBlockIndex(const std::string &name) const; | |
| GLuint getShaderStorageBlockIndex(const std::string &name) const; | |
| void bindUniformBlock(UniformBlockIndex 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); | |
| bool hasBaseVertexUniform() const; | |
| void setBaseVertexUniform(GLint baseVertex); | |
| bool hasBaseInstanceUniform() const; | |
| void setBaseInstanceUniform(GLuint baseInstance); | |
| ANGLE_INLINE void addRef() | |
| { | |
| ASSERT(!mLinkingState); | |
| mRefCount++; | |
| } | |
| ANGLE_INLINE void release(const Context *context) | |
| { | |
| ASSERT(!mLinkingState); | |
| 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 isValidated() const; | |
| const std::vector<ImageBinding> &getImageBindings() const | |
| { | |
| ASSERT(!mLinkingState); | |
| return getExecutable().getImageBindings(); | |
| } | |
| const sh::WorkGroupSize &getComputeShaderLocalSize() const; | |
| PrimitiveMode getGeometryShaderInputPrimitiveType() const; | |
| PrimitiveMode getGeometryShaderOutputPrimitiveType() const; | |
| GLint getGeometryShaderInvocations() const; | |
| GLint getGeometryShaderMaxVertices() const; | |
| GLint getTessControlShaderVertices() const; | |
| GLenum getTessGenMode() const; | |
| GLenum getTessGenPointMode() const; | |
| GLenum getTessGenSpacing() const; | |
| GLenum getTessGenVertexOrder() const; | |
| const ProgramState &getState() const | |
| { | |
| ASSERT(!mLinkingState); | |
| return mState; | |
| } | |
| 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::ShaderVariable &getInputResource(size_t index) const; | |
| GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const; | |
| GLuint getInputResourceMaxNameSize() const; | |
| GLuint getOutputResourceMaxNameSize() const; | |
| GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const; | |
| GLuint getInputResourceLocation(const GLchar *name) const; | |
| GLuint getOutputResourceLocation(const GLchar *name) const; | |
| const std::string getResourceName(const sh::ShaderVariable &resource) const; | |
| const std::string getInputResourceName(GLuint index) const; | |
| const std::string getOutputResourceName(GLuint index) const; | |
| const sh::ShaderVariable &getOutputResource(size_t index) const; | |
| const ProgramBindings &getAttributeBindings() const; | |
| const ProgramAliasedBindings &getUniformLocationBindings() const; | |
| const ProgramAliasedBindings &getFragmentOutputLocations() const; | |
| const ProgramAliasedBindings &getFragmentOutputIndexes() const; | |
| int getNumViews() const | |
| { | |
| ASSERT(!mLinkingState); | |
| return mState.getNumViews(); | |
| } | |
| bool usesMultiview() const { return mState.usesMultiview(); } | |
| const std::vector<GLsizei> &getTransformFeedbackStrides() const; | |
| // 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 (mLinkingState) | |
| { | |
| resolveLinkImpl(context); | |
| } | |
| } | |
| ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); } | |
| // Writes a program's binary to the output memory buffer. | |
| angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const; | |
| rx::Serial serial() const { return mSerial; } | |
| const ProgramExecutable &getExecutable() const { return mState.getExecutable(); } | |
| ProgramExecutable &getExecutable() { return mState.getExecutable(); } | |
| 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); | |
| angle::Result linkImpl(const Context *context); | |
| bool linkValidateShaders(InfoLog &infoLog); | |
| bool linkAttributes(const Context *context, InfoLog &infoLog); | |
| bool linkVaryings(InfoLog &infoLog) const; | |
| bool linkUniforms(const Context *context, | |
| std::vector<UnusedUniform> *unusedUniformsOutOrNull, | |
| GLuint *combinedImageUniformsOut, | |
| InfoLog &infoLog); | |
| void updateLinkedShaderStages(); | |
| void setUniformValuesFromBindingQualifiers(); | |
| bool shouldIgnoreUniform(UniformLocation location) const; | |
| 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(UniformLocation 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, | |
| UniformLocation location, | |
| GLenum nativeType, | |
| int components) const; | |
| void getResourceName(const std::string name, | |
| GLsizei bufSize, | |
| GLsizei *length, | |
| GLchar *dest) const; | |
| template <typename T> | |
| GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const; | |
| GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const; | |
| GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const; | |
| // Block until linking is finished and resolve it. | |
| void resolveLinkImpl(const gl::Context *context); | |
| void postResolveLink(const gl::Context *context); | |
| template <typename UniformT, | |
| GLint UniformSize, | |
| void (rx::ProgramImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)> | |
| void setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v); | |
| template < | |
| typename UniformT, | |
| GLint MatrixC, | |
| GLint MatrixR, | |
| void (rx::ProgramImpl::*SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)> | |
| void setUniformMatrixGeneric(UniformLocation location, | |
| GLsizei count, | |
| GLboolean transpose, | |
| const UniformT *v); | |
| rx::Serial mSerial; | |
| ProgramState mState; | |
| rx::ProgramImpl *mProgram; | |
| bool mValidated; | |
| ProgramBindings mAttributeBindings; | |
| // EXT_blend_func_extended | |
| ProgramAliasedBindings mFragmentOutputLocations; | |
| ProgramAliasedBindings mFragmentOutputIndexes; | |
| bool mLinked; | |
| 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 ShaderProgramID mHandle; | |
| DirtyBits mDirtyBits; | |
| }; | |
| } // namespace gl | |
| #endif // LIBANGLE_PROGRAM_H_ |