// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Program.h: Defines the Program class. Implements GL program objects // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. #ifndef LIBGLESV2_PROGRAM_H_ #define LIBGLESV2_PROGRAM_H_ #include "Shader.h" #include "Context.h" #include "Shader/PixelShader.hpp" #include "Shader/VertexShader.hpp" #include <string> #include <vector> #include <set> #include <map> namespace es2 { class Device; class ResourceManager; class FragmentShader; class VertexShader; // Helper struct representing a single shader uniform struct Uniform { struct BlockInfo { BlockInfo(const glsl::Uniform& uniform, int blockIndex); int index = -1; int offset = -1; int arrayStride = -1; int matrixStride = -1; bool isRowMajorMatrix = false; }; Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo); ~Uniform(); bool isArray() const; int size() const; int registerCount() const; const GLenum type; const GLenum precision; const std::string name; const unsigned int arraySize; const BlockInfo blockInfo; std::vector<glsl::ShaderVariable> fields; unsigned char *data = nullptr; bool dirty = true; short psRegisterIndex = -1; short vsRegisterIndex = -1; }; // Helper struct representing a single shader uniform block struct UniformBlock { // use GL_INVALID_INDEX for non-array elements UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize, std::vector<unsigned int> memberUniformIndexes); void setRegisterIndex(GLenum shader, unsigned int registerIndex); bool isArrayElement() const; bool isReferencedByVertexShader() const; bool isReferencedByFragmentShader() const; const std::string name; const unsigned int elementIndex; const unsigned int dataSize; std::vector<unsigned int> memberUniformIndexes; unsigned int psRegisterIndex; unsigned int vsRegisterIndex; }; // Struct used for correlating uniforms/elements of uniform arrays to handles struct UniformLocation { UniformLocation(const std::string &name, unsigned int element, unsigned int index); std::string name; unsigned int element; unsigned int index; }; struct LinkedVarying { LinkedVarying(); LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col); // Original GL name std::string name; GLenum type; GLsizei size; int reg; // First varying register, assigned during link int col; // First register element, assigned during link }; class Program { public: Program(ResourceManager *manager, GLuint handle); ~Program(); bool attachShader(Shader *shader); bool detachShader(Shader *shader); int getAttachedShadersCount() const; sw::PixelShader *getPixelShader(); sw::VertexShader *getVertexShader(); void bindAttributeLocation(GLuint index, const char *name); GLint getAttributeLocation(const char *name); int getAttributeStream(int attributeIndex); GLint getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex); TextureType getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex); GLuint getUniformIndex(const std::string &name) const; GLuint getUniformBlockIndex(const std::string &name) const; void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; GLint getUniformLocation(const std::string &name) const; bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v); bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v); bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v); bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v); bool setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); bool setUniform1iv(GLint location, GLsizei count, const GLint *v); bool setUniform2iv(GLint location, GLsizei count, const GLint *v); bool setUniform3iv(GLint location, GLsizei count, const GLint *v); bool setUniform4iv(GLint location, GLsizei count, const GLint *v); bool setUniform1uiv(GLint location, GLsizei count, const GLuint *v); bool setUniform2uiv(GLint location, GLsizei count, const GLuint *v); bool setUniform3uiv(GLint location, GLsizei count, const GLuint *v); bool setUniform4uiv(GLint location, GLsizei count, const GLuint *v); bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); bool getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params); void dirtyAllUniforms(); void applyUniforms(Device *device); void applyUniformBuffers(Device *device, BufferBinding* uniformBuffers); void applyTransformFeedback(Device *device, TransformFeedback* transformFeedback); void link(); bool isLinked() const; size_t getInfoLogLength() const; void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); GLint getFragDataLocation(const GLchar *name); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; size_t getActiveAttributeCount() const; GLint getActiveAttributeMaxLength() const; void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; size_t getActiveUniformCount() const; GLint getActiveUniformMaxLength() const; GLint getActiveUniformi(GLuint index, GLenum pname) const; void getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; size_t getActiveUniformBlockCount() const; GLint getActiveUniformBlockMaxLength() 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; void addRef(); void release(); unsigned int getRefCount() const; void flagForDeletion(); bool isFlaggedForDeletion() const; void validate(Device* device); bool validateSamplers(bool logErrors); bool isValidated() const; unsigned int getSerial() const; bool getBinaryRetrievableHint() const { return retrievableBinary; } void setBinaryRetrievable(bool retrievable) { retrievableBinary = retrievable; } GLint getBinaryLength() const; private: void unlink(); void resetUniformBlockBindings(); bool linkVaryings(); bool linkTransformFeedback(); bool linkAttributes(); bool linkAttribute(const glsl::Attribute &attribute, int location, unsigned int &usedLocations); int getAttributeLocation(const std::string &name); Uniform *getUniform(const std::string &name) const; bool linkUniforms(const Shader *shader); bool linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader); bool areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2); bool areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name); bool validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct); bool defineUniform(GLenum shader, const glsl::Uniform &uniform, const Uniform::BlockInfo& blockInfo); bool defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block); bool applyUniform(Device *device, GLint location, float* data); bool applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v); bool applyUniform2bv(Device *device, GLint location, GLsizei count, const GLboolean *v); bool applyUniform3bv(Device *device, GLint location, GLsizei count, const GLboolean *v); bool applyUniform4bv(Device *device, GLint location, GLsizei count, const GLboolean *v); bool applyUniform1fv(Device *device, GLint location, GLsizei count, const GLfloat *v); bool applyUniform2fv(Device *device, GLint location, GLsizei count, const GLfloat *v); bool applyUniform3fv(Device *device, GLint location, GLsizei count, const GLfloat *v); bool applyUniform4fv(Device *device, GLint location, GLsizei count, const GLfloat *v); bool applyUniformMatrix2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix2x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix2x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix3x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix3x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix4x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniformMatrix4x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); bool applyUniform1iv(Device *device, GLint location, GLsizei count, const GLint *v); bool applyUniform2iv(Device *device, GLint location, GLsizei count, const GLint *v); bool applyUniform3iv(Device *device, GLint location, GLsizei count, const GLint *v); bool applyUniform4iv(Device *device, GLint location, GLsizei count, const GLint *v); bool applyUniform1uiv(Device *device, GLint location, GLsizei count, const GLuint *v); bool applyUniform2uiv(Device *device, GLint location, GLsizei count, const GLuint *v); bool applyUniform3uiv(Device *device, GLint location, GLsizei count, const GLuint *v); bool applyUniform4uiv(Device *device, GLint location, GLsizei count, const GLuint *v); bool setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements); bool setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum type); bool setUniformiv(GLint location, GLsizei count, const GLint *v, int numElements); bool setUniformuiv(GLint location, GLsizei count, const GLuint *v, int numElements); void appendToInfoLog(const char *info, ...); void resetInfoLog(); static unsigned int issueSerial(); FragmentShader *fragmentShader; VertexShader *vertexShader; sw::PixelShader *pixelBinary; sw::VertexShader *vertexBinary; std::map<std::string, GLuint> attributeBinding; std::map<std::string, GLuint> linkedAttributeLocation; std::vector<glsl::Attribute> linkedAttribute; int attributeStream[MAX_VERTEX_ATTRIBS]; GLuint uniformBlockBindings[MAX_UNIFORM_BUFFER_BINDINGS]; std::vector<std::string> transformFeedbackVaryings; GLenum transformFeedbackBufferMode; size_t totalLinkedVaryingsComponents; struct Sampler { bool active; GLint logicalTextureUnit; TextureType textureType; }; Sampler samplersPS[MAX_TEXTURE_IMAGE_UNITS]; Sampler samplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS]; typedef std::vector<Uniform*> UniformArray; UniformArray uniforms; typedef std::vector<Uniform> UniformStructArray; UniformStructArray uniformStructs; typedef std::vector<UniformLocation> UniformIndex; UniformIndex uniformIndex; typedef std::vector<UniformBlock*> UniformBlockArray; UniformBlockArray uniformBlocks; typedef std::vector<LinkedVarying> LinkedVaryingArray; LinkedVaryingArray transformFeedbackLinkedVaryings; bool linked; bool orphaned; // Flag to indicate that the program can be deleted when no longer in use char *infoLog; bool validated; bool retrievableBinary; unsigned int referenceCount; const unsigned int serial; static unsigned int currentSerial; ResourceManager *resourceManager; const GLuint handle; }; } #endif // LIBGLESV2_PROGRAM_H_