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 <memory> 19 #include <set> 20 #include <sstream> 21 #include <string> 22 #include <vector> 23 24 #include "common/Optional.h" 25 #include "common/SimpleMutex.h" 26 #include "common/angleutils.h" 27 #include "common/hash_containers.h" 28 #include "common/mathutil.h" 29 #include "common/utilities.h" 30 31 #include "libANGLE/Constants.h" 32 #include "libANGLE/Debug.h" 33 #include "libANGLE/Error.h" 34 #include "libANGLE/InfoLog.h" 35 #include "libANGLE/ProgramExecutable.h" 36 #include "libANGLE/ProgramLinkedResources.h" 37 #include "libANGLE/RefCountObject.h" 38 #include "libANGLE/Shader.h" 39 #include "libANGLE/Uniform.h" 40 #include "libANGLE/angletypes.h" 41 42 namespace rx 43 { 44 class GLImplFactory; 45 class ProgramImpl; 46 class LinkSubTask; 47 struct TranslatedAttribute; 48 } // namespace rx 49 50 namespace gl 51 { 52 class Buffer; 53 class BinaryInputStream; 54 class BinaryOutputStream; 55 struct Caps; 56 class Context; 57 struct Extensions; 58 class Framebuffer; 59 class ProgramExecutable; 60 class ShaderProgramManager; 61 class State; 62 struct UnusedUniform; 63 struct Version; 64 65 extern const char *const g_fakepath; 66 67 enum class LinkMismatchError 68 { 69 // Shared 70 NO_MISMATCH, 71 TYPE_MISMATCH, 72 ARRAYNESS_MISMATCH, 73 ARRAY_SIZE_MISMATCH, 74 PRECISION_MISMATCH, 75 STRUCT_NAME_MISMATCH, 76 FIELD_NUMBER_MISMATCH, 77 FIELD_NAME_MISMATCH, 78 79 // Varying specific 80 INTERPOLATION_TYPE_MISMATCH, 81 INVARIANCE_MISMATCH, 82 83 // Uniform specific 84 BINDING_MISMATCH, 85 LOCATION_MISMATCH, 86 OFFSET_MISMATCH, 87 INSTANCE_NAME_MISMATCH, 88 FORMAT_MISMATCH, 89 90 // Interface block specific 91 LAYOUT_QUALIFIER_MISMATCH, 92 MATRIX_PACKING_MISMATCH, 93 94 // I/O block specific 95 FIELD_LOCATION_MISMATCH, 96 FIELD_STRUCT_NAME_MISMATCH, 97 }; 98 99 void LogLinkMismatch(InfoLog &infoLog, 100 const std::string &variableName, 101 const char *variableType, 102 LinkMismatchError linkError, 103 const std::string &mismatchedStructOrBlockFieldName, 104 ShaderType shaderType1, 105 ShaderType shaderType2); 106 107 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock); 108 109 // Struct used for correlating uniforms/elements of uniform arrays to handles 110 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS 111 struct VariableLocation 112 { 113 static constexpr unsigned int kUnused = GL_INVALID_INDEX; 114 115 VariableLocation(); 116 VariableLocation(unsigned int arrayIndex, unsigned int index); 117 118 // If used is false, it means this location is only used to fill an empty space in an array, 119 // and there is no corresponding uniform variable for this location. It can also mean the 120 // uniform was optimized out by the implementation. usedVariableLocation121 bool used() const { return (index != kUnused); } markUnusedVariableLocation122 void markUnused() { index = kUnused; } markIgnoredVariableLocation123 void markIgnored() { ignored = true; } 124 125 bool operator==(const VariableLocation &other) const 126 { 127 return arrayIndex == other.arrayIndex && index == other.index; 128 } 129 130 // "index" is an index of the variable. The variable contains the indices for other than the 131 // innermost GLSL arrays. 132 uint32_t index; 133 134 // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays. 135 uint32_t arrayIndex : 31; 136 // If this location was bound to an unreferenced uniform. Setting data on this uniform is a 137 // no-op. 138 uint32_t ignored : 1; 139 }; 140 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS 141 142 // Information about a variable binding. 143 // Currently used by CHROMIUM_path_rendering 144 struct BindingInfo 145 { 146 // The type of binding, for example GL_FLOAT_VEC3. 147 // This can be GL_NONE if the variable is optimized away. 148 GLenum type; 149 150 // This is the name of the variable in 151 // the translated shader program. Note that 152 // this can be empty in the case where the 153 // variable has been optimized away. 154 std::string name; 155 156 // True if the binding is valid, otherwise false. 157 bool valid; 158 }; 159 160 struct ProgramBinding 161 { ProgramBindingProgramBinding162 ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {} ProgramBindingProgramBinding163 ProgramBinding(GLuint index) : location(index), aliased(false) {} 164 165 GLuint location; 166 // Whether another binding was set that may potentially alias this. 167 bool aliased; 168 }; 169 170 class ProgramBindings final : angle::NonCopyable 171 { 172 public: 173 ProgramBindings(); 174 ~ProgramBindings(); 175 176 void bindLocation(GLuint index, const std::string &name); 177 int getBindingByName(const std::string &name) const; 178 template <typename T> 179 int getBinding(const T &variable) const; 180 181 using const_iterator = angle::HashMap<std::string, GLuint>::const_iterator; 182 const_iterator begin() const; 183 const_iterator end() const; 184 185 std::map<std::string, GLuint> getStableIterationMap() const; 186 187 private: 188 angle::HashMap<std::string, GLuint> mBindings; 189 }; 190 191 // Uniforms and Fragment Outputs require special treatment due to array notation (e.g., "[0]") 192 class ProgramAliasedBindings final : angle::NonCopyable 193 { 194 public: 195 ProgramAliasedBindings(); 196 ~ProgramAliasedBindings(); 197 198 void bindLocation(GLuint index, const std::string &name); 199 int getBindingByName(const std::string &name) const; 200 int getBindingByLocation(GLuint location) const; 201 template <typename T> 202 int getBinding(const T &variable) const; 203 204 using const_iterator = angle::HashMap<std::string, ProgramBinding>::const_iterator; 205 const_iterator begin() const; 206 const_iterator end() const; 207 208 std::map<std::string, ProgramBinding> getStableIterationMap() const; 209 210 private: 211 angle::HashMap<std::string, ProgramBinding> mBindings; 212 }; 213 214 class ProgramState final : angle::NonCopyable 215 { 216 public: 217 ProgramState(rx::GLImplFactory *factory); 218 ~ProgramState(); 219 220 const std::string &getLabel(); 221 222 SharedCompiledShaderState getAttachedShader(ShaderType shaderType) const; getAttachedShaders()223 const ShaderMap<SharedCompiledShaderState> &getAttachedShaders() const 224 { 225 return mAttachedShaders; 226 } getTransformFeedbackVaryingNames()227 const std::vector<std::string> &getTransformFeedbackVaryingNames() const 228 { 229 return mTransformFeedbackVaryingNames; 230 } getTransformFeedbackBufferMode()231 GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } 232 233 bool hasAnyAttachedShader() const; 234 getAttributeBindings()235 const ProgramBindings &getAttributeBindings() const { return mAttributeBindings; } getUniformLocationBindings()236 const ProgramAliasedBindings &getUniformLocationBindings() const 237 { 238 return mUniformLocationBindings; 239 } getFragmentOutputLocations()240 const ProgramAliasedBindings &getFragmentOutputLocations() const 241 { 242 return mFragmentOutputLocations; 243 } getFragmentOutputIndexes()244 const ProgramAliasedBindings &getFragmentOutputIndexes() const 245 { 246 return mFragmentOutputIndexes; 247 } 248 getExecutable()249 const ProgramExecutable &getExecutable() const 250 { 251 ASSERT(mExecutable); 252 return *mExecutable; 253 } getExecutable()254 ProgramExecutable &getExecutable() 255 { 256 ASSERT(mExecutable); 257 return *mExecutable; 258 } 259 getSharedExecutable()260 const SharedProgramExecutable &getSharedExecutable() const 261 { 262 ASSERT(mExecutable); 263 return mExecutable; 264 } 265 getLabel()266 const std::string &getLabel() const { return mLabel; } 267 hasBinaryRetrieveableHint()268 bool hasBinaryRetrieveableHint() const { return mBinaryRetrieveableHint; } 269 isSeparable()270 bool isSeparable() const { return mSeparable; } 271 272 ShaderType getAttachedTransformFeedbackStage() const; 273 274 private: 275 friend class MemoryProgramCache; 276 friend class Program; 277 278 void updateActiveSamplers(); 279 void updateProgramInterfaceInputs(); 280 void updateProgramInterfaceOutputs(); 281 282 // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. 283 void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex); 284 285 std::string mLabel; 286 287 ShaderMap<SharedCompileJob> mShaderCompileJobs; 288 ShaderMap<SharedCompiledShaderState> mAttachedShaders; 289 290 std::vector<std::string> mTransformFeedbackVaryingNames; 291 GLenum mTransformFeedbackBufferMode; 292 293 bool mBinaryRetrieveableHint; 294 bool mSeparable; 295 296 ProgramBindings mAttributeBindings; 297 298 // Note that this has nothing to do with binding layout qualifiers that can be set for some 299 // uniforms in GLES3.1+. It is used to pre-set the location of uniforms. 300 ProgramAliasedBindings mUniformLocationBindings; 301 302 // EXT_blend_func_extended 303 ProgramAliasedBindings mFragmentOutputLocations; 304 ProgramAliasedBindings mFragmentOutputIndexes; 305 306 InfoLog mInfoLog; 307 308 // The result of the link. State that is not the link output should remain in ProgramState, 309 // while the link output should be placed in ProgramExecutable. 310 // 311 // This is a shared_ptr because it can be "installed" in the context as part of the rendering 312 // context. Similarly, it can be installed in a program pipeline. Once the executable is 313 // installed, the actual Program should not be referenced; it may have been unsuccessfully 314 // relinked and its executable in an unusable state. 315 SharedProgramExecutable mExecutable; 316 }; 317 318 struct ProgramVaryingRef 319 { getProgramVaryingRef320 const sh::ShaderVariable *get(ShaderType stage) const 321 { 322 ASSERT(stage == frontShaderStage || stage == backShaderStage); 323 const sh::ShaderVariable *ref = stage == frontShaderStage ? frontShader : backShader; 324 ASSERT(ref); 325 return ref; 326 } 327 328 const sh::ShaderVariable *frontShader = nullptr; 329 const sh::ShaderVariable *backShader = nullptr; 330 ShaderType frontShaderStage = ShaderType::InvalidEnum; 331 ShaderType backShaderStage = ShaderType::InvalidEnum; 332 }; 333 334 using ProgramMergedVaryings = std::vector<ProgramVaryingRef>; 335 336 class Program final : public LabeledObject, public angle::Subject 337 { 338 public: 339 Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle); 340 void onDestroy(const Context *context); 341 342 ShaderProgramID id() const; 343 344 angle::Result setLabel(const Context *context, const std::string &label) override; 345 const std::string &getLabel() const override; 346 getImplementation()347 ANGLE_INLINE rx::ProgramImpl *getImplementation() const 348 { 349 ASSERT(!mLinkingState); 350 return mProgram; 351 } 352 353 void attachShader(const Context *context, Shader *shader); 354 void detachShader(const Context *context, Shader *shader); 355 int getAttachedShadersCount() const; 356 357 Shader *getAttachedShader(ShaderType shaderType) const; 358 359 void bindAttributeLocation(const Context *context, GLuint index, const char *name); 360 void bindUniformLocation(const Context *context, UniformLocation location, const char *name); 361 362 // EXT_blend_func_extended 363 void bindFragmentOutputLocation(const Context *context, GLuint index, const char *name); 364 void bindFragmentOutputIndex(const Context *context, GLuint index, const char *name); 365 366 // KHR_parallel_shader_compile 367 // Try to link the program asynchronously. As a result, background threads may be launched to 368 // execute the linking tasks concurrently. 369 angle::Result link(const Context *context, angle::JobResultExpectancy resultExpectancy); 370 371 // Peek whether there is any running linking tasks. 372 bool isLinking() const; hasLinkingState()373 bool hasLinkingState() const { return mLinkingState != nullptr; } 374 isLinked()375 bool isLinked() const 376 { 377 ASSERT(!mLinkingState); 378 return mLinked; 379 } 380 bool isBinaryReady(const Context *context); cacheProgramBinaryIfNecessary(const Context * context)381 ANGLE_INLINE void cacheProgramBinaryIfNecessary(const Context *context) 382 { 383 // This function helps ensure the program binary is cached, even if the backend waits for 384 // post-link tasks without the knowledge of the front-end. 385 if (!mIsBinaryCached && !mState.mBinaryRetrieveableHint && 386 mState.mExecutable->mPostLinkSubTasks.empty()) 387 { 388 cacheProgramBinaryIfNotAlready(context); 389 } 390 } 391 392 angle::Result setBinary(const Context *context, 393 GLenum binaryFormat, 394 const void *binary, 395 GLsizei length); 396 angle::Result getBinary(Context *context, 397 GLenum *binaryFormat, 398 void *binary, 399 GLsizei bufSize, 400 GLsizei *length); 401 GLint getBinaryLength(Context *context); 402 void setBinaryRetrievableHint(bool retrievable); 403 bool getBinaryRetrievableHint() const; 404 405 angle::Result loadBinary(const Context *context, 406 const void *binary, 407 GLsizei length, 408 egl::CacheGetResult *resultOut); 409 getInfoLog()410 InfoLog &getInfoLog() { return mState.mInfoLog; } 411 int getInfoLogLength() const; 412 void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; 413 414 void setSeparable(const Context *context, bool separable); isSeparable()415 bool isSeparable() const { return mState.mSeparable; } 416 417 void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const; 418 419 void bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding); 420 421 void setTransformFeedbackVaryings(const Context *context, 422 GLsizei count, 423 const GLchar *const *varyings, 424 GLenum bufferMode); getTransformFeedbackBufferMode()425 GLenum getTransformFeedbackBufferMode() const { return mState.mTransformFeedbackBufferMode; } 426 addRef()427 ANGLE_INLINE void addRef() { mRefCount++; } 428 release(const Context * context)429 ANGLE_INLINE void release(const Context *context) 430 { 431 mRefCount--; 432 433 if (mRefCount == 0 && mDeleteStatus) 434 { 435 deleteSelf(context); 436 } 437 } 438 439 unsigned int getRefCount() const; isInUse()440 bool isInUse() const { return getRefCount() != 0; } 441 void flagForDeletion(); 442 bool isFlaggedForDeletion() const; 443 444 void validate(const Caps &caps); 445 bool isValidated() const; 446 getState()447 const ProgramState &getState() const { return mState; } 448 getAttributeBindings()449 const ProgramBindings &getAttributeBindings() const { return mState.getAttributeBindings(); } getUniformLocationBindings()450 const ProgramAliasedBindings &getUniformLocationBindings() const 451 { 452 return mState.getUniformLocationBindings(); 453 } getFragmentOutputLocations()454 const ProgramAliasedBindings &getFragmentOutputLocations() const 455 { 456 return mState.getFragmentOutputLocations(); 457 } getFragmentOutputIndexes()458 const ProgramAliasedBindings &getFragmentOutputIndexes() const 459 { 460 return mState.getFragmentOutputIndexes(); 461 } 462 463 // Try to resolve linking. Inlined to make sure its overhead is as low as possible. resolveLink(const Context * context)464 void resolveLink(const Context *context) 465 { 466 if (mLinkingState) 467 { 468 resolveLinkImpl(context); 469 } 470 } 471 472 // Writes a program's binary to |mBinary|. 473 angle::Result serialize(const Context *context); getSerializedBinary()474 const angle::MemoryBuffer &getSerializedBinary() const { return mBinary; } 475 serial()476 rx::UniqueSerial serial() const { return mSerial; } 477 getExecutable()478 const ProgramExecutable &getExecutable() const { return mState.getExecutable(); } getExecutable()479 ProgramExecutable &getExecutable() { return mState.getExecutable(); } getSharedExecutable()480 const SharedProgramExecutable &getSharedExecutable() const 481 { 482 return mState.getSharedExecutable(); 483 } 484 485 private: 486 class MainLinkLoadTask; 487 class MainLoadTask; 488 class MainLinkTask; 489 class MainLinkLoadEvent; 490 491 friend class ProgramPipeline; 492 friend class MainLinkLoadTask; 493 friend class MainLoadTask; 494 friend class MainLinkTask; 495 496 struct LinkingState; 497 ~Program() override; 498 499 // Loads program state according to the specified binary blob. Returns true on success. 500 bool deserialize(const Context *context, BinaryInputStream &stream); 501 502 void unlink(); 503 void setupExecutableForLink(const Context *context); 504 void deleteSelf(const Context *context); 505 506 angle::Result linkJobImpl(const Caps &caps, 507 const Limitations &limitations, 508 const Version &clientVersion, 509 bool isWebGL, 510 LinkingVariables *linkingVariables, 511 ProgramLinkedResources *resources, 512 ProgramMergedVaryings *mergedVaryingsOut); 513 514 void makeNewExecutable(const Context *context); 515 516 bool linkValidateShaders(); 517 void linkShaders(); 518 bool linkAttributes(const Caps &caps, const Limitations &limitations, bool webglCompatibility); 519 bool linkVaryings(); 520 521 bool linkUniforms(const Caps &caps, 522 const Version &clientVersion, 523 std::vector<UnusedUniform> *unusedUniformsOutOrNull, 524 GLuint *combinedImageUniformsOut); 525 526 void updateLinkedShaderStages(); 527 528 // Block until linking is finished and resolve it. 529 void resolveLinkImpl(const Context *context); 530 // Block until post-link tasks are finished. 531 void waitForPostLinkTasks(const Context *context); 532 533 void postResolveLink(const Context *context); 534 void cacheProgramBinaryIfNotAlready(const Context *context); 535 536 void dumpProgramInfo(const Context *context) const; 537 538 rx::UniqueSerial mSerial; 539 ProgramState mState; 540 rx::ProgramImpl *mProgram; 541 542 bool mValidated; 543 // Flag to indicate that the program can be deleted when no longer in use 544 bool mDeleteStatus; 545 // Whether the program binary is implicitly cached yet. This is usually done in 546 // |resolveLinkImpl|, but may be deferred in the presence of post-link tasks. In that case, 547 // |waitForPostLinkTasks| would cache the binary. However, if the wait on the tasks is done by 548 // the backend itself, this caching will not be done. This flag is used to make sure the binary 549 // is eventually cached at some point in the future. 550 bool mIsBinaryCached; 551 552 bool mLinked; 553 std::unique_ptr<LinkingState> mLinkingState; 554 555 egl::BlobCache::Key mProgramHash; 556 557 unsigned int mRefCount; 558 559 ShaderProgramManager *mResourceManager; 560 const ShaderProgramID mHandle; 561 562 // ProgramState::mAttachedShaders holds a reference to shaders' compiled state, which is all the 563 // program and the backends require after link. The actual shaders linked to the program are 564 // stored here to support shader attach/detach and link without providing access to them in the 565 // backends. 566 ShaderMap<Shader *> mAttachedShaders; 567 568 // A cache of the program binary, prepared by |serialize()|. OpenGL requires the application to 569 // query the length of the binary first (requiring a call to |serialize()|), and then get the 570 // actual binary. This cache ensures the second call does not need to call |serialize()| again. 571 angle::MemoryBuffer mBinary; 572 573 angle::SimpleMutex mHistogramMutex; 574 }; 575 } // namespace gl 576 577 #endif // LIBANGLE_PROGRAM_H_ 578