// // 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 LIBGLESV2_PROGRAM_BINARY_H_ #define LIBGLESV2_PROGRAM_BINARY_H_ #include "angle_gl.h" #include #include #include "common/RefCountObject.h" #include "angletypes.h" #include "common/mathutil.h" #include "libGLESv2/Uniform.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Constants.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/DynamicHLSL.h" namespace sh { class HLSLBlockEncoder; } namespace rx { class ShaderExecutable; class Renderer; struct TranslatedAttribute; class UniformStorage; } namespace gl { class FragmentShader; class VertexShader; class InfoLog; class AttributeBindings; class Buffer; class Framebuffer; // 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; }; struct LinkedVarying { LinkedVarying(); LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, unsigned int semanticIndex, unsigned int semanticIndexCount); // Original GL name std::string name; GLenum type; GLsizei size; // DirectX semantic information std::string semanticName; unsigned int semanticIndex; unsigned int semanticIndexCount; }; // This is the result of linking a program. It is the state that would be passed to ProgramBinary. class ProgramBinary : public RefCountObject { public: explicit ProgramBinary(rx::Renderer *renderer); ~ProgramBinary(); rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo); rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector &outputLayout); rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]); rx::ShaderExecutable *getGeometryExecutable() const; GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex); TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; bool usesPointSpriteEmulation() const; bool usesGeometryShader() const; GLint getUniformLocation(std::string name); GLuint getUniformIndex(std::string name); GLuint getUniformBlockIndex(std::string name); 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); 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(); bool applyUniformBuffers(const std::vector boundBuffers); bool load(InfoLog &infoLog, const void *binary, GLsizei length); bool save(void* binary, GLsizei bufSize, GLsizei *length); GLint getLength(); bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; GLint getActiveAttributeCount() const; GLint getActiveAttributeMaxLength() 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; LinkedUniform *getUniformByLocation(GLint location) const; LinkedUniform *getUniformByName(const std::string &name) const; void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; GLuint getActiveUniformBlockCount() const; GLuint getActiveUniformBlockMaxLength() const; UniformBlock *getUniformBlockByIndex(GLuint blockIndex); GLint getFragDataLocation(const char *name) const; size_t getTransformFeedbackVaryingCount() const; const LinkedVarying &getTransformFeedbackVarying(size_t idx) const; GLenum getTransformFeedbackBufferMode() const; void validate(InfoLog &infoLog); bool validateSamplers(InfoLog *infoLog); bool isValidated() const; void updateSamplerMapping(); unsigned int getSerial() const; int getShaderVersion() const; void initAttributesByLayout(); void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; const std::vector &getUniforms() const { return mUniforms; } const rx::UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } const rx::UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); struct Sampler { Sampler(); bool active; GLint logicalTextureUnit; TextureType textureType; }; void reset(); bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); template bool linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar); bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable, bool validatePrecision); bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); bool linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); void defineUniform(GLenum shader, const sh::Uniform &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog); bool indexUniforms(InfoLog &infoLog); static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, Sampler *outArray, GLuint *usedRange, unsigned int limit); bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); bool linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, const std::vector &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, std::vector *outTransformFeedbackLinkedVaryings) const; void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes); bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock); bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex); void defineOutputVariables(FragmentShader *fragmentShader); void initializeUniformStorage(); template void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); template void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); template bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType); class VertexExecutable { public: VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS], const GLenum signature[MAX_VERTEX_ATTRIBS], rx::ShaderExecutable *shaderExecutable); ~VertexExecutable(); bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const; const VertexFormat *inputs() const { return mInputs; } const GLenum *signature() const { return mSignature; } rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } private: VertexFormat mInputs[MAX_VERTEX_ATTRIBS]; GLenum mSignature[MAX_VERTEX_ATTRIBS]; rx::ShaderExecutable *mShaderExecutable; }; class PixelExecutable { public: PixelExecutable(const std::vector &outputSignature, rx::ShaderExecutable *shaderExecutable); ~PixelExecutable(); // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers bool matchesSignature(const std::vector &signature) const { return true; /* mOutputSignature == signature; */ } const std::vector &outputSignature() const { return mOutputSignature; } rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } private: std::vector mOutputSignature; rx::ShaderExecutable *mShaderExecutable; }; rx::Renderer *const mRenderer; DynamicHLSL *mDynamicHLSL; std::string mVertexHLSL; rx::D3DWorkaroundType mVertexWorkarounds; std::vector mVertexExecutables; std::string mPixelHLSL; rx::D3DWorkaroundType mPixelWorkarounds; bool mUsesFragDepth; std::vector mPixelShaderKey; std::vector mPixelExecutables; rx::ShaderExecutable *mGeometryExecutable; sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS]; int mSemanticIndex[MAX_VERTEX_ATTRIBS]; int mAttributesByLayout[MAX_VERTEX_ATTRIBS]; GLenum mTransformFeedbackBufferMode; std::vector mTransformFeedbackLinkedVaryings; Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mUsesPointSize; int mShaderVersion; bool mDirtySamplerMapping; std::vector mUniforms; std::vector mUniformBlocks; std::vector mUniformIndex; std::map mOutputVariables; rx::UniformStorage *mVertexUniformStorage; rx::UniformStorage *mFragmentUniformStorage; bool mValidated; const unsigned int mSerial; static unsigned int issueSerial(); static unsigned int mCurrentSerial; }; } #endif // LIBGLESV2_PROGRAM_BINARY_H_