diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/Program.h | 897 |
1 files changed, 897 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..0b7b62480b --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/Program.h @@ -0,0 +1,897 @@ +// +// 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(const Context *context); + void updateProgramInterfaceOutputs(const Context *context); + + // 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; + + angle::Result 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 Context *context, + 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(const Context *context, InfoLog &infoLog); + bool linkAttributes(const Context *context, InfoLog &infoLog); + bool linkVaryings(const Context *context, 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; + + std::mutex mHistogramMutex; +}; +} // namespace gl + +#endif // LIBANGLE_PROGRAM_H_ |