| 1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | // Program.h: Defines the Program class. Implements GL program objects |
| 16 | // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. |
| 17 | |
| 18 | #ifndef LIBGLESV2_PROGRAM_H_ |
| 19 | #define LIBGLESV2_PROGRAM_H_ |
| 20 | |
| 21 | #include "Shader.h" |
| 22 | #include "Context.h" |
| 23 | #include "Shader/PixelShader.hpp" |
| 24 | #include "Shader/VertexShader.hpp" |
| 25 | |
| 26 | #include <string> |
| 27 | #include <vector> |
| 28 | #include <set> |
| 29 | #include <map> |
| 30 | |
| 31 | namespace es2 |
| 32 | { |
| 33 | class Device; |
| 34 | class ResourceManager; |
| 35 | class FragmentShader; |
| 36 | class VertexShader; |
| 37 | |
| 38 | // Helper struct representing a single shader uniform |
| 39 | struct Uniform |
| 40 | { |
| 41 | struct BlockInfo |
| 42 | { |
| 43 | BlockInfo(const glsl::Uniform& uniform, int blockIndex); |
| 44 | |
| 45 | int index = -1; |
| 46 | int offset = -1; |
| 47 | int arrayStride = -1; |
| 48 | int matrixStride = -1; |
| 49 | bool isRowMajorMatrix = false; |
| 50 | }; |
| 51 | |
| 52 | Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo); |
| 53 | |
| 54 | ~Uniform(); |
| 55 | |
| 56 | bool isArray() const; |
| 57 | int size() const; |
| 58 | int registerCount() const; |
| 59 | |
| 60 | const GLenum type; |
| 61 | const GLenum precision; |
| 62 | const std::string name; |
| 63 | const unsigned int arraySize; |
| 64 | const BlockInfo blockInfo; |
| 65 | std::vector<glsl::ShaderVariable> fields; |
| 66 | |
| 67 | unsigned char *data = nullptr; |
| 68 | bool dirty = true; |
| 69 | |
| 70 | short psRegisterIndex = -1; |
| 71 | short vsRegisterIndex = -1; |
| 72 | }; |
| 73 | |
| 74 | // Helper struct representing a single shader uniform block |
| 75 | struct UniformBlock |
| 76 | { |
| 77 | // use GL_INVALID_INDEX for non-array elements |
| 78 | UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize, std::vector<unsigned int> memberUniformIndexes); |
| 79 | |
| 80 | void setRegisterIndex(GLenum shader, unsigned int registerIndex); |
| 81 | |
| 82 | bool isArrayElement() const; |
| 83 | bool isReferencedByVertexShader() const; |
| 84 | bool isReferencedByFragmentShader() const; |
| 85 | |
| 86 | const std::string name; |
| 87 | const unsigned int elementIndex; |
| 88 | const unsigned int dataSize; |
| 89 | |
| 90 | std::vector<unsigned int> memberUniformIndexes; |
| 91 | |
| 92 | unsigned int psRegisterIndex; |
| 93 | unsigned int vsRegisterIndex; |
| 94 | }; |
| 95 | |
| 96 | // Struct used for correlating uniforms/elements of uniform arrays to handles |
| 97 | struct UniformLocation |
| 98 | { |
| 99 | UniformLocation(const std::string &name, unsigned int element, unsigned int index); |
| 100 | |
| 101 | std::string name; |
| 102 | unsigned int element; |
| 103 | unsigned int index; |
| 104 | }; |
| 105 | |
| 106 | struct LinkedVarying |
| 107 | { |
| 108 | LinkedVarying(); |
| 109 | LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col); |
| 110 | |
| 111 | // Original GL name |
| 112 | std::string name; |
| 113 | |
| 114 | GLenum type; |
| 115 | GLsizei size; |
| 116 | |
| 117 | int reg; // First varying register, assigned during link |
| 118 | int col; // First register element, assigned during link |
| 119 | }; |
| 120 | |
| 121 | class Program |
| 122 | { |
| 123 | public: |
| 124 | Program(ResourceManager *manager, GLuint handle); |
| 125 | |
| 126 | ~Program(); |
| 127 | |
| 128 | bool attachShader(Shader *shader); |
| 129 | bool detachShader(Shader *shader); |
| 130 | int getAttachedShadersCount() const; |
| 131 | |
| 132 | sw::PixelShader *getPixelShader(); |
| 133 | sw::VertexShader *getVertexShader(); |
| 134 | |
| 135 | void bindAttributeLocation(GLuint index, const char *name); |
| 136 | GLint getAttributeLocation(const char *name); |
| 137 | int getAttributeStream(int attributeIndex); |
| 138 | |
| 139 | GLint getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex); |
| 140 | TextureType getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex); |
| 141 | |
| 142 | GLuint getUniformIndex(const std::string &name) const; |
| 143 | GLuint getUniformBlockIndex(const std::string &name) const; |
| 144 | void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); |
| 145 | GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; |
| 146 | void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; |
| 147 | |
| 148 | GLint getUniformLocation(const std::string &name) const; |
| 149 | bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v); |
| 150 | bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v); |
| 151 | bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v); |
| 152 | bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v); |
| 153 | bool setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 154 | bool setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 155 | bool setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 156 | bool setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 157 | bool setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 158 | bool setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 159 | bool setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 160 | bool setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 161 | bool setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); |
| 162 | bool setUniform1iv(GLint location, GLsizei count, const GLint *v); |
| 163 | bool setUniform2iv(GLint location, GLsizei count, const GLint *v); |
| 164 | bool setUniform3iv(GLint location, GLsizei count, const GLint *v); |
| 165 | bool setUniform4iv(GLint location, GLsizei count, const GLint *v); |
| 166 | bool setUniform1uiv(GLint location, GLsizei count, const GLuint *v); |
| 167 | bool setUniform2uiv(GLint location, GLsizei count, const GLuint *v); |
| 168 | bool setUniform3uiv(GLint location, GLsizei count, const GLuint *v); |
| 169 | bool setUniform4uiv(GLint location, GLsizei count, const GLuint *v); |
| 170 | |
| 171 | bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); |
| 172 | bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); |
| 173 | bool getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params); |
| 174 | |
| 175 | void dirtyAllUniforms(); |
| 176 | void applyUniforms(Device *device); |
| 177 | void applyUniformBuffers(Device *device, BufferBinding* uniformBuffers); |
| 178 | void applyTransformFeedback(Device *device, TransformFeedback* transformFeedback); |
| 179 | |
| 180 | void link(); |
| 181 | bool isLinked() const; |
| 182 | size_t getInfoLogLength() const; |
| 183 | void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); |
| 184 | void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); |
| 185 | |
| 186 | GLint getFragDataLocation(const GLchar *name); |
| 187 | |
| 188 | void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; |
| 189 | size_t getActiveAttributeCount() const; |
| 190 | GLint getActiveAttributeMaxLength() const; |
| 191 | |
| 192 | void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; |
| 193 | size_t getActiveUniformCount() const; |
| 194 | GLint getActiveUniformMaxLength() const; |
| 195 | GLint getActiveUniformi(GLuint index, GLenum pname) const; |
| 196 | |
| 197 | void getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; |
| 198 | size_t getActiveUniformBlockCount() const; |
| 199 | GLint getActiveUniformBlockMaxLength() const; |
| 200 | |
| 201 | void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); |
| 202 | void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; |
| 203 | GLsizei getTransformFeedbackVaryingCount() const; |
| 204 | GLsizei getTransformFeedbackVaryingMaxLength() const; |
| 205 | GLenum getTransformFeedbackBufferMode() const; |
| 206 | |
| 207 | void addRef(); |
| 208 | void release(); |
| 209 | unsigned int getRefCount() const; |
| 210 | void flagForDeletion(); |
| 211 | bool isFlaggedForDeletion() const; |
| 212 | |
| 213 | void validate(Device* device); |
| 214 | bool validateSamplers(bool logErrors); |
| 215 | bool isValidated() const; |
| 216 | |
| 217 | unsigned int getSerial() const; |
| 218 | |
| 219 | bool getBinaryRetrievableHint() const { return retrievableBinary; } |
| 220 | void setBinaryRetrievable(bool retrievable) { retrievableBinary = retrievable; } |
| 221 | GLint getBinaryLength() const; |
| 222 | |
| 223 | private: |
| 224 | void unlink(); |
| 225 | void resetUniformBlockBindings(); |
| 226 | |
| 227 | bool linkVaryings(); |
| 228 | bool linkTransformFeedback(); |
| 229 | |
| 230 | bool linkAttributes(); |
| 231 | bool linkAttribute(const glsl::Attribute &attribute, int location, unsigned int &usedLocations); |
| 232 | int getAttributeLocation(const std::string &name); |
| 233 | |
| 234 | Uniform *getUniform(const std::string &name) const; |
| 235 | bool linkUniforms(const Shader *shader); |
| 236 | bool linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader); |
| 237 | bool areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2); |
| 238 | bool areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name); |
| 239 | bool validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct); |
| 240 | bool defineUniform(GLenum shader, const glsl::Uniform &uniform, const Uniform::BlockInfo& blockInfo); |
| 241 | bool defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block); |
| 242 | bool applyUniform(Device *device, GLint location, float* data); |
| 243 | bool applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
| 244 | bool applyUniform2bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
| 245 | bool applyUniform3bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
| 246 | bool applyUniform4bv(Device *device, GLint location, GLsizei count, const GLboolean *v); |
| 247 | bool applyUniform1fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
| 248 | bool applyUniform2fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
| 249 | bool applyUniform3fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
| 250 | bool applyUniform4fv(Device *device, GLint location, GLsizei count, const GLfloat *v); |
| 251 | bool applyUniformMatrix2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 252 | bool applyUniformMatrix2x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 253 | bool applyUniformMatrix2x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 254 | bool applyUniformMatrix3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 255 | bool applyUniformMatrix3x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 256 | bool applyUniformMatrix3x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 257 | bool applyUniformMatrix4fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 258 | bool applyUniformMatrix4x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 259 | bool applyUniformMatrix4x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value); |
| 260 | bool applyUniform1iv(Device *device, GLint location, GLsizei count, const GLint *v); |
| 261 | bool applyUniform2iv(Device *device, GLint location, GLsizei count, const GLint *v); |
| 262 | bool applyUniform3iv(Device *device, GLint location, GLsizei count, const GLint *v); |
| 263 | bool applyUniform4iv(Device *device, GLint location, GLsizei count, const GLint *v); |
| 264 | bool applyUniform1uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
| 265 | bool applyUniform2uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
| 266 | bool applyUniform3uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
| 267 | bool applyUniform4uiv(Device *device, GLint location, GLsizei count, const GLuint *v); |
| 268 | |
| 269 | bool setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements); |
| 270 | bool setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum type); |
| 271 | bool setUniformiv(GLint location, GLsizei count, const GLint *v, int numElements); |
| 272 | bool setUniformuiv(GLint location, GLsizei count, const GLuint *v, int numElements); |
| 273 | |
| 274 | void appendToInfoLog(const char *info, ...); |
| 275 | void resetInfoLog(); |
| 276 | |
| 277 | static unsigned int issueSerial(); |
| 278 | |
| 279 | FragmentShader *fragmentShader; |
| 280 | VertexShader *vertexShader; |
| 281 | |
| 282 | sw::PixelShader *pixelBinary; |
| 283 | sw::VertexShader *vertexBinary; |
| 284 | |
| 285 | std::map<std::string, GLuint> attributeBinding; |
| 286 | std::map<std::string, GLuint> linkedAttributeLocation; |
| 287 | std::vector<glsl::Attribute> linkedAttribute; |
| 288 | int attributeStream[MAX_VERTEX_ATTRIBS]; |
| 289 | |
| 290 | GLuint uniformBlockBindings[MAX_UNIFORM_BUFFER_BINDINGS]; |
| 291 | |
| 292 | std::vector<std::string> transformFeedbackVaryings; |
| 293 | GLenum transformFeedbackBufferMode; |
| 294 | size_t totalLinkedVaryingsComponents; |
| 295 | |
| 296 | struct Sampler |
| 297 | { |
| 298 | bool active; |
| 299 | GLint logicalTextureUnit; |
| 300 | TextureType textureType; |
| 301 | }; |
| 302 | |
| 303 | Sampler samplersPS[MAX_TEXTURE_IMAGE_UNITS]; |
| 304 | Sampler samplersVS[MAX_VERTEX_TEXTURE_IMAGE_UNITS]; |
| 305 | |
| 306 | typedef std::vector<Uniform*> UniformArray; |
| 307 | UniformArray uniforms; |
| 308 | typedef std::vector<Uniform> UniformStructArray; |
| 309 | UniformStructArray uniformStructs; |
| 310 | typedef std::vector<UniformLocation> UniformIndex; |
| 311 | UniformIndex uniformIndex; |
| 312 | typedef std::vector<UniformBlock*> UniformBlockArray; |
| 313 | UniformBlockArray uniformBlocks; |
| 314 | typedef std::vector<LinkedVarying> LinkedVaryingArray; |
| 315 | LinkedVaryingArray transformFeedbackLinkedVaryings; |
| 316 | |
| 317 | bool linked; |
| 318 | bool orphaned; // Flag to indicate that the program can be deleted when no longer in use |
| 319 | char *infoLog; |
| 320 | bool validated; |
| 321 | bool retrievableBinary; |
| 322 | |
| 323 | unsigned int referenceCount; |
| 324 | const unsigned int serial; |
| 325 | |
| 326 | static unsigned int currentSerial; |
| 327 | |
| 328 | ResourceManager *resourceManager; |
| 329 | const GLuint handle; |
| 330 | }; |
| 331 | } |
| 332 | |
| 333 | #endif // LIBGLESV2_PROGRAM_H_ |
| 334 | |