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 Shader; 55 class ShaderProgramManager; 56 class State; 57 struct UnusedUniform; 58 struct Version; 59 60 extern const char *const g_fakepath; 61 62 enum class LinkMismatchError 63 { 64 // Shared 65 NO_MISMATCH, 66 TYPE_MISMATCH, 67 ARRAY_SIZE_MISMATCH, 68 PRECISION_MISMATCH, 69 STRUCT_NAME_MISMATCH, 70 FIELD_NUMBER_MISMATCH, 71 FIELD_NAME_MISMATCH, 72 73 // Varying specific 74 INTERPOLATION_TYPE_MISMATCH, 75 INVARIANCE_MISMATCH, 76 77 // Uniform specific 78 BINDING_MISMATCH, 79 LOCATION_MISMATCH, 80 OFFSET_MISMATCH, 81 INSTANCE_NAME_MISMATCH, 82 FORMAT_MISMATCH, 83 84 // Interface block specific 85 LAYOUT_QUALIFIER_MISMATCH, 86 MATRIX_PACKING_MISMATCH, 87 }; 88 89 void LogLinkMismatch(InfoLog &infoLog, 90 const std::string &variableName, 91 const char *variableType, 92 LinkMismatchError linkError, 93 const std::string &mismatchedStructOrBlockFieldName, 94 ShaderType shaderType1, 95 ShaderType shaderType2); 96 97 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock); 98 99 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var); 100 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var); 101 102 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var); 103 void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var); 104 105 // Struct used for correlating uniforms/elements of uniform arrays to handles 106 struct VariableLocation 107 { 108 static constexpr unsigned int kUnused = GL_INVALID_INDEX; 109 110 VariableLocation(); 111 VariableLocation(unsigned int arrayIndex, unsigned int index); 112 113 // If used is false, it means this location is only used to fill an empty space in an array, 114 // and there is no corresponding uniform variable for this location. It can also mean the 115 // uniform was optimized out by the implementation. usedVariableLocation116 bool used() const { return (index != kUnused); } markUnusedVariableLocation117 void markUnused() { index = kUnused; } markIgnoredVariableLocation118 void markIgnored() { ignored = true; } 119 120 bool operator==(const VariableLocation &other) const 121 { 122 return arrayIndex == other.arrayIndex && index == other.index; 123 } 124 125 // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays. 126 unsigned int arrayIndex; 127 // "index" is an index of the variable. The variable contains the indices for other than the 128 // innermost GLSL arrays. 129 unsigned int index; 130 131 // If this location was bound to an unreferenced uniform. Setting data on this uniform is a 132 // no-op. 133 bool ignored; 134 }; 135 136 // Information about a variable binding. 137 // Currently used by CHROMIUM_path_rendering 138 struct BindingInfo 139 { 140 // The type of binding, for example GL_FLOAT_VEC3. 141 // This can be GL_NONE if the variable is optimized away. 142 GLenum type; 143 144 // This is the name of the variable in 145 // the translated shader program. Note that 146 // this can be empty in the case where the 147 // variable has been optimized away. 148 std::string name; 149 150 // True if the binding is valid, otherwise false. 151 bool valid; 152 }; 153 154 // A varying with tranform feedback enabled. If it's an array, either the whole array or one of its 155 // elements specified by 'arrayIndex' can set to be enabled. 156 struct TransformFeedbackVarying : public sh::ShaderVariable 157 { TransformFeedbackVaryingTransformFeedbackVarying158 TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn) 159 : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn) 160 { 161 ASSERT(!isArrayOfArrays()); 162 } 163 TransformFeedbackVaryingTransformFeedbackVarying164 TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent) 165 : arrayIndex(GL_INVALID_INDEX) 166 { 167 sh::ShaderVariable *thisVar = this; 168 *thisVar = field; 169 interpolation = parent.interpolation; 170 isInvariant = parent.isInvariant; 171 name = parent.name + "." + name; 172 mappedName = parent.mappedName + "." + mappedName; 173 } 174 nameWithArrayIndexTransformFeedbackVarying175 std::string nameWithArrayIndex() const 176 { 177 std::stringstream fullNameStr; 178 fullNameStr << name; 179 if (arrayIndex != GL_INVALID_INDEX) 180 { 181 fullNameStr << "[" << arrayIndex << "]"; 182 } 183 return fullNameStr.str(); 184 } sizeTransformFeedbackVarying185 GLsizei size() const 186 { 187 return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1); 188 } 189 190 GLuint arrayIndex; 191 }; 192 193 struct ProgramBinding 194 { ProgramBindingProgramBinding195 ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {} ProgramBindingProgramBinding196 ProgramBinding(GLuint index) : location(index), aliased(false) {} 197 198 GLuint location; 199 // Whether another binding was set that may potentially alias this. 200 bool aliased; 201 }; 202 203 class ProgramBindings final : angle::NonCopyable 204 { 205 public: 206 ProgramBindings(); 207 ~ProgramBindings(); 208 209 void bindLocation(GLuint index, const std::string &name); 210 int getBindingByName(const std::string &name) const; 211 int getBinding(const sh::ShaderVariable &variable) const; 212 213 using const_iterator = std::unordered_map<std::string, GLuint>::const_iterator; 214 const_iterator begin() const; 215 const_iterator end() const; 216 217 private: 218 std::unordered_map<std::string, GLuint> mBindings; 219 }; 220 221 // Uniforms and Fragment Outputs require special treatment due to array notation (e.g., "[0]") 222 class ProgramAliasedBindings final : angle::NonCopyable 223 { 224 public: 225 ProgramAliasedBindings(); 226 ~ProgramAliasedBindings(); 227 228 void bindLocation(GLuint index, const std::string &name); 229 int getBindingByName(const std::string &name) const; 230 int getBindingByLocation(GLuint location) const; 231 int getBinding(const sh::ShaderVariable &variable) const; 232 233 using const_iterator = std::unordered_map<std::string, ProgramBinding>::const_iterator; 234 const_iterator begin() const; 235 const_iterator end() const; 236 237 private: 238 std::unordered_map<std::string, ProgramBinding> mBindings; 239 }; 240 241 class ProgramState final : angle::NonCopyable 242 { 243 public: 244 ProgramState(); 245 ~ProgramState(); 246 247 const std::string &getLabel(); 248 249 Shader *getAttachedShader(ShaderType shaderType) const; getAttachedShaders()250 const gl::ShaderMap<Shader *> &getAttachedShaders() const { return mAttachedShaders; } getTransformFeedbackVaryingNames()251 const std::vector<std::string> &getTransformFeedbackVaryingNames() const 252 { 253 return mTransformFeedbackVaryingNames; 254 } getTransformFeedbackBufferMode()255 GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } getUniformBlockBinding(GLuint uniformBlockIndex)256 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const 257 { 258 ASSERT(uniformBlockIndex < mUniformBlocks.size()); 259 return mUniformBlocks[uniformBlockIndex].binding; 260 } getShaderStorageBlockBinding(GLuint blockIndex)261 GLuint getShaderStorageBlockBinding(GLuint blockIndex) const 262 { 263 ASSERT(blockIndex < mShaderStorageBlocks.size()); 264 return mShaderStorageBlocks[blockIndex].binding; 265 } getActiveUniformBlockBindingsMask()266 const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const 267 { 268 return mActiveUniformBlockBindings; 269 } getProgramInputs()270 const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; } getActiveOutputVariables()271 DrawBufferMask getActiveOutputVariables() const { return mActiveOutputVariables; } getOutputVariables()272 const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; } getOutputLocations()273 const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; } getSecondaryOutputLocations()274 const std::vector<VariableLocation> &getSecondaryOutputLocations() const 275 { 276 return mSecondaryOutputLocations; 277 } getUniforms()278 const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; } getUniformLocations()279 const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; } getUniformBlocks()280 const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } getShaderStorageBlocks()281 const std::vector<InterfaceBlock> &getShaderStorageBlocks() const 282 { 283 return mShaderStorageBlocks; 284 } getBufferVariables()285 const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; } getSamplerBindings()286 const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; } getImageBindings()287 const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; } getComputeShaderLocalSize()288 const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } getDefaultUniformRange()289 const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; } getSamplerUniformRange()290 const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; } getImageUniformRange()291 const RangeUI &getImageUniformRange() const { return mImageUniformRange; } getAtomicCounterUniformRange()292 const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; } 293 getLinkedTransformFeedbackVaryings()294 const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const 295 { 296 return mLinkedTransformFeedbackVaryings; 297 } getTransformFeedbackStrides()298 const std::vector<GLsizei> &getTransformFeedbackStrides() const 299 { 300 return mTransformFeedbackStrides; 301 } getAtomicCounterBuffers()302 const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const 303 { 304 return mAtomicCounterBuffers; 305 } 306 307 // Count the number of uniform and storage buffer declarations, counting arrays as one. 308 size_t getTransformFeedbackBufferCount() const; 309 310 GLuint getUniformIndexFromName(const std::string &name) const; 311 GLuint getUniformIndexFromLocation(UniformLocation location) const; 312 Optional<GLuint> getSamplerIndex(UniformLocation location) const; 313 bool isSamplerUniformIndex(GLuint index) const; 314 GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const; 315 GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const; 316 bool isImageUniformIndex(GLuint index) const; 317 GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const; 318 GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const; 319 GLuint getAttributeLocation(const std::string &name) const; 320 321 GLuint getBufferVariableIndexFromName(const std::string &name) const; 322 getNumViews()323 int getNumViews() const { return mNumViews; } usesMultiview()324 bool usesMultiview() const { return mNumViews != -1; } 325 326 bool hasAttachedShader() const; 327 328 ShaderType getFirstAttachedShaderStageType() const; 329 ShaderType getLastAttachedShaderStageType() const; 330 getUniformLocationBindings()331 const ProgramAliasedBindings &getUniformLocationBindings() const 332 { 333 return mUniformLocationBindings; 334 } 335 getProgramExecutable()336 const ProgramExecutable &getProgramExecutable() const { return mExecutable; } getProgramExecutable()337 ProgramExecutable &getProgramExecutable() { return mExecutable; } 338 hasDefaultUniforms()339 bool hasDefaultUniforms() const { return !getDefaultUniformRange().empty(); } hasTextures()340 bool hasTextures() const { return !getSamplerBindings().empty(); } hasUniformBuffers()341 bool hasUniformBuffers() const { return !getUniformBlocks().empty(); } hasStorageBuffers()342 bool hasStorageBuffers() const { return !getShaderStorageBlocks().empty(); } hasAtomicCounterBuffers()343 bool hasAtomicCounterBuffers() const { return !getAtomicCounterBuffers().empty(); } hasImages()344 bool hasImages() const { return !getImageBindings().empty(); } hasTransformFeedbackOutput()345 bool hasTransformFeedbackOutput() const 346 { 347 return !getLinkedTransformFeedbackVaryings().empty(); 348 } hasEarlyFragmentTestsOptimization()349 bool hasEarlyFragmentTestsOptimization() const { return mEarlyFramentTestsOptimization; } 350 isShaderMarkedForDetach(gl::ShaderType shaderType)351 bool isShaderMarkedForDetach(gl::ShaderType shaderType) const 352 { 353 return mAttachedShadersMarkedForDetach[shaderType]; 354 } 355 356 private: 357 friend class MemoryProgramCache; 358 friend class Program; 359 360 void updateTransformFeedbackStrides(); 361 void updateActiveSamplers(); 362 void updateActiveImages(); 363 void updateProgramInterfaceInputs(); 364 void updateProgramInterfaceOutputs(); 365 366 // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'. 367 void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex); 368 369 std::string mLabel; 370 371 sh::WorkGroupSize mComputeShaderLocalSize; 372 373 ShaderMap<Shader *> mAttachedShaders; 374 ShaderMap<bool> mAttachedShadersMarkedForDetach; 375 376 uint32_t mLocationsUsedForXfbExtension; 377 std::vector<std::string> mTransformFeedbackVaryingNames; 378 std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings; 379 GLenum mTransformFeedbackBufferMode; 380 381 // For faster iteration on the blocks currently being bound. 382 UniformBlockBindingMask mActiveUniformBlockBindings; 383 384 // Vertex attributes, Fragment input varyings, etc. 385 std::vector<sh::ShaderVariable> mProgramInputs; 386 387 // Uniforms are sorted in order: 388 // 1. Non-opaque uniforms 389 // 2. Sampler uniforms 390 // 3. Image uniforms 391 // 4. Atomic counter uniforms 392 // 5. Uniform block uniforms 393 // This makes opaque uniform validation easier, since we don't need a separate list. 394 // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section 395 // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each 396 // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include 397 // [0] in the end. This makes implementation of queries simpler. 398 std::vector<LinkedUniform> mUniforms; 399 400 std::vector<VariableLocation> mUniformLocations; 401 std::vector<InterfaceBlock> mUniformBlocks; 402 std::vector<BufferVariable> mBufferVariables; 403 std::vector<InterfaceBlock> mShaderStorageBlocks; 404 std::vector<AtomicCounterBuffer> mAtomicCounterBuffers; 405 RangeUI mDefaultUniformRange; 406 RangeUI mSamplerUniformRange; 407 RangeUI mImageUniformRange; 408 RangeUI mAtomicCounterUniformRange; 409 410 // An array of the samplers that are used by the program 411 std::vector<SamplerBinding> mSamplerBindings; 412 413 // An array of the images that are used by the program 414 std::vector<ImageBinding> mImageBindings; 415 416 // Names and mapped names of output variables that are arrays include [0] in the end, similarly 417 // to uniforms. 418 std::vector<sh::ShaderVariable> mOutputVariables; 419 std::vector<VariableLocation> mOutputLocations; 420 421 // EXT_blend_func_extended secondary outputs (ones with index 1) in ESSL 3.00 shaders. 422 std::vector<VariableLocation> mSecondaryOutputLocations; 423 424 DrawBufferMask mActiveOutputVariables; 425 426 // Fragment output variable base types: FLOAT, INT, or UINT. Ordered by location. 427 std::vector<GLenum> mOutputVariableTypes; 428 ComponentTypeMask mDrawBufferTypeMask; 429 430 bool mBinaryRetrieveableHint; 431 bool mSeparable; 432 bool mEarlyFramentTestsOptimization; 433 434 // ANGLE_multiview. 435 int mNumViews; 436 437 // GL_EXT_geometry_shader. 438 PrimitiveMode mGeometryShaderInputPrimitiveType; 439 PrimitiveMode mGeometryShaderOutputPrimitiveType; 440 int mGeometryShaderInvocations; 441 int mGeometryShaderMaxVertices; 442 443 // GL_ANGLE_multi_draw 444 int mDrawIDLocation; 445 446 // GL_ANGLE_base_vertex_base_instance 447 int mBaseVertexLocation; 448 int mBaseInstanceLocation; 449 // Cached value of base vertex and base instance 450 // need to reset them to zero if using non base vertex or base instance draw calls. 451 GLint mCachedBaseVertex; 452 GLuint mCachedBaseInstance; 453 454 // The size of the data written to each transform feedback buffer per vertex. 455 std::vector<GLsizei> mTransformFeedbackStrides; 456 457 // Note that this has nothing to do with binding layout qualifiers that can be set for some 458 // uniforms in GLES3.1+. It is used to pre-set the location of uniforms. 459 ProgramAliasedBindings mUniformLocationBindings; 460 461 ProgramExecutable mExecutable; 462 }; 463 464 struct ProgramVaryingRef 465 { getProgramVaryingRef466 const sh::ShaderVariable *get(ShaderType stage) const 467 { 468 ASSERT(stage == frontShaderStage || stage == backShaderStage); 469 const sh::ShaderVariable *ref = stage == frontShaderStage ? frontShader : backShader; 470 ASSERT(ref); 471 return ref; 472 } 473 474 const sh::ShaderVariable *frontShader = nullptr; 475 const sh::ShaderVariable *backShader = nullptr; 476 ShaderType frontShaderStage = ShaderType::InvalidEnum; 477 ShaderType backShaderStage = ShaderType::InvalidEnum; 478 }; 479 480 using ProgramMergedVaryings = std::vector<ProgramVaryingRef>; 481 482 class Program final : angle::NonCopyable, public LabeledObject 483 { 484 public: 485 Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle); 486 void onDestroy(const Context *context); 487 488 ShaderProgramID id() const; 489 490 void setLabel(const Context *context, const std::string &label) override; 491 const std::string &getLabel() const override; 492 getImplementation()493 ANGLE_INLINE rx::ProgramImpl *getImplementation() const 494 { 495 ASSERT(mLinkResolved); 496 return mProgram; 497 } 498 499 void attachShader(const Context *context, Shader *shader); 500 void detachShader(const Context *context, Shader *shader); 501 int getAttachedShadersCount() const; 502 503 const Shader *getAttachedShader(ShaderType shaderType) const; 504 505 void bindAttributeLocation(GLuint index, const char *name); 506 void bindUniformLocation(UniformLocation location, const char *name); 507 508 // EXT_blend_func_extended 509 void bindFragmentOutputLocation(GLuint index, const char *name); 510 void bindFragmentOutputIndex(GLuint index, const char *name); 511 512 angle::Result linkMergedVaryings(const Context *context, 513 const ProgramMergedVaryings &mergedVaryings); 514 515 // KHR_parallel_shader_compile 516 // Try to link the program asynchrously. As a result, background threads may be launched to 517 // execute the linking tasks concurrently. 518 angle::Result link(const Context *context); 519 520 // Peek whether there is any running linking tasks. 521 bool isLinking() const; 522 isLinked()523 bool isLinked() const 524 { 525 ASSERT(mLinkResolved); 526 return mLinked; 527 } 528 529 angle::Result loadBinary(const Context *context, 530 GLenum binaryFormat, 531 const void *binary, 532 GLsizei length); 533 angle::Result saveBinary(Context *context, 534 GLenum *binaryFormat, 535 void *binary, 536 GLsizei bufSize, 537 GLsizei *length) const; 538 GLint getBinaryLength(Context *context) const; 539 void setBinaryRetrievableHint(bool retrievable); 540 bool getBinaryRetrievableHint() const; 541 542 void setSeparable(bool separable); 543 bool isSeparable() const; 544 545 void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const; 546 547 GLuint getAttributeLocation(const std::string &name) const; 548 549 void getActiveAttribute(GLuint index, 550 GLsizei bufsize, 551 GLsizei *length, 552 GLint *size, 553 GLenum *type, 554 GLchar *name) const; 555 GLint getActiveAttributeCount() const; 556 GLint getActiveAttributeMaxLength() const; 557 const std::vector<sh::ShaderVariable> &getAttributes() const; 558 559 GLint getFragDataLocation(const std::string &name) const; 560 size_t getOutputResourceCount() const; 561 const std::vector<GLenum> &getOutputVariableTypes() const; getActiveOutputVariables()562 DrawBufferMask getActiveOutputVariables() const 563 { 564 ASSERT(mLinkResolved); 565 return mState.mActiveOutputVariables; 566 } 567 568 // EXT_blend_func_extended 569 GLint getFragDataIndex(const std::string &name) const; 570 571 void getActiveUniform(GLuint index, 572 GLsizei bufsize, 573 GLsizei *length, 574 GLint *size, 575 GLenum *type, 576 GLchar *name) const; 577 GLint getActiveUniformCount() const; 578 size_t getActiveBufferVariableCount() const; 579 GLint getActiveUniformMaxLength() const; 580 bool isValidUniformLocation(UniformLocation location) const; 581 const LinkedUniform &getUniformByLocation(UniformLocation location) const; 582 const VariableLocation &getUniformLocation(UniformLocation location) const; 583 getUniformLocations()584 const std::vector<VariableLocation> &getUniformLocations() const 585 { 586 ASSERT(mLinkResolved); 587 return mState.mUniformLocations; 588 } 589 getUniformByIndex(GLuint index)590 const LinkedUniform &getUniformByIndex(GLuint index) const 591 { 592 ASSERT(mLinkResolved); 593 ASSERT(index < static_cast<size_t>(mState.mUniforms.size())); 594 return mState.mUniforms[index]; 595 } 596 597 const BufferVariable &getBufferVariableByIndex(GLuint index) const; 598 599 enum SetUniformResult 600 { 601 SamplerChanged, 602 NoSamplerChange, 603 }; 604 605 UniformLocation getUniformLocation(const std::string &name) const; 606 GLuint getUniformIndex(const std::string &name) const; 607 void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v); 608 void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v); 609 void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v); 610 void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v); 611 void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v); 612 void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v); 613 void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v); 614 void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v); 615 void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v); 616 void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v); 617 void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v); 618 void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v); 619 void setUniformMatrix2fv(UniformLocation location, 620 GLsizei count, 621 GLboolean transpose, 622 const GLfloat *value); 623 void setUniformMatrix3fv(UniformLocation location, 624 GLsizei count, 625 GLboolean transpose, 626 const GLfloat *value); 627 void setUniformMatrix4fv(UniformLocation location, 628 GLsizei count, 629 GLboolean transpose, 630 const GLfloat *value); 631 void setUniformMatrix2x3fv(UniformLocation location, 632 GLsizei count, 633 GLboolean transpose, 634 const GLfloat *value); 635 void setUniformMatrix3x2fv(UniformLocation location, 636 GLsizei count, 637 GLboolean transpose, 638 const GLfloat *value); 639 void setUniformMatrix2x4fv(UniformLocation location, 640 GLsizei count, 641 GLboolean transpose, 642 const GLfloat *value); 643 void setUniformMatrix4x2fv(UniformLocation location, 644 GLsizei count, 645 GLboolean transpose, 646 const GLfloat *value); 647 void setUniformMatrix3x4fv(UniformLocation location, 648 GLsizei count, 649 GLboolean transpose, 650 const GLfloat *value); 651 void setUniformMatrix4x3fv(UniformLocation location, 652 GLsizei count, 653 GLboolean transpose, 654 const GLfloat *value); 655 656 void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const; 657 void getUniformiv(const Context *context, UniformLocation location, GLint *params) const; 658 void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const; 659 660 void getActiveUniformBlockName(const GLuint blockIndex, 661 GLsizei bufSize, 662 GLsizei *length, 663 GLchar *blockName) const; 664 void getActiveShaderStorageBlockName(const GLuint blockIndex, 665 GLsizei bufSize, 666 GLsizei *length, 667 GLchar *blockName) const; 668 getActiveUniformBlockCount()669 ANGLE_INLINE GLuint getActiveUniformBlockCount() const 670 { 671 ASSERT(mLinkResolved); 672 return static_cast<GLuint>(mState.mUniformBlocks.size()); 673 } 674 getActiveAtomicCounterBufferCount()675 ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const 676 { 677 ASSERT(mLinkResolved); 678 return static_cast<GLuint>(mState.mAtomicCounterBuffers.size()); 679 } 680 getActiveShaderStorageBlockCount()681 ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const 682 { 683 ASSERT(mLinkResolved); 684 return static_cast<GLuint>(mState.mShaderStorageBlocks.size()); 685 } 686 687 GLint getActiveUniformBlockMaxNameLength() const; 688 GLint getActiveShaderStorageBlockMaxNameLength() const; 689 690 GLuint getUniformBlockIndex(const std::string &name) const; 691 GLuint getShaderStorageBlockIndex(const std::string &name) const; 692 693 void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); 694 GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; 695 GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const; 696 697 const InterfaceBlock &getUniformBlockByIndex(GLuint index) const; 698 const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const; 699 700 void setTransformFeedbackVaryings(GLsizei count, 701 const GLchar *const *varyings, 702 GLenum bufferMode); 703 void getTransformFeedbackVarying(GLuint index, 704 GLsizei bufSize, 705 GLsizei *length, 706 GLsizei *size, 707 GLenum *type, 708 GLchar *name) const; 709 GLsizei getTransformFeedbackVaryingCount() const; 710 GLsizei getTransformFeedbackVaryingMaxLength() const; 711 GLenum getTransformFeedbackBufferMode() const; 712 GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const; 713 const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const; 714 715 bool hasDrawIDUniform() const; 716 void setDrawIDUniform(GLint drawid); 717 718 bool hasBaseVertexUniform() const; 719 void setBaseVertexUniform(GLint baseVertex); 720 bool hasBaseInstanceUniform() const; 721 void setBaseInstanceUniform(GLuint baseInstance); 722 addRef()723 ANGLE_INLINE void addRef() 724 { 725 ASSERT(mLinkResolved); 726 mRefCount++; 727 } 728 release(const Context * context)729 ANGLE_INLINE void release(const Context *context) 730 { 731 ASSERT(mLinkResolved); 732 mRefCount--; 733 734 if (mRefCount == 0 && mDeleteStatus) 735 { 736 deleteSelf(context); 737 } 738 } 739 740 unsigned int getRefCount() const; isInUse()741 bool isInUse() const { return getRefCount() != 0; } 742 void flagForDeletion(); 743 bool isFlaggedForDeletion() const; 744 745 void validate(const Caps &caps); validateSamplers(InfoLog * infoLog,const Caps & caps)746 bool validateSamplers(InfoLog *infoLog, const Caps &caps) 747 { 748 // Skip cache if we're using an infolog, so we get the full error. 749 // Also skip the cache if the sample mapping has changed, or if we haven't ever validated. 750 if (infoLog == nullptr && mCachedValidateSamplersResult.valid()) 751 { 752 return mCachedValidateSamplersResult.value(); 753 } 754 755 return validateSamplersImpl(infoLog, caps); 756 } 757 758 bool isValidated() const; 759 getCachedValidateSamplersResult()760 Optional<bool> getCachedValidateSamplersResult() { return mCachedValidateSamplersResult; } setCachedValidateSamplersResult(bool result)761 void setCachedValidateSamplersResult(bool result) { mCachedValidateSamplersResult = result; } 762 763 const std::vector<SamplerBinding> &getSamplerBindings() const; getImageBindings()764 const std::vector<ImageBinding> &getImageBindings() const 765 { 766 ASSERT(mLinkResolved); 767 return mState.mImageBindings; 768 } 769 const sh::WorkGroupSize &getComputeShaderLocalSize() const; 770 PrimitiveMode getGeometryShaderInputPrimitiveType() const; 771 PrimitiveMode getGeometryShaderOutputPrimitiveType() const; 772 GLint getGeometryShaderInvocations() const; 773 GLint getGeometryShaderMaxVertices() const; 774 getState()775 const ProgramState &getState() const 776 { 777 ASSERT(mLinkResolved); 778 return mState; 779 } 780 781 static LinkMismatchError LinkValidateVariablesBase( 782 const sh::ShaderVariable &variable1, 783 const sh::ShaderVariable &variable2, 784 bool validatePrecision, 785 bool validateArraySize, 786 std::string *mismatchedStructOrBlockMemberName); 787 788 GLuint getInputResourceIndex(const GLchar *name) const; 789 GLuint getOutputResourceIndex(const GLchar *name) const; 790 void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 791 void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 792 void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const; 793 void getBufferVariableResourceName(GLuint index, 794 GLsizei bufSize, 795 GLsizei *length, 796 GLchar *name) const; 797 const sh::ShaderVariable &getInputResource(size_t index) const; 798 GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const; 799 GLuint getInputResourceMaxNameSize() const; 800 GLuint getOutputResourceMaxNameSize() const; 801 GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const; 802 GLuint getInputResourceLocation(const GLchar *name) const; 803 GLuint getOutputResourceLocation(const GLchar *name) const; 804 const std::string getResourceName(const sh::ShaderVariable &resource) const; 805 const std::string getInputResourceName(GLuint index) const; 806 const std::string getOutputResourceName(GLuint index) const; 807 const sh::ShaderVariable &getOutputResource(size_t index) const; 808 809 const ProgramBindings &getAttributeBindings() const; 810 const ProgramAliasedBindings &getUniformLocationBindings() const; 811 const ProgramAliasedBindings &getFragmentOutputLocations() const; 812 const ProgramAliasedBindings &getFragmentOutputIndexes() const; 813 getNumViews()814 int getNumViews() const 815 { 816 ASSERT(mLinkResolved); 817 return mState.getNumViews(); 818 } 819 usesMultiview()820 bool usesMultiview() const { return mState.usesMultiview(); } 821 822 ComponentTypeMask getDrawBufferTypeMask() const; 823 824 const std::vector<GLsizei> &getTransformFeedbackStrides() const; 825 826 // Program dirty bits. 827 enum DirtyBitType 828 { 829 DIRTY_BIT_UNIFORM_BLOCK_BINDING_0, 830 DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX = 831 DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS, 832 833 DIRTY_BIT_COUNT = DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX, 834 }; 835 836 using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>; 837 838 angle::Result syncState(const Context *context); 839 840 // Try to resolve linking. Inlined to make sure its overhead is as low as possible. resolveLink(const Context * context)841 void resolveLink(const Context *context) 842 { 843 if (!mLinkResolved) 844 { 845 resolveLinkImpl(context); 846 } 847 } 848 hasAnyDirtyBit()849 ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); } 850 getResources()851 gl::ProgramLinkedResources &getResources() const 852 { 853 ASSERT(mResources); 854 return *mResources; 855 } 856 857 // Writes a program's binary to the output memory buffer. 858 angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const; 859 serial()860 rx::Serial serial() const { return mSerial; } 861 getExecutable()862 const ProgramExecutable &getExecutable() const { return mState.getProgramExecutable(); } getExecutable()863 ProgramExecutable &getExecutable() { return mState.getProgramExecutable(); } 864 865 const char *validateDrawStates(const State &state, const gl::Extensions &extensions) const; 866 867 static void getFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings, 868 std::vector<const sh::ShaderVariable *> *filteredVaryingsOut); 869 static bool doShaderVariablesMatch(gl::Shader *generatingShader, 870 gl::Shader *consumingShader, 871 const sh::ShaderVariable &input, 872 const sh::ShaderVariable &output, 873 bool validateGeometryShaderInputs, 874 bool isSeparable, 875 gl::InfoLog &infoLog); 876 static bool linkValidateShaderInterfaceMatching(Shader *generatingShader, 877 Shader *consumingShader, 878 bool isSeparable, 879 InfoLog &infoLog); 880 static bool linkValidateBuiltInVaryings(Shader *vertexShader, 881 Shader *fragmentShader, 882 InfoLog &infoLog); 883 884 private: 885 struct LinkingState; 886 887 ~Program() override; 888 889 // Loads program state according to the specified binary blob. 890 angle::Result deserialize(const Context *context, BinaryInputStream &stream, InfoLog &infoLog); 891 892 void unlink(); 893 void deleteSelf(const Context *context); 894 895 bool linkValidateShaders(InfoLog &infoLog); 896 bool linkAttributes(const Context *context, InfoLog &infoLog); 897 bool linkInterfaceBlocks(const Caps &caps, 898 const Version &version, 899 bool webglCompatibility, 900 InfoLog &infoLog, 901 GLuint *combinedShaderStorageBlocksCount); 902 bool linkVaryings(InfoLog &infoLog) const; 903 904 bool linkUniforms(const Caps &caps, 905 const Version &version, 906 InfoLog &infoLog, 907 const ProgramAliasedBindings &uniformLocationBindings, 908 GLuint *combinedImageUniformsCount, 909 std::vector<UnusedUniform> *unusedUniforms); 910 void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount); 911 bool linkAtomicCounterBuffers(); 912 913 void updateLinkedShaderStages(); 914 915 static LinkMismatchError LinkValidateVaryings(const sh::ShaderVariable &outputVarying, 916 const sh::ShaderVariable &inputVarying, 917 int shaderVersion, 918 bool validateGeometryShaderInputVarying, 919 bool isSeparable, 920 std::string *mismatchedStructFieldName); 921 922 bool linkValidateTransformFeedback(const Version &version, 923 InfoLog &infoLog, 924 const ProgramMergedVaryings &linkedVaryings, 925 ShaderType stage, 926 const Caps &caps) const; 927 928 void gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings, ShaderType stage); 929 930 ProgramMergedVaryings getMergedVaryings() const; 931 int getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const; 932 bool isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const; 933 bool linkOutputVariables(const Caps &caps, 934 const Extensions &extensions, 935 const Version &version, 936 GLuint combinedImageUniformsCount, 937 GLuint combinedShaderStorageBlocksCount); 938 939 void setUniformValuesFromBindingQualifiers(); 940 bool shouldIgnoreUniform(UniformLocation location) const; 941 942 void initInterfaceBlockBindings(); 943 944 // Both these function update the cached uniform values and return a modified "count" 945 // so that the uniform update doesn't overflow the uniform. 946 template <typename T> 947 GLsizei clampUniformCount(const VariableLocation &locationInfo, 948 GLsizei count, 949 int vectorSize, 950 const T *v); 951 template <size_t cols, size_t rows, typename T> 952 GLsizei clampMatrixUniformCount(UniformLocation location, 953 GLsizei count, 954 GLboolean transpose, 955 const T *v); 956 957 void updateSamplerUniform(Context *context, 958 const VariableLocation &locationInfo, 959 GLsizei clampedCount, 960 const GLint *v); 961 962 template <typename DestT> 963 void getUniformInternal(const Context *context, 964 DestT *dataOut, 965 UniformLocation location, 966 GLenum nativeType, 967 int components) const; 968 969 void getResourceName(const std::string name, 970 GLsizei bufSize, 971 GLsizei *length, 972 GLchar *dest) const; 973 974 template <typename T> 975 GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const; 976 977 GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const; 978 GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const; 979 980 bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps); 981 982 // Block until linking is finished and resolve it. 983 void resolveLinkImpl(const gl::Context *context); 984 985 void postResolveLink(const gl::Context *context); 986 987 rx::Serial mSerial; 988 ProgramState mState; 989 rx::ProgramImpl *mProgram; 990 991 bool mValidated; 992 993 ProgramBindings mAttributeBindings; 994 995 // EXT_blend_func_extended 996 ProgramAliasedBindings mFragmentOutputLocations; 997 ProgramAliasedBindings mFragmentOutputIndexes; 998 999 bool mLinked; 1000 bool mLinkResolved; 1001 std::unique_ptr<LinkingState> mLinkingState; 1002 bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use 1003 1004 unsigned int mRefCount; 1005 1006 ShaderProgramManager *mResourceManager; 1007 const ShaderProgramID mHandle; 1008 1009 // Cache for sampler validation 1010 Optional<bool> mCachedValidateSamplersResult; 1011 1012 DirtyBits mDirtyBits; 1013 1014 // TODO: http://anglebug.com/4514: Remove 1015 std::unique_ptr<gl::ProgramLinkedResources> mResources; 1016 }; 1017 } // namespace gl 1018 1019 #endif // LIBANGLE_PROGRAM_H_ 1020