1 // 2 // Copyright 2002 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/Optional.h" 24 #include "common/angleutils.h" 25 #include "common/mathutil.h" 26 #include "common/utilities.h" 27 28 #include "libANGLE/Constants.h" 29 #include "libANGLE/Debug.h" 30 #include "libANGLE/Error.h" 31 #include "libANGLE/InfoLog.h" 32 #include "libANGLE/ProgramExecutable.h" 33 #include "libANGLE/ProgramLinkedResources.h" 34 #include "libANGLE/RefCountObject.h" 35 #include "libANGLE/Uniform.h" 36 #include "libANGLE/angletypes.h" 37 38 namespace rx 39 { 40 class GLImplFactory; 41 class ProgramImpl; 42 struct TranslatedAttribute; 43 } // namespace rx 44 45 namespace gl 46 { 47 class Buffer; 48 class BinaryInputStream; 49 class BinaryOutputStream; 50 struct Caps; 51 class Context; 52 struct Extensions; 53 class Framebuffer; 54 class ProgramExecutable; 55 class Shader; 56 class ShaderProgramManager; 57 class State; 58 struct UnusedUniform; 59 struct Version; 60 61 extern const char *const g_fakepath; 62 63 enum class LinkMismatchError 64 { 65 // Shared 66 NO_MISMATCH, 67 TYPE_MISMATCH, 68 ARRAYNESS_MISMATCH, 69 ARRAY_SIZE_MISMATCH, 70 PRECISION_MISMATCH, 71 STRUCT_NAME_MISMATCH, 72 FIELD_NUMBER_MISMATCH, 73 FIELD_NAME_MISMATCH, 74 75 // Varying specific 76 INTERPOLATION_TYPE_MISMATCH, 77 INVARIANCE_MISMATCH, 78 79 // Uniform specific 80 BINDING_MISMATCH, 81 LOCATION_MISMATCH, 82 OFFSET_MISMATCH, 83 INSTANCE_NAME_MISMATCH, 84 FORMAT_MISMATCH, 85 86 // Interface block specific 87 LAYOUT_QUALIFIER_MISMATCH, 88 MATRIX_PACKING_MISMATCH, 89 90 // I/O block specific 91 FIELD_LOCATION_MISMATCH, 92 FIELD_STRUCT_NAME_MISMATCH, 93 }; 94 95 void LogLinkMismatch(InfoLog &infoLog, 96 const std::string &variableName, 97 const char *variableType, 98 LinkMismatchError linkError, 99 const std::string &mismatchedStructOrBlockFieldName, 100 ShaderType shaderType1, 101 ShaderType shaderType2); 102 103 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock); 104 105 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var); 106 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var); 107 108 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block); 109 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block); 110 111 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var); 112 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var); 113 114 // Struct used for correlating uniforms/elements of uniform arrays to handles 115 struct VariableLocation 116 { 117 static constexpr unsigned int kUnused = GL_INVALID_INDEX; 118 119 VariableLocation(); 120 VariableLocation(unsigned int arrayIndex, unsigned int index); 121 122 // If used is false, it means this location is only used to fill an empty space in an array, 123 // and there is no corresponding uniform variable for this location. It can also mean the 124 // uniform was optimized out by the implementation. usedVariableLocation125 bool used() const { return (index != kUnused); } markUnusedVariableLocation126 void markUnused() { index = kUnused; } markIgnoredVariableLocation127 void markIgnored() { ignored = true; } 128 129 bool operator==(const VariableLocation &other) const 130 { 131 return arrayIndex == other.arrayIndex && index == other.index; 132 } 133 134 // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays. 135 unsigned int arrayIndex; 136 // "index" is an index of the variable. The variable contains the indices for other than the 137 // innermost GLSL arrays. 138 unsigned int index; 139 140 // If this location was bound to an unreferenced uniform. Setting data on this uniform is a 141 // no-op. 142 bool ignored; 143 }; 144 145 // Information about a variable binding. 146 // Currently used by CHROMIUM_path_rendering 147 struct BindingInfo 148 { 149 // The type of binding, for example GL_FLOAT_VEC3. 150 // This can be GL_NONE if the variable is optimized away. 151 GLenum type; 152 153 // This is the name of the variable in 154 // the translated shader program. Note that 155 // this can be empty in the case where the 156 // variable has been optimized away. 157 std::string name; 158 159 // True if the binding is valid, otherwise false. 160 bool valid; 161 }; 162 163 struct ProgramBinding 164 { ProgramBindingProgramBinding165 ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {} ProgramBindingProgramBinding166 ProgramBinding(GLuint index) : location(index), aliased(false) {} 167 168 GLuint location; 169 // Whether another binding was set that may potentially alias this. 170 bool aliased; 171 }; 172 173 class ProgramBindings final : angle::NonCopyable 174 { 175 public: 176 ProgramBindings(); 177 ~ProgramBindings(); 178 179 void bindLocation(GLuint index, const std::string &name); 180 int getBindingByName(const std::string &name) const; 181 template <typename T> 182 int getBinding(const T &variable) const; 183 184 using const_iterator = angle::HashMap<std::string, GLuint>::const_iterator; 185 const_iterator begin() const; 186 const_iterator end() const; 187 188 std::map<std::string, GLuint> getStableIterationMap() const; 189 190 private: 191 angle::HashMap<std::string, GLuint> mBindings; 192 }; 193 194 // Uniforms and Fragment Outputs require special treatment due to array notation (e.g., "[0]") 195 class ProgramAliasedBindings final : angle::NonCopyable 196 { 197 public: 198 ProgramAliasedBindings(); 199 ~ProgramAliasedBindings(); 200 201 void bindLocation(GLuint index, const std::string &name); 202 int getBindingByName(const std::string &name) const; 203 int getBindingByLocation(GLuint location) const; 204 template <typename T> 205 int getBinding(const T &variable) const; 206 207 using const_iterator = angle::HashMap<std::string, ProgramBinding>::const_iterator; 208 const_iterator begin() const; 209 const_iterator end() const; 210 211 std::map<std::string, ProgramBinding> getStableIterationMap() const; 212 213 private: 214 angle::HashMap<std::string, ProgramBinding> mBindings; 215 }; 216 217 class ProgramState final : angle::NonCopyable 218 { 219 public: 220 ProgramState(); 221 ~ProgramState(); 222 223 const std::string &getLabel(); 224 225 Shader *getAttachedShader(ShaderType shaderType) const; getAttachedShaders()226 const gl::ShaderMap<Shader *> &getAttachedShaders() const { return mAttachedShaders; } getTransformFeedbackVaryingNames()227 const std::vector<std::string> &getTransformFeedbackVaryingNames() const 228 { 229 return mTransformFeedbackVaryingNames; 230 } getTransformFeedbackBufferMode()231 GLint getTransformFeedbackBufferMode() const 232 { 233 return mExecutable->getTransformFeedbackBufferMode(); 234 } getUniformBlockBinding(GLuint uniformBlockIndex)235 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const 236 { 237 return mExecutable->getUniformBlockBinding(uniformBlockIndex); 238 } getShaderStorageBlockBinding(GLuint blockIndex)239 GLuint getShaderStorageBlockBinding(GLuint blockIndex) const 240 { 241 return mExecutable->getShaderStorageBlockBinding(blockIndex); 242 } getActiveUniformBlockBindingsMask()243 const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const 244 { 245 return mExecutable->getActiveUniformBlockBindings(); 246 } getProgramInputs()247 const std::vector<sh::ShaderVariable> &getProgramInputs() const 248 { 249 return mExecutable->getProgramInputs(); 250 } getOutputVariables()251 const std::vector<sh::ShaderVariable> &getOutputVariables() const 252 { 253 return mExecutable->getOutputVariables(); 254 } getOutputLocations()255 const std::vector<VariableLocation> &getOutputLocations() const 256 { 257 return mExecutable->getOutputLocations(); 258 } getSecondaryOutputLocations()259 const std::vector<VariableLocation> &getSecondaryOutputLocations() const 260 { 261 return mExecutable->getSecondaryOutputLocations(); 262 } getUniforms()263 const std::vector<LinkedUniform> &getUniforms() const { return mExecutable->getUniforms(); } getUniformLocations()264 const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; } getUniformBlocks()265 const std::vector<InterfaceBlock> &getUniformBlocks() const 266 { 267 return mExecutable->getUniformBlocks(); 268 } getShaderStorageBlocks()269 const std::vector<InterfaceBlock> &getShaderStorageBlocks() const 270 { 271 return mExecutable->getShaderStorageBlocks(); 272 } getBufferVariables()273 const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; } getSamplerBindings()274 const std::vector<SamplerBinding> &getSamplerBindings() const 275 { 276 return mExecutable->getSamplerBindings(); 277 } getImageBindings()278 const std::vector<ImageBinding> &getImageBindings() const 279 { 280 return getExecutable().getImageBindings(); 281 } getComputeShaderLocalSize()282 const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } getDefaultUniformRange()283 const RangeUI &getDefaultUniformRange() const { return mExecutable->getDefaultUniformRange(); } getSamplerUniformRange()284 const RangeUI &getSamplerUniformRange() const { return mExecutable->getSamplerUniformRange(); } getImageUniformRange()285 const RangeUI &getImageUniformRange() const { return mExecutable->getImageUniformRange(); } getAtomicCounterUniformRange()286 const RangeUI &getAtomicCounterUniformRange() const 287 { 288 return mExecutable->getAtomicCounterUniformRange(); 289 } getFragmentInoutRange()290 const RangeUI &getFragmentInoutRange() const { return mExecutable->getFragmentInoutRange(); } 291 getLinkedTransformFeedbackVaryings()292 const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const 293 { 294 return mExecutable->getLinkedTransformFeedbackVaryings(); 295 } getTransformFeedbackStrides()296 const std::vector<GLsizei> &getTransformFeedbackStrides() const 297 { 298 return mExecutable->getTransformFeedbackStrides(); 299 } getAtomicCounterBuffers()300 const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const 301 { 302 return mExecutable->getAtomicCounterBuffers(); 303 } 304 305 GLuint getUniformIndexFromName(const std::string &name) const; 306 GLuint getUniformIndexFromLocation(UniformLocation location) const; 307 Optional<GLuint> getSamplerIndex(UniformLocation location) const; 308 bool isSamplerUniformIndex(GLuint index) const; 309 GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const; 310 GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const; 311 bool isImageUniformIndex(GLuint index) const; 312 GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const; 313 GLuint getAttributeLocation(const std::string &name) const; 314 315 GLuint getBufferVariableIndexFromName(const std::string &name) const; 316 getNumViews()317 int getNumViews() const { return mNumViews; } usesMultiview()318 bool usesMultiview() const { return mNumViews != -1; } 319 320 bool hasAttachedShader() const; 321 322 ShaderType getFirstAttachedShaderStageType() const; 323 ShaderType getLastAttachedShaderStageType() const; 324 getUniformLocationBindings()325 const ProgramAliasedBindings &getUniformLocationBindings() const 326 { 327 return mUniformLocationBindings; 328 } 329 getExecutable()330 const ProgramExecutable &getExecutable() const 331 { 332 ASSERT(mExecutable); 333 return *mExecutable; 334 } getExecutable()335 ProgramExecutable &getExecutable() 336 { 337 ASSERT(mExecutable); 338 return *mExecutable; 339 } 340 hasImages()341 bool hasImages() const { return !getImageBindings().empty(); } getSpecConstUsageBits()342 rx::SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; } 343 344 // A Program can only either be graphics or compute, but never both, so it 345 // can answer isCompute() based on which shaders it has. isCompute()346 bool isCompute() const { return mExecutable->hasLinkedShaderStage(ShaderType::Compute); } 347 getLabel()348 const std::string &getLabel() const { return mLabel; } 349 getLocationsUsedForXfbExtension()350 uint32_t getLocationsUsedForXfbExtension() const { return mLocationsUsedForXfbExtension; } 351 hasBinaryRetrieveableHint()352 bool hasBinaryRetrieveableHint() const { return mBinaryRetrieveableHint; } 353 isSeparable()354 bool isSeparable() const { return mSeparable; } 355 getDrawIDLocation()356 int getDrawIDLocation() const { return mDrawIDLocation; } 357 getBaseVertexLocation()358 int getBaseVertexLocation() const { return mBaseVertexLocation; } 359 getBaseInstanceLocation()360 int getBaseInstanceLocation() const { return mBaseInstanceLocation; } 361 362 ShaderType getAttachedTransformFeedbackStage() const; 363 364 private: 365 friend class MemoryProgramCache; 366 friend class Program; 367 368 void updateActiveSamplers(); 369 void updateProgramInterfaceInputs(const Context *context); 370 void updateProgramInterfaceOutputs(const Context *context); 371 372 // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. 373 void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex); 374 375 std::string mLabel; 376 377 sh::WorkGroupSize mComputeShaderLocalSize; 378 379 ShaderMap<Shader *> mAttachedShaders; 380 381 uint32_t mLocationsUsedForXfbExtension; 382 std::vector<std::string> mTransformFeedbackVaryingNames; 383 384 std::vector<VariableLocation> mUniformLocations; 385 std::vector<BufferVariable> mBufferVariables; 386 387 bool mBinaryRetrieveableHint; 388 bool mSeparable; 389 rx::SpecConstUsageBits mSpecConstUsageBits; 390 391 // GL_OVR_multiview / GL_OVR_multiview2 392 int mNumViews; 393 394 // GL_ANGLE_multi_draw 395 int mDrawIDLocation; 396 397 // GL_ANGLE_base_vertex_base_instance_shader_builtin 398 int mBaseVertexLocation; 399 int mBaseInstanceLocation; 400 // Cached value of base vertex and base instance 401 // need to reset them to zero if using non base vertex or base instance draw calls. 402 GLint mCachedBaseVertex; 403 GLuint mCachedBaseInstance; 404 405 // Note that this has nothing to do with binding layout qualifiers that can be set for some 406 // uniforms in GLES3.1+. It is used to pre-set the location of uniforms. 407 ProgramAliasedBindings mUniformLocationBindings; 408 409 std::shared_ptr<ProgramExecutable> mExecutable; 410 }; 411 412 struct ProgramVaryingRef 413 { getProgramVaryingRef414 const sh::ShaderVariable *get(ShaderType stage) const 415 { 416 ASSERT(stage == frontShaderStage || stage == backShaderStage); 417 const sh::ShaderVariable *ref = stage == frontShaderStage ? frontShader : backShader; 418 ASSERT(ref); 419 return ref; 420 } 421 422 const sh::ShaderVariable *frontShader = nullptr; 423 const sh::ShaderVariable *backShader = nullptr; 424 ShaderType frontShaderStage = ShaderType::InvalidEnum; 425 ShaderType backShaderStage = ShaderType::InvalidEnum; 426 }; 427 428 using ProgramMergedVaryings = std::vector<ProgramVaryingRef>; 429 430 class Program final : public LabeledObject, public angle::Subject 431 { 432 public: 433 Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle); 434 void onDestroy(const Context *context); 435 436 ShaderProgramID id() const; 437 438 angle::Result setLabel(const Context *context, const std::string &label) override; 439 const std::string &getLabel() const override; 440 getImplementation()441 ANGLE_INLINE rx::ProgramImpl *getImplementation() const 442 { 443 ASSERT(!mLinkingState); 444 return mProgram; 445 } 446 447 void attachShader(Shader *shader); 448 void detachShader(const Context *context, Shader *shader); 449 int getAttachedShadersCount() const; 450 451 Shader *getAttachedShader(ShaderType shaderType) const; 452 453 void bindAttributeLocation(GLuint index, const char *name); 454 void bindUniformLocation(UniformLocation location, const char *name); 455 456 // EXT_blend_func_extended 457 void bindFragmentOutputLocation(GLuint index, const char *name); 458 void bindFragmentOutputIndex(GLuint index, const char *name); 459 460 // KHR_parallel_shader_compile 461 // Try to link the program asynchronously. As a result, background threads may be launched to 462 // execute the linking tasks concurrently. 463 angle::Result link(const Context *context); 464 465 // Peek whether there is any running linking tasks. 466 bool isLinking() const; hasLinkingState()467 bool hasLinkingState() const { return mLinkingState != nullptr; } 468 isLinked()469 bool isLinked() const 470 { 471 ASSERT(!mLinkingState); 472 return mLinked; 473 } 474 475 angle::Result loadBinary(const Context *context, 476 GLenum binaryFormat, 477 const void *binary, 478 GLsizei length); 479 angle::Result saveBinary(Context *context, 480 GLenum *binaryFormat, 481 void *binary, 482 GLsizei bufSize, 483 GLsizei *length) const; 484 GLint getBinaryLength(Context *context) const; 485 void setBinaryRetrievableHint(bool retrievable); 486 bool getBinaryRetrievableHint() const; 487 488 void setSeparable(bool separable); 489 bool isSeparable() const; 490 491 void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const; 492 493 GLuint getAttributeLocation(const std::string &name) const; 494 495 void getActiveAttribute(GLuint index, 496 GLsizei bufsize, 497 GLsizei *length, 498 GLint *size, 499 GLenum *type, 500 GLchar *name) const; 501 GLint getActiveAttributeCount() const; 502 GLint getActiveAttributeMaxLength() const; 503 const std::vector<sh::ShaderVariable> &getAttributes() const; 504 505 GLint getFragDataLocation(const std::string &name) const; 506 size_t getOutputResourceCount() const; 507 508 // EXT_blend_func_extended 509 GLint getFragDataIndex(const std::string &name) const; 510 511 void getActiveUniform(GLuint index, 512 GLsizei bufsize, 513 GLsizei *length, 514 GLint *size, 515 GLenum *type, 516 GLchar *name) const; 517 GLint getActiveUniformCount() const; 518 size_t getActiveBufferVariableCount() const; 519 GLint getActiveUniformMaxLength() const; 520 bool isValidUniformLocation(UniformLocation location) const; 521 const LinkedUniform &getUniformByLocation(UniformLocation location) const; 522 const VariableLocation &getUniformLocation(UniformLocation location) const; 523 getUniformLocations()524 const std::vector<VariableLocation> &getUniformLocations() const 525 { 526 ASSERT(!mLinkingState); 527 return mState.mUniformLocations; 528 } 529 getUniformByIndex(GLuint index)530 const LinkedUniform &getUniformByIndex(GLuint index) const 531 { 532 ASSERT(!mLinkingState); 533 return mState.mExecutable->getUniformByIndex(index); 534 } 535 536 const BufferVariable &getBufferVariableByIndex(GLuint index) const; 537 538 enum SetUniformResult 539 { 540 SamplerChanged, 541 NoSamplerChange, 542 }; 543 544 UniformLocation getUniformLocation(const std::string &name) const; 545 GLuint getUniformIndex(const std::string &name) const; 546 void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v); 547 void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v); 548 void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v); 549 void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v); 550 void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v); 551 void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v); 552 void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v); 553 void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v); 554 void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v); 555 void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v); 556 void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v); 557 void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v); 558 void setUniformMatrix2fv(UniformLocation location, 559 GLsizei count, 560 GLboolean transpose, 561 const GLfloat *value); 562 void setUniformMatrix3fv(UniformLocation location, 563 GLsizei count, 564 GLboolean transpose, 565 const GLfloat *value); 566 void setUniformMatrix4fv(UniformLocation location, 567 GLsizei count, 568 GLboolean transpose, 569 const GLfloat *value); 570 void setUniformMatrix2x3fv(UniformLocation location, 571 GLsizei count, 572 GLboolean transpose, 573 const GLfloat *value); 574 void setUniformMatrix3x2fv(UniformLocation location, 575 GLsizei count, 576 GLboolean transpose, 577 const GLfloat *value); 578 void setUniformMatrix2x4fv(UniformLocation location, 579 GLsizei count, 580 GLboolean transpose, 581 const GLfloat *value); 582 void setUniformMatrix4x2fv(UniformLocation location, 583 GLsizei count, 584 GLboolean transpose, 585 const GLfloat *value); 586 void setUniformMatrix3x4fv(UniformLocation location, 587 GLsizei count, 588 GLboolean transpose, 589 const GLfloat *value); 590 void setUniformMatrix4x3fv(UniformLocation location, 591 GLsizei count, 592 GLboolean transpose, 593 const GLfloat *value); 594 595 void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const; 596 void getUniformiv(const Context *context, UniformLocation location, GLint *params) const; 597 void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const; 598 599 void getActiveUniformBlockName(const Context *context, 600 const UniformBlockIndex blockIndex, 601 GLsizei bufSize, 602 GLsizei *length, 603 GLchar *blockName) const; 604 void getActiveShaderStorageBlockName(const GLuint blockIndex, 605 GLsizei bufSize, 606 GLsizei *length, 607 GLchar *blockName) const; 608 getActiveUniformBlockCount()609 ANGLE_INLINE GLuint getActiveUniformBlockCount() const 610 { 611 ASSERT(!mLinkingState); 612 return static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()); 613 } 614 getActiveAtomicCounterBufferCount()615 ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const 616 { 617 ASSERT(!mLinkingState); 618 return static_cast<GLuint>(mState.mExecutable->getActiveAtomicCounterBufferCount()); 619 } 620 getActiveShaderStorageBlockCount()621 ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const 622 { 623 ASSERT(!mLinkingState); 624 return static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()); 625 } 626 627 GLint getActiveUniformBlockMaxNameLength() const; 628 GLint getActiveShaderStorageBlockMaxNameLength() const; 629 getUniforms()630 const std::vector<LinkedUniform> &getUniforms() const { return mState.getUniforms(); } 631 GLuint getUniformBlockIndex(const std::string &name) const; 632 GLuint getShaderStorageBlockIndex(const std::string &name) const; 633 634 void bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding); 635 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; 636 GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const; 637 638 const InterfaceBlock &getUniformBlockByIndex(GLuint index) const; 639 const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const; 640 641 void setTransformFeedbackVaryings(GLsizei count, 642 const GLchar *const *varyings, 643 GLenum bufferMode); 644 void getTransformFeedbackVarying(GLuint index, 645 GLsizei bufSize, 646 GLsizei *length, 647 GLsizei *size, 648 GLenum *type, 649 GLchar *name) const; 650 GLsizei getTransformFeedbackVaryingCount() const; 651 GLsizei getTransformFeedbackVaryingMaxLength() const; 652 GLenum getTransformFeedbackBufferMode() const; 653 GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const; 654 const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const; 655 656 bool hasDrawIDUniform() const; 657 void setDrawIDUniform(GLint drawid); 658 659 bool hasBaseVertexUniform() const; 660 void setBaseVertexUniform(GLint baseVertex); 661 bool hasBaseInstanceUniform() const; 662 void setBaseInstanceUniform(GLuint baseInstance); 663 addRef()664 ANGLE_INLINE void addRef() 665 { 666 ASSERT(!mLinkingState); 667 mRefCount++; 668 } 669 release(const Context * context)670 ANGLE_INLINE void release(const Context *context) 671 { 672 ASSERT(!mLinkingState); 673 mRefCount--; 674 675 if (mRefCount == 0 && mDeleteStatus) 676 { 677 deleteSelf(context); 678 } 679 } 680 681 unsigned int getRefCount() const; isInUse()682 bool isInUse() const { return getRefCount() != 0; } 683 void flagForDeletion(); 684 bool isFlaggedForDeletion() const; 685 686 void validate(const Caps &caps); 687 bool isValidated() const; 688 getImageBindings()689 const std::vector<ImageBinding> &getImageBindings() const 690 { 691 ASSERT(!mLinkingState); 692 return getExecutable().getImageBindings(); 693 } 694 const sh::WorkGroupSize &getComputeShaderLocalSize() const; 695 PrimitiveMode getGeometryShaderInputPrimitiveType() const; 696 PrimitiveMode getGeometryShaderOutputPrimitiveType() const; 697 GLint getGeometryShaderInvocations() const; 698 GLint getGeometryShaderMaxVertices() const; 699 700 GLint getTessControlShaderVertices() const; 701 GLenum getTessGenMode() const; 702 GLenum getTessGenPointMode() const; 703 GLenum getTessGenSpacing() const; 704 GLenum getTessGenVertexOrder() const; 705 getState()706 const ProgramState &getState() const 707 { 708 ASSERT(!mLinkingState); 709 return mState; 710 } 711 712 GLuint getInputResourceIndex(const GLchar *name) const; 713 GLuint getOutputResourceIndex(const GLchar *name) const; 714 void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 715 void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 716 void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 717 void getBufferVariableResourceName(GLuint index, 718 GLsizei bufSize, 719 GLsizei *length, 720 GLchar *name) const; 721 const sh::ShaderVariable &getInputResource(size_t index) const; 722 GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const; 723 GLuint getInputResourceMaxNameSize() const; 724 GLuint getOutputResourceMaxNameSize() const; 725 GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const; 726 GLuint getInputResourceLocation(const GLchar *name) const; 727 GLuint getOutputResourceLocation(const GLchar *name) const; 728 const std::string getResourceName(const sh::ShaderVariable &resource) const; 729 const std::string getInputResourceName(GLuint index) const; 730 const std::string getOutputResourceName(GLuint index) const; 731 const sh::ShaderVariable &getOutputResource(size_t index) const; 732 733 const ProgramBindings &getAttributeBindings() const; 734 const ProgramAliasedBindings &getUniformLocationBindings() const; 735 const ProgramAliasedBindings &getFragmentOutputLocations() const; 736 const ProgramAliasedBindings &getFragmentOutputIndexes() const; 737 getNumViews()738 int getNumViews() const 739 { 740 ASSERT(!mLinkingState); 741 return mState.getNumViews(); 742 } 743 usesMultiview()744 bool usesMultiview() const { return mState.usesMultiview(); } 745 746 const std::vector<GLsizei> &getTransformFeedbackStrides() const; 747 748 // Program dirty bits. 749 enum DirtyBitType 750 { 751 DIRTY_BIT_UNIFORM_BLOCK_BINDING_0, 752 DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX = 753 DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS, 754 755 DIRTY_BIT_COUNT = DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX, 756 }; 757 static_assert(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 == 0, 758 "UniformBlockBindingMask must match DirtyBits because UniformBlockBindingMask is " 759 "used directly to set dirty bits."); 760 761 using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>; 762 763 angle::Result syncState(const Context *context); 764 765 // Try to resolve linking. Inlined to make sure its overhead is as low as possible. resolveLink(const Context * context)766 void resolveLink(const Context *context) 767 { 768 if (mLinkingState) 769 { 770 resolveLinkImpl(context); 771 } 772 } 773 hasAnyDirtyBit()774 ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); } 775 776 // Writes a program's binary to the output memory buffer. 777 angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const; 778 serial()779 rx::UniqueSerial serial() const { return mSerial; } 780 getExecutable()781 const ProgramExecutable &getExecutable() const { return mState.getExecutable(); } getExecutable()782 ProgramExecutable &getExecutable() { return mState.getExecutable(); } 783 onUniformBufferStateChange(size_t uniformBufferIndex)784 void onUniformBufferStateChange(size_t uniformBufferIndex) 785 { 786 if (uniformBufferIndex >= mUniformBlockBindingMasks.size()) 787 { 788 mUniformBlockBindingMasks.resize(uniformBufferIndex + 1, UniformBlockBindingMask()); 789 } 790 mDirtyBits |= mUniformBlockBindingMasks[uniformBufferIndex]; 791 } 792 793 private: 794 friend class ProgramPipeline; 795 796 struct LinkingState; 797 ~Program() override; 798 799 // Loads program state according to the specified binary blob. 800 angle::Result deserialize(const Context *context, BinaryInputStream &stream, InfoLog &infoLog); 801 802 void unlink(); 803 void deleteSelf(const Context *context); 804 805 angle::Result linkImpl(const Context *context); 806 807 bool linkValidateShaders(const Context *context, InfoLog &infoLog); 808 bool linkAttributes(const Context *context, InfoLog &infoLog); 809 bool linkVaryings(const Context *context, InfoLog &infoLog) const; 810 811 bool linkUniforms(const Context *context, 812 std::vector<UnusedUniform> *unusedUniformsOutOrNull, 813 GLuint *combinedImageUniformsOut, 814 InfoLog &infoLog); 815 816 void updateLinkedShaderStages(); 817 818 void setUniformValuesFromBindingQualifiers(); 819 bool shouldIgnoreUniform(UniformLocation location) const; 820 821 void initInterfaceBlockBindings(); 822 823 // Both these function update the cached uniform values and return a modified "count" 824 // so that the uniform update doesn't overflow the uniform. 825 template <typename T> 826 GLsizei clampUniformCount(const VariableLocation &locationInfo, 827 GLsizei count, 828 int vectorSize, 829 const T *v); 830 template <size_t cols, size_t rows, typename T> 831 GLsizei clampMatrixUniformCount(UniformLocation location, 832 GLsizei count, 833 GLboolean transpose, 834 const T *v); 835 836 void updateSamplerUniform(Context *context, 837 const VariableLocation &locationInfo, 838 GLsizei clampedCount, 839 const GLint *v); 840 841 template <typename DestT> 842 void getUniformInternal(const Context *context, 843 DestT *dataOut, 844 UniformLocation location, 845 GLenum nativeType, 846 int components) const; 847 848 void getResourceName(const std::string name, 849 GLsizei bufSize, 850 GLsizei *length, 851 GLchar *dest) const; 852 853 template <typename T> 854 GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const; 855 856 GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const; 857 GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const; 858 859 // Block until linking is finished and resolve it. 860 void resolveLinkImpl(const gl::Context *context); 861 862 void postResolveLink(const gl::Context *context); 863 864 template <typename UniformT, 865 GLint UniformSize, 866 void (rx::ProgramImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)> 867 void setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v); 868 869 template < 870 typename UniformT, 871 GLint MatrixC, 872 GLint MatrixR, 873 void (rx::ProgramImpl::*SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)> 874 void setUniformMatrixGeneric(UniformLocation location, 875 GLsizei count, 876 GLboolean transpose, 877 const UniformT *v); 878 879 void dumpProgramInfo() const; 880 881 rx::UniqueSerial mSerial; 882 ProgramState mState; 883 rx::ProgramImpl *mProgram; 884 885 bool mValidated; 886 887 ProgramBindings mAttributeBindings; 888 889 // EXT_blend_func_extended 890 ProgramAliasedBindings mFragmentOutputLocations; 891 ProgramAliasedBindings mFragmentOutputIndexes; 892 893 bool mLinked; 894 std::unique_ptr<LinkingState> mLinkingState; 895 bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use 896 897 unsigned int mRefCount; 898 899 ShaderProgramManager *mResourceManager; 900 const ShaderProgramID mHandle; 901 902 DirtyBits mDirtyBits; 903 904 // To simplify dirty bits handling, instead of tracking dirtiness of both uniform block index 905 // and uniform binding index, we only track which uniform block index is dirty. And then when 906 // buffer index is dirty, we look at which uniform blocks are bound to this buffer binding index 907 // and set all of these uniform blocks dirty. This variable tracks all the uniform blocks bound 908 // to the given binding index in the form of bitmask so that we can quickly convert them to the 909 // dirty bits. 910 static constexpr size_t kFastUniformBlockBindingLimit = 8; 911 angle::FastVector<UniformBlockBindingMask, kFastUniformBlockBindingLimit> 912 mUniformBlockBindingMasks; 913 914 std::mutex mHistogramMutex; 915 }; 916 } // namespace gl 917 918 #endif // LIBANGLE_PROGRAM_H_ 919