diff options
Diffstat (limited to 'libs/angle/src/libANGLE/Program.h')
-rw-r--r-- | libs/angle/src/libANGLE/Program.h | 498 |
1 files changed, 498 insertions, 0 deletions
diff --git a/libs/angle/src/libANGLE/Program.h b/libs/angle/src/libANGLE/Program.h new file mode 100644 index 000000000..03212a5cd --- /dev/null +++ b/libs/angle/src/libANGLE/Program.h @@ -0,0 +1,498 @@ +// +// 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/ShaderLang.h> + +#include <set> +#include <sstream> +#include <string> +#include <vector> + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "common/Optional.h" + +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Debug.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +namespace rx +{ +class GLImplFactory; +class ProgramImpl; +struct TranslatedAttribute; +} + +namespace gl +{ +struct Caps; +class ContextState; +class ResourceManager; +class Shader; +class InfoLog; +class Buffer; +class Framebuffer; +struct UniformBlock; +struct LinkedUniform; + +extern const char * const g_fakepath; + +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) + { + StreamHelper helper(&mStream); + helper << value; + return helper; + } + + std::string str() const { return mStream.str(); } + + private: + std::stringstream mStream; +}; + +// Struct used for correlating uniforms/elements of uniform arrays to handles +struct VariableLocation +{ + VariableLocation(); + VariableLocation(const std::string &name, unsigned int element, unsigned int index); + + std::string name; + unsigned int element; + unsigned int index; + + // If this is a valid uniform location + bool used; + + // 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; +}; + +class ProgramState final : angle::NonCopyable +{ + public: + ProgramState(); + ~ProgramState(); + + const std::string &getLabel(); + + const Shader *getAttachedVertexShader() const { return mAttachedVertexShader; } + const Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; } + const Shader *getAttachedComputeShader() const { return mAttachedComputeShader; } + const std::vector<std::string> &getTransformFeedbackVaryingNames() const + { + return mTransformFeedbackVaryingNames; + } + GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } + GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const + { + ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + return mUniformBlockBindings[uniformBlockIndex]; + } + const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const + { + return mActiveUniformBlockBindings; + } + const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; } + const AttributesMask &getActiveAttribLocationsMask() const + { + return mActiveAttribLocationsMask; + } + const std::map<int, VariableLocation> &getOutputVariables() const { return mOutputVariables; } + const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; } + const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; } + const std::vector<UniformBlock> &getUniformBlocks() const { return mUniformBlocks; } + + const LinkedUniform *getUniformByName(const std::string &name) const; + GLint getUniformLocation(const std::string &name) const; + GLuint getUniformIndex(const std::string &name) const; + + private: + friend class Program; + + std::string mLabel; + + sh::WorkGroupSize mComputeShaderLocalSize; + + Shader *mAttachedFragmentShader; + Shader *mAttachedVertexShader; + Shader *mAttachedComputeShader; + + std::vector<std::string> mTransformFeedbackVaryingNames; + std::vector<sh::Varying> mTransformFeedbackVaryingVars; + GLenum mTransformFeedbackBufferMode; + + GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + UniformBlockBindingMask mActiveUniformBlockBindings; + + std::vector<sh::Attribute> mAttributes; + std::bitset<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask; + + // Uniforms are sorted in order: + // 1. Non-sampler uniforms + // 2. Sampler uniforms + // 3. Uniform block uniforms + // This makes sampler validation easier, since we don't need a separate list. + std::vector<LinkedUniform> mUniforms; + std::vector<VariableLocation> mUniformLocations; + std::vector<UniformBlock> mUniformBlocks; + + // TODO(jmadill): use unordered/hash map when available + std::map<int, VariableLocation> mOutputVariables; + + bool mBinaryRetrieveableHint; +}; + +class Program final : angle::NonCopyable, public LabeledObject +{ + public: + Program(rx::GLImplFactory *factory, ResourceManager *manager, GLuint handle); + ~Program(); + + GLuint id() const { return mHandle; } + + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + + rx::ProgramImpl *getImplementation() { return mProgram; } + const rx::ProgramImpl *getImplementation() const { return mProgram; } + + bool attachShader(Shader *shader); + bool detachShader(Shader *shader); + int getAttachedShadersCount() 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); + + Error link(const ContextState &data); + bool isLinked() const; + + Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length); + Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const; + GLint getBinaryLength() const; + void setBinaryRetrievableHint(bool retrievable); + bool getBinaryRetrievableHint() 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); + GLint getActiveAttributeCount() const; + GLint getActiveAttributeMaxLength() const; + const std::vector<sh::Attribute> &getAttributes() const { return mState.mAttributes; } + + GLint getFragDataLocation(const std::string &name) const; + + void getActiveUniform(GLuint index, + GLsizei bufsize, + GLsizei *length, + GLint *size, + GLenum *type, + GLchar *name) const; + GLint getActiveUniformCount() const; + GLint getActiveUniformMaxLength() const; + GLint getActiveUniformi(GLuint index, GLenum pname) const; + bool isValidUniformLocation(GLint location) const; + bool isIgnoredUniformLocation(GLint location) const; + const LinkedUniform &getUniformByLocation(GLint location) const; + + GLint getUniformLocation(const std::string &name) const; + GLuint getUniformIndex(const std::string &name) const; + void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform1iv(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(GLint location, GLfloat *params) const; + void getUniformiv(GLint location, GLint *params) const; + void getUniformuiv(GLint location, GLuint *params) const; + + void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; + void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; + GLuint getActiveUniformBlockCount() const; + GLint getActiveUniformBlockMaxLength() const; + + GLuint getUniformBlockIndex(const std::string &name) const; + + void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); + GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; + + const UniformBlock &getUniformBlockByIndex(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; + + static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); + static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); + + void addRef(); + void release(); + unsigned int getRefCount() const; + void flagForDeletion(); + bool isFlaggedForDeletion() const; + + void validate(const Caps &caps); + bool validateSamplers(InfoLog *infoLog, const Caps &caps); + bool isValidated() const; + + const AttributesMask &getActiveAttribLocationsMask() const + { + return mState.mActiveAttribLocationsMask; + } + + private: + class Bindings final : angle::NonCopyable + { + public: + void bindLocation(GLuint index, const std::string &name); + int getBinding(const std::string &name) const; + + typedef std::unordered_map<std::string, GLuint>::const_iterator const_iterator; + const_iterator begin() const; + const_iterator end() const; + + private: + std::unordered_map<std::string, GLuint> mBindings; + }; + + void unlink(bool destroy = false); + void resetUniformBlockBindings(); + + bool linkAttributes(const ContextState &data, + InfoLog &infoLog, + const Bindings &attributeBindings, + const Shader *vertexShader); + bool validateUniformBlocksCount(GLuint maxUniformBlocks, + const std::vector<sh::InterfaceBlock> &block, + const std::string &errorMessage, + InfoLog &infoLog) const; + bool validateVertexAndFragmentInterfaceBlocks( + const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks, + const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks, + InfoLog &infoLog) const; + bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps); + bool linkVaryings(InfoLog &infoLog, const Shader *vertexShader, const Shader *fragmentShader) const; + bool validateVertexAndFragmentUniforms(InfoLog &infoLog) const; + bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps, const Bindings &uniformBindings); + bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps, const Bindings &uniformBindings); + bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, + const sh::InterfaceBlock &vertexInterfaceBlock, + const sh::InterfaceBlock &fragmentInterfaceBlock) const; + + static bool linkValidateVariablesBase(InfoLog &infoLog, + const std::string &variableName, + const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, + bool validatePrecision); + + static bool linkValidateVaryings(InfoLog &infoLog, + const std::string &varyingName, + const sh::Varying &vertexVarying, + const sh::Varying &fragmentVarying, + int shaderVersion); + bool linkValidateTransformFeedback(InfoLog &infoLog, + const std::vector<const sh::Varying *> &linkedVaryings, + const Caps &caps) const; + + void gatherTransformFeedbackVaryings(const std::vector<const sh::Varying *> &varyings); + bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); + void defineOutputVariables(Shader *fragmentShader); + + std::vector<const sh::Varying *> getMergedVaryings() const; + void linkOutputVariables(); + + bool flattenUniformsAndCheckCapsForShader(const gl::Shader &shader, + GLuint maxUniformComponents, + GLuint maxTextureImageUnits, + const std::string &componentsErrorMessage, + const std::string &samplerErrorMessage, + std::vector<LinkedUniform> &samplerUniforms, + InfoLog &infoLog); + bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog); + + struct VectorAndSamplerCount + { + VectorAndSamplerCount() : vectorCount(0), samplerCount(0) {} + VectorAndSamplerCount(const VectorAndSamplerCount &other) = default; + VectorAndSamplerCount &operator=(const VectorAndSamplerCount &other) = default; + + VectorAndSamplerCount &operator+=(const VectorAndSamplerCount &other) + { + vectorCount += other.vectorCount; + samplerCount += other.samplerCount; + return *this; + } + + unsigned int vectorCount; + unsigned int samplerCount; + }; + + VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform, + const std::string &fullName, + std::vector<LinkedUniform> *samplerUniforms); + + void gatherInterfaceBlockInfo(); + template <typename VarT> + void defineUniformBlockMembers(const std::vector<VarT> &fields, + const std::string &prefix, + int blockIndex); + + void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType); + + template <typename T> + void setUniformInternal(GLint location, GLsizei count, const T *v); + + template <size_t cols, size_t rows, typename T> + void setMatrixUniformInternal(GLint location, GLsizei count, GLboolean transpose, const T *v); + + template <typename DestT> + void getUniformInternal(GLint location, DestT *dataOut) const; + + ProgramState mState; + rx::ProgramImpl *mProgram; + + bool mValidated; + + Bindings mAttributeBindings; + Bindings mUniformBindings; + + // CHROMIUM_path_rendering + Bindings mFragmentInputBindings; + + bool mLinked; + bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use + + unsigned int mRefCount; + + ResourceManager *mResourceManager; + const GLuint mHandle; + + InfoLog mInfoLog; + + // Cache for sampler validation + Optional<bool> mCachedValidateSamplersResult; + std::vector<GLenum> mTextureUnitTypesCache; + RangeUI mSamplerUniformRange; +}; +} + +#endif // LIBANGLE_PROGRAM_H_ |