1 // 2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Program.h: Defines the gl::Program class. Implements GL program objects 8 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28. 9 10 #ifndef LIBANGLE_PROGRAM_H_ 11 #define LIBANGLE_PROGRAM_H_ 12 13 #include <GLES2/gl2.h> 14 #include <GLSLANG/ShaderVars.h> 15 16 #include <array> 17 #include <map> 18 #include <set> 19 #include <sstream> 20 #include <string> 21 #include <vector> 22 23 #include "common/angleutils.h" 24 #include "common/mathutil.h" 25 #include "common/Optional.h" 26 27 #include "libANGLE/Constants.h" 28 #include "libANGLE/Debug.h" 29 #include "libANGLE/Error.h" 30 #include "libANGLE/RefCountObject.h" 31 #include "libANGLE/Uniform.h" 32 #include "libANGLE/angletypes.h" 33 34 namespace rx 35 { 36 class GLImplFactory; 37 class ProgramImpl; 38 struct TranslatedAttribute; 39 } 40 41 namespace gl 42 { 43 struct Caps; 44 class Context; 45 class ContextState; 46 class Shader; 47 class ShaderProgramManager; 48 class State; 49 class InfoLog; 50 class Buffer; 51 class Framebuffer; 52 53 extern const char * const g_fakepath; 54 55 class InfoLog : angle::NonCopyable 56 { 57 public: 58 InfoLog(); 59 ~InfoLog(); 60 61 size_t getLength() const; 62 void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; 63 64 void appendSanitized(const char *message); 65 void reset(); 66 67 // This helper class ensures we append a newline after writing a line. 68 class StreamHelper : angle::NonCopyable 69 { 70 public: StreamHelper(StreamHelper && rhs)71 StreamHelper(StreamHelper &&rhs) 72 : mStream(rhs.mStream) 73 { 74 rhs.mStream = nullptr; 75 } 76 77 StreamHelper &operator=(StreamHelper &&rhs) 78 { 79 std::swap(mStream, rhs.mStream); 80 return *this; 81 } 82 ~StreamHelper()83 ~StreamHelper() 84 { 85 // Write newline when destroyed on the stack 86 if (mStream) 87 { 88 (*mStream) << std::endl; 89 } 90 } 91 92 template <typename T> 93 StreamHelper &operator<<(const T &value) 94 { 95 (*mStream) << value; 96 return *this; 97 } 98 99 private: 100 friend class InfoLog; 101 StreamHelper(std::stringstream * stream)102 StreamHelper(std::stringstream *stream) 103 : mStream(stream) 104 { 105 ASSERT(stream); 106 } 107 108 std::stringstream *mStream; 109 }; 110 111 template <typename T> 112 StreamHelper operator<<(const T &value) 113 { 114 ensureInitialized(); 115 StreamHelper helper(mLazyStream.get()); 116 helper << value; 117 return helper; 118 } 119 str()120 std::string str() const { return mLazyStream ? mLazyStream->str() : ""; } 121 122 private: ensureInitialized()123 void ensureInitialized() 124 { 125 if (!mLazyStream) 126 { 127 mLazyStream.reset(new std::stringstream()); 128 } 129 } 130 131 std::unique_ptr<std::stringstream> mLazyStream; 132 }; 133 134 // Struct used for correlating uniforms/elements of uniform arrays to handles 135 struct VariableLocation 136 { 137 static constexpr unsigned int kUnused = GL_INVALID_INDEX; 138 139 VariableLocation(); 140 VariableLocation(unsigned int arrayIndex, unsigned int index); 141 142 // If used is false, it means this location is only used to fill an empty space in an array, 143 // and there is no corresponding uniform variable for this location. It can also mean the 144 // uniform was optimized out by the implementation. usedVariableLocation145 bool used() const { return (index != kUnused); } markUnusedVariableLocation146 void markUnused() { index = kUnused; } markIgnoredVariableLocation147 void markIgnored() { ignored = true; } 148 149 // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays. 150 unsigned int arrayIndex; 151 // "index" is an index of the variable. The variable contains the indices for other than the 152 // innermost GLSL arrays. 153 unsigned int index; 154 155 // If this location was bound to an unreferenced uniform. Setting data on this uniform is a 156 // no-op. 157 bool ignored; 158 }; 159 160 // Information about a variable binding. 161 // Currently used by CHROMIUM_path_rendering 162 struct BindingInfo 163 { 164 // The type of binding, for example GL_FLOAT_VEC3. 165 // This can be GL_NONE if the variable is optimized away. 166 GLenum type; 167 168 // This is the name of the variable in 169 // the translated shader program. Note that 170 // this can be empty in the case where the 171 // variable has been optimized away. 172 std::string name; 173 174 // True if the binding is valid, otherwise false. 175 bool valid; 176 }; 177 178 // This small structure encapsulates binding sampler uniforms to active GL textures. 179 struct SamplerBinding 180 { 181 SamplerBinding(GLenum textureTypeIn, size_t elementCount, bool unreferenced); 182 SamplerBinding(const SamplerBinding &other); 183 ~SamplerBinding(); 184 185 // Necessary for retrieving active textures from the GL state. 186 GLenum textureType; 187 188 // List of all textures bound to this sampler, of type textureType. 189 std::vector<GLuint> boundTextureUnits; 190 191 // A note if this sampler is an unreferenced uniform. 192 bool unreferenced; 193 }; 194 195 // A varying with tranform feedback enabled. If it's an array, either the whole array or one of its 196 // elements specified by 'arrayIndex' can set to be enabled. 197 struct TransformFeedbackVarying : public sh::Varying 198 { TransformFeedbackVaryingTransformFeedbackVarying199 TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index) 200 : sh::Varying(varyingIn), arrayIndex(index) 201 { 202 ASSERT(!isArrayOfArrays()); 203 } nameWithArrayIndexTransformFeedbackVarying204 std::string nameWithArrayIndex() const 205 { 206 std::stringstream fullNameStr; 207 fullNameStr << name; 208 if (arrayIndex != GL_INVALID_INDEX) 209 { 210 fullNameStr << "[" << arrayIndex << "]"; 211 } 212 return fullNameStr.str(); 213 } sizeTransformFeedbackVarying214 GLsizei size() const 215 { 216 return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1); 217 } 218 219 GLuint arrayIndex; 220 }; 221 222 struct ImageBinding 223 { 224 ImageBinding(size_t count); 225 ImageBinding(GLuint imageUnit, size_t count); 226 ImageBinding(const ImageBinding &other); 227 ~ImageBinding(); 228 229 std::vector<GLuint> boundImageUnits; 230 }; 231 232 using ShaderStagesMask = angle::BitSet<SHADER_TYPE_MAX>; 233 234 class ProgramState final : angle::NonCopyable 235 { 236 public: 237 ProgramState(); 238 ~ProgramState(); 239 240 const std::string &getLabel(); 241 getAttachedVertexShader()242 Shader *getAttachedVertexShader() const { return mAttachedVertexShader; } getAttachedFragmentShader()243 Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; } getAttachedComputeShader()244 Shader *getAttachedComputeShader() const { return mAttachedComputeShader; } getAttachedGeometryShader()245 Shader *getAttachedGeometryShader() const { return mAttachedGeometryShader; } getTransformFeedbackVaryingNames()246 const std::vector<std::string> &getTransformFeedbackVaryingNames() const 247 { 248 return mTransformFeedbackVaryingNames; 249 } getTransformFeedbackBufferMode()250 GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } getUniformBlockBinding(GLuint uniformBlockIndex)251 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const 252 { 253 ASSERT(uniformBlockIndex < mUniformBlocks.size()); 254 return mUniformBlocks[uniformBlockIndex].binding; 255 } getShaderStorageBlockBinding(GLuint blockIndex)256 GLuint getShaderStorageBlockBinding(GLuint blockIndex) const 257 { 258 ASSERT(blockIndex < mShaderStorageBlocks.size()); 259 return mShaderStorageBlocks[blockIndex].binding; 260 } getActiveUniformBlockBindingsMask()261 const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const 262 { 263 return mActiveUniformBlockBindings; 264 } getAttributes()265 const std::vector<sh::Attribute> &getAttributes() const { return mAttributes; } getActiveAttribLocationsMask()266 const AttributesMask &getActiveAttribLocationsMask() const 267 { 268 return mActiveAttribLocationsMask; 269 } getMaxActiveAttribLocation()270 unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; } getActiveOutputVariables()271 DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; } getOutputVariables()272 const std::vector<sh::OutputVariable> &getOutputVariables() const { return mOutputVariables; } getOutputLocations()273 const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; } getUniforms()274 const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; } getUniformLocations()275 const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; } getUniformBlocks()276 const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } getShaderStorageBlocks()277 const std::vector<InterfaceBlock> &getShaderStorageBlocks() const 278 { 279 return mShaderStorageBlocks; 280 } getBufferVariables()281 const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; } getSamplerBindings()282 const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; } getImageBindings()283 const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; } getComputeShaderLocalSize()284 const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } getSamplerUniformRange()285 const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; } getImageUniformRange()286 const RangeUI &getImageUniformRange() const { return mImageUniformRange; } getAtomicCounterUniformRange()287 const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; } 288 getLinkedTransformFeedbackVaryings()289 const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const 290 { 291 return mLinkedTransformFeedbackVaryings; 292 } getAtomicCounterBuffers()293 const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const 294 { 295 return mAtomicCounterBuffers; 296 } 297 298 GLuint getUniformIndexFromName(const std::string &name) const; 299 GLuint getUniformIndexFromLocation(GLint location) const; 300 Optional<GLuint> getSamplerIndex(GLint location) const; 301 bool isSamplerUniformIndex(GLuint index) const; 302 GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const; 303 GLuint getAttributeLocation(const std::string &name) const; 304 305 GLuint getBufferVariableIndexFromName(const std::string &name) const; 306 getNumViews()307 int getNumViews() const { return mNumViews; } usesMultiview()308 bool usesMultiview() const { return mNumViews != -1; } 309 getLinkedShaderStages()310 const ShaderStagesMask &getLinkedShaderStages() const { return mLinkedShaderStages; } 311 312 private: 313 friend class MemoryProgramCache; 314 friend class Program; 315 316 std::string mLabel; 317 318 sh::WorkGroupSize mComputeShaderLocalSize; 319 320 Shader *mAttachedFragmentShader; 321 Shader *mAttachedVertexShader; 322 Shader *mAttachedComputeShader; 323 Shader *mAttachedGeometryShader; 324 325 std::vector<std::string> mTransformFeedbackVaryingNames; 326 std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings; 327 GLenum mTransformFeedbackBufferMode; 328 329 // For faster iteration on the blocks currently being bound. 330 UniformBlockBindingMask mActiveUniformBlockBindings; 331 332 std::vector<sh::Attribute> mAttributes; 333 angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask; 334 unsigned int mMaxActiveAttribLocation; 335 336 // Uniforms are sorted in order: 337 // 1. Non-opaque uniforms 338 // 2. Sampler uniforms 339 // 3. Image uniforms 340 // 4. Atomic counter uniforms 341 // 5. Uniform block uniforms 342 // This makes opaque uniform validation easier, since we don't need a separate list. 343 // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section 344 // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each 345 // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include 346 // [0] in the end. This makes implementation of queries simpler. 347 std::vector<LinkedUniform> mUniforms; 348 349 std::vector<VariableLocation> mUniformLocations; 350 std::vector<InterfaceBlock> mUniformBlocks; 351 std::vector<BufferVariable> mBufferVariables; 352 std::vector<InterfaceBlock> mShaderStorageBlocks; 353 std::vector<AtomicCounterBuffer> mAtomicCounterBuffers; 354 RangeUI mSamplerUniformRange; 355 RangeUI mImageUniformRange; 356 RangeUI mAtomicCounterUniformRange; 357 358 // An array of the samplers that are used by the program 359 std::vector<gl::SamplerBinding> mSamplerBindings; 360 361 // An array of the images that are used by the program 362 std::vector<gl::ImageBinding> mImageBindings; 363 364 // Names and mapped names of output variables that are arrays include [0] in the end, similarly 365 // to uniforms. 366 std::vector<sh::OutputVariable> mOutputVariables; 367 std::vector<VariableLocation> mOutputLocations; 368 DrawBufferMask mActiveOutputVariables; 369 370 // Fragment output variable base types: FLOAT, INT, or UINT. Ordered by location. 371 std::vector<GLenum> mOutputVariableTypes; 372 373 bool mBinaryRetrieveableHint; 374 bool mSeparable; 375 ShaderStagesMask mLinkedShaderStages; 376 377 // ANGLE_multiview. 378 int mNumViews; 379 }; 380 381 class Program final : angle::NonCopyable, public LabeledObject 382 { 383 public: 384 Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle); 385 void onDestroy(const Context *context); 386 id()387 GLuint id() const { return mHandle; } 388 389 void setLabel(const std::string &label) override; 390 const std::string &getLabel() const override; 391 getImplementation()392 rx::ProgramImpl *getImplementation() const { return mProgram; } 393 394 void attachShader(Shader *shader); 395 void detachShader(const Context *context, Shader *shader); 396 int getAttachedShadersCount() const; 397 getAttachedVertexShader()398 const Shader *getAttachedVertexShader() const { return mState.mAttachedVertexShader; } getAttachedFragmentShader()399 const Shader *getAttachedFragmentShader() const { return mState.mAttachedFragmentShader; } getAttachedComputeShader()400 const Shader *getAttachedComputeShader() const { return mState.mAttachedComputeShader; } getAttachedGeometryShader()401 const Shader *getAttachedGeometryShader() const { return mState.mAttachedGeometryShader; } 402 403 void bindAttributeLocation(GLuint index, const char *name); 404 void bindUniformLocation(GLuint index, const char *name); 405 406 // CHROMIUM_path_rendering 407 BindingInfo getFragmentInputBindingInfo(const Context *context, GLint index) const; 408 void bindFragmentInputLocation(GLint index, const char *name); 409 void pathFragmentInputGen(const Context *context, 410 GLint index, 411 GLenum genMode, 412 GLint components, 413 const GLfloat *coeffs); 414 415 Error link(const gl::Context *context); 416 bool isLinked() const; 417 hasLinkedVertexShader()418 bool hasLinkedVertexShader() const { return mState.mLinkedShaderStages[SHADER_VERTEX]; } hasLinkedFragmentShader()419 bool hasLinkedFragmentShader() const { return mState.mLinkedShaderStages[SHADER_FRAGMENT]; } hasLinkedComputeShader()420 bool hasLinkedComputeShader() const { return mState.mLinkedShaderStages[SHADER_COMPUTE]; } 421 422 Error loadBinary(const Context *context, 423 GLenum binaryFormat, 424 const void *binary, 425 GLsizei length); 426 Error saveBinary(const Context *context, 427 GLenum *binaryFormat, 428 void *binary, 429 GLsizei bufSize, 430 GLsizei *length) const; 431 GLint getBinaryLength(const Context *context) const; 432 void setBinaryRetrievableHint(bool retrievable); 433 bool getBinaryRetrievableHint() const; 434 435 void setSeparable(bool separable); 436 bool isSeparable() const; 437 438 int getInfoLogLength() const; 439 void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; 440 void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const; 441 442 GLuint getAttributeLocation(const std::string &name) const; 443 bool isAttribLocationActive(size_t attribLocation) const; 444 445 void getActiveAttribute(GLuint index, 446 GLsizei bufsize, 447 GLsizei *length, 448 GLint *size, 449 GLenum *type, 450 GLchar *name) const; 451 GLint getActiveAttributeCount() const; 452 GLint getActiveAttributeMaxLength() const; getAttributes()453 const std::vector<sh::Attribute> &getAttributes() const { return mState.mAttributes; } 454 455 GLint getFragDataLocation(const std::string &name) const; 456 size_t getOutputResourceCount() const; getOutputVariableTypes()457 const std::vector<GLenum> &getOutputVariableTypes() const 458 { 459 return mState.mOutputVariableTypes; 460 } getActiveOutputVariables()461 DrawBufferMask getActiveOutputVariables() const { return mState.mActiveOutputVariables; } 462 463 void getActiveUniform(GLuint index, 464 GLsizei bufsize, 465 GLsizei *length, 466 GLint *size, 467 GLenum *type, 468 GLchar *name) const; 469 GLint getActiveUniformCount() const; 470 size_t getActiveBufferVariableCount() const; 471 GLint getActiveUniformMaxLength() const; 472 bool isValidUniformLocation(GLint location) const; 473 const LinkedUniform &getUniformByLocation(GLint location) const; 474 const VariableLocation &getUniformLocation(GLint location) const; 475 const std::vector<VariableLocation> &getUniformLocations() const; 476 const LinkedUniform &getUniformByIndex(GLuint index) const; 477 478 const BufferVariable &getBufferVariableByIndex(GLuint index) const; 479 480 enum SetUniformResult 481 { 482 SamplerChanged, 483 NoSamplerChange, 484 }; 485 486 GLint getUniformLocation(const std::string &name) const; 487 GLuint getUniformIndex(const std::string &name) const; 488 void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); 489 void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); 490 void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); 491 void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); 492 SetUniformResult setUniform1iv(GLint location, GLsizei count, const GLint *v); 493 void setUniform2iv(GLint location, GLsizei count, const GLint *v); 494 void setUniform3iv(GLint location, GLsizei count, const GLint *v); 495 void setUniform4iv(GLint location, GLsizei count, const GLint *v); 496 void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); 497 void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); 498 void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); 499 void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); 500 void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 501 void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 502 void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 503 void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 504 void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 505 void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 506 void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 507 void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 508 void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 509 510 void getUniformfv(const Context *context, GLint location, GLfloat *params) const; 511 void getUniformiv(const Context *context, GLint location, GLint *params) const; 512 void getUniformuiv(const Context *context, GLint location, GLuint *params) const; 513 514 void getActiveUniformBlockName(const GLuint blockIndex, 515 GLsizei bufSize, 516 GLsizei *length, 517 GLchar *blockName) const; 518 void getActiveShaderStorageBlockName(const GLuint blockIndex, 519 GLsizei bufSize, 520 GLsizei *length, 521 GLchar *blockName) const; 522 GLuint getActiveUniformBlockCount() const; 523 GLuint getActiveAtomicCounterBufferCount() const; 524 GLuint getActiveShaderStorageBlockCount() const; 525 GLint getActiveUniformBlockMaxLength() const; 526 527 GLuint getUniformBlockIndex(const std::string &name) const; 528 GLuint getShaderStorageBlockIndex(const std::string &name) const; 529 530 void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); 531 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; 532 GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const; 533 534 const InterfaceBlock &getUniformBlockByIndex(GLuint index) const; 535 const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const; 536 537 void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); 538 void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; 539 GLsizei getTransformFeedbackVaryingCount() const; 540 GLsizei getTransformFeedbackVaryingMaxLength() const; 541 GLenum getTransformFeedbackBufferMode() const; 542 543 static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, 544 const std::string &uniformName, 545 const sh::InterfaceBlockField &vertexUniform, 546 const sh::InterfaceBlockField &fragmentUniform, 547 bool webglCompatibility); 548 549 void addRef(); 550 void release(const Context *context); 551 unsigned int getRefCount() const; 552 void flagForDeletion(); 553 bool isFlaggedForDeletion() const; 554 555 void validate(const Caps &caps); 556 bool validateSamplers(InfoLog *infoLog, const Caps &caps); 557 bool isValidated() const; 558 bool samplesFromTexture(const gl::State &state, GLuint textureID) const; 559 getActiveAttribLocationsMask()560 const AttributesMask &getActiveAttribLocationsMask() const 561 { 562 return mState.mActiveAttribLocationsMask; 563 } 564 getSamplerBindings()565 const std::vector<SamplerBinding> &getSamplerBindings() const 566 { 567 return mState.mSamplerBindings; 568 } 569 getImageBindings()570 const std::vector<ImageBinding> &getImageBindings() const { return mState.mImageBindings; } getComputeShaderLocalSize()571 const sh::WorkGroupSize &getComputeShaderLocalSize() const 572 { 573 return mState.mComputeShaderLocalSize; 574 } 575 getState()576 const ProgramState &getState() const { return mState; } 577 578 static bool linkValidateVariablesBase(InfoLog &infoLog, 579 const std::string &variableName, 580 const sh::ShaderVariable &vertexVariable, 581 const sh::ShaderVariable &fragmentVariable, 582 bool validatePrecision); 583 584 GLuint getInputResourceIndex(const GLchar *name) const; 585 GLuint getOutputResourceIndex(const GLchar *name) const; 586 void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 587 void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 588 void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 589 void getBufferVariableResourceName(GLuint index, 590 GLsizei bufSize, 591 GLsizei *length, 592 GLchar *name) const; 593 const sh::Attribute &getInputResource(GLuint index) const; 594 const sh::OutputVariable &getOutputResource(GLuint index) const; 595 596 class Bindings final : angle::NonCopyable 597 { 598 public: 599 Bindings(); 600 ~Bindings(); 601 void bindLocation(GLuint index, const std::string &name); 602 int getBinding(const std::string &name) const; 603 604 typedef std::unordered_map<std::string, GLuint>::const_iterator const_iterator; 605 const_iterator begin() const; 606 const_iterator end() const; 607 608 private: 609 std::unordered_map<std::string, GLuint> mBindings; 610 }; 611 getAttributeBindings()612 const Bindings &getAttributeBindings() const { return mAttributeBindings; } getUniformLocationBindings()613 const Bindings &getUniformLocationBindings() const { return mUniformLocationBindings; } getFragmentInputBindings()614 const Bindings &getFragmentInputBindings() const { return mFragmentInputBindings; } 615 getNumViews()616 int getNumViews() const { return mState.getNumViews(); } usesMultiview()617 bool usesMultiview() const { return mState.usesMultiview(); } 618 619 struct VaryingRef 620 { getVaryingRef621 const sh::Varying *get() const { return vertex ? vertex : fragment; } 622 623 const sh::Varying *vertex = nullptr; 624 const sh::Varying *fragment = nullptr; 625 }; 626 using MergedVaryings = std::map<std::string, VaryingRef>; 627 628 private: 629 ~Program() override; 630 631 void unlink(); 632 633 bool linkAttributes(const Context *context, InfoLog &infoLog); 634 bool validateVertexAndFragmentInterfaceBlocks( 635 const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks, 636 const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks, 637 InfoLog &infoLog, 638 bool webglCompatibility) const; 639 bool linkInterfaceBlocks(const Context *context, InfoLog &infoLog); 640 bool linkVaryings(const Context *context, InfoLog &infoLog) const; 641 642 bool linkUniforms(const Context *context, 643 InfoLog &infoLog, 644 const Bindings &uniformLocationBindings); 645 void linkSamplerAndImageBindings(); 646 bool linkAtomicCounterBuffers(); 647 648 void updateLinkedShaderStages(); 649 650 bool areMatchingInterfaceBlocks(InfoLog &infoLog, 651 const sh::InterfaceBlock &vertexInterfaceBlock, 652 const sh::InterfaceBlock &fragmentInterfaceBlock, 653 bool webglCompatibility) const; 654 655 static bool linkValidateVaryings(InfoLog &infoLog, 656 const std::string &varyingName, 657 const sh::Varying &vertexVarying, 658 const sh::Varying &fragmentVarying, 659 int shaderVersion); 660 bool linkValidateBuiltInVaryings(const Context *context, InfoLog &infoLog) const; 661 bool linkValidateTransformFeedback(const gl::Context *context, 662 InfoLog &infoLog, 663 const MergedVaryings &linkedVaryings, 664 const Caps &caps) const; 665 bool linkValidateGlobalNames(const Context *context, InfoLog &infoLog) const; 666 667 void gatherTransformFeedbackVaryings(const MergedVaryings &varyings); 668 669 MergedVaryings getMergedVaryings(const Context *context) const; 670 void linkOutputVariables(const Context *context); 671 672 void setUniformValuesFromBindingQualifiers(); 673 674 void gatherAtomicCounterBuffers(); 675 void initInterfaceBlockBindings(); 676 677 // Both these function update the cached uniform values and return a modified "count" 678 // so that the uniform update doesn't overflow the uniform. 679 template <typename T> 680 GLsizei clampUniformCount(const VariableLocation &locationInfo, 681 GLsizei count, 682 int vectorSize, 683 const T *v); 684 template <size_t cols, size_t rows, typename T> 685 GLsizei clampMatrixUniformCount(GLint location, GLsizei count, GLboolean transpose, const T *v); 686 687 void updateSamplerUniform(const VariableLocation &locationInfo, 688 GLsizei clampedCount, 689 const GLint *v); 690 691 template <typename DestT> 692 void getUniformInternal(const Context *context, 693 DestT *dataOut, 694 GLint location, 695 GLenum nativeType, 696 int components) const; 697 698 template <typename T> 699 void getResourceName(GLuint index, 700 const std::vector<T> &resources, 701 GLsizei bufSize, 702 GLsizei *length, 703 GLchar *name) const; 704 705 ProgramState mState; 706 rx::ProgramImpl *mProgram; 707 708 bool mValidated; 709 710 Bindings mAttributeBindings; 711 712 // Note that this has nothing to do with binding layout qualifiers that can be set for some 713 // uniforms in GLES3.1+. It is used to pre-set the location of uniforms. 714 Bindings mUniformLocationBindings; 715 716 // CHROMIUM_path_rendering 717 Bindings mFragmentInputBindings; 718 719 bool mLinked; 720 bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use 721 722 unsigned int mRefCount; 723 724 ShaderProgramManager *mResourceManager; 725 const GLuint mHandle; 726 727 InfoLog mInfoLog; 728 729 // Cache for sampler validation 730 Optional<bool> mCachedValidateSamplersResult; 731 std::vector<GLenum> mTextureUnitTypesCache; 732 }; 733 } // namespace gl 734 735 #endif // LIBANGLE_PROGRAM_H_ 736