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