ProgramLinkedResources.cpp (89034B)
1 // 2 // Copyright 2017 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 // ProgramLinkedResources.cpp: implements link-time checks for default block uniforms, and generates 8 // uniform locations. Populates data structures related to uniforms so that they can be stored in 9 // program state. 10 11 #include "libANGLE/ProgramLinkedResources.h" 12 13 #include "common/string_utils.h" 14 #include "common/utilities.h" 15 #include "libANGLE/Caps.h" 16 #include "libANGLE/Context.h" 17 #include "libANGLE/Shader.h" 18 #include "libANGLE/features.h" 19 20 namespace gl 21 { 22 namespace 23 { 24 LinkedUniform *FindUniform(std::vector<LinkedUniform> &list, const std::string &name) 25 { 26 for (LinkedUniform &uniform : list) 27 { 28 if (uniform.name == name) 29 return &uniform; 30 } 31 32 return nullptr; 33 } 34 35 template <typename VarT> 36 void SetActive(std::vector<VarT> *list, const std::string &name, ShaderType shaderType, bool active) 37 { 38 for (auto &variable : *list) 39 { 40 if (variable.name == name) 41 { 42 variable.setActive(shaderType, active); 43 return; 44 } 45 } 46 } 47 48 // GLSL ES Spec 3.00.3, section 4.3.5. 49 LinkMismatchError LinkValidateUniforms(const sh::ShaderVariable &uniform1, 50 const sh::ShaderVariable &uniform2, 51 std::string *mismatchedStructFieldName) 52 { 53 #if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED 54 const bool validatePrecisionFeature = true; 55 #else 56 const bool validatePrecisionFeature = false; 57 #endif 58 59 // Validate precision match of uniforms iff they are statically used 60 bool validatePrecision = uniform1.staticUse && uniform2.staticUse && validatePrecisionFeature; 61 LinkMismatchError linkError = LinkValidateProgramVariables( 62 uniform1, uniform2, validatePrecision, false, false, mismatchedStructFieldName); 63 if (linkError != LinkMismatchError::NO_MISMATCH) 64 { 65 return linkError; 66 } 67 68 // GLSL ES Spec 3.10.4, section 4.4.5. 69 if (uniform1.binding != -1 && uniform2.binding != -1 && uniform1.binding != uniform2.binding) 70 { 71 return LinkMismatchError::BINDING_MISMATCH; 72 } 73 74 // GLSL ES Spec 3.10.4, section 9.2.1. 75 if (uniform1.location != -1 && uniform2.location != -1 && 76 uniform1.location != uniform2.location) 77 { 78 return LinkMismatchError::LOCATION_MISMATCH; 79 } 80 if (uniform1.offset != uniform2.offset) 81 { 82 return LinkMismatchError::OFFSET_MISMATCH; 83 } 84 85 return LinkMismatchError::NO_MISMATCH; 86 } 87 88 GLuint GetMaximumShaderUniformVectors(ShaderType shaderType, const Caps &caps) 89 { 90 switch (shaderType) 91 { 92 case ShaderType::Vertex: 93 return static_cast<GLuint>(caps.maxVertexUniformVectors); 94 case ShaderType::Fragment: 95 return static_cast<GLuint>(caps.maxFragmentUniformVectors); 96 97 case ShaderType::Compute: 98 case ShaderType::Geometry: 99 case ShaderType::TessControl: 100 case ShaderType::TessEvaluation: 101 return static_cast<GLuint>(caps.maxShaderUniformComponents[shaderType]) / 4; 102 103 default: 104 UNREACHABLE(); 105 return 0u; 106 } 107 } 108 109 enum class UniformType : uint8_t 110 { 111 Variable = 0, 112 Sampler = 1, 113 Image = 2, 114 AtomicCounter = 3, 115 116 InvalidEnum = 4, 117 EnumCount = 4, 118 }; 119 120 const char *GetUniformResourceNameString(UniformType uniformType) 121 { 122 switch (uniformType) 123 { 124 case UniformType::Variable: 125 return "uniform"; 126 case UniformType::Sampler: 127 return "texture image unit"; 128 case UniformType::Image: 129 return "image uniform"; 130 case UniformType::AtomicCounter: 131 return "atomic counter"; 132 default: 133 UNREACHABLE(); 134 return ""; 135 } 136 } 137 138 std::string GetUniformResourceLimitName(ShaderType shaderType, UniformType uniformType) 139 { 140 // Special case: MAX_TEXTURE_IMAGE_UNITS (no "MAX_FRAGMENT_TEXTURE_IMAGE_UNITS") 141 if (shaderType == ShaderType::Fragment && uniformType == UniformType::Sampler) 142 { 143 return "MAX_TEXTURE_IMAGE_UNITS"; 144 } 145 146 std::ostringstream ostream; 147 ostream << "MAX_" << GetShaderTypeString(shaderType) << "_"; 148 149 switch (uniformType) 150 { 151 case UniformType::Variable: 152 // For vertex and fragment shaders, ES 2.0 only defines MAX_VERTEX_UNIFORM_VECTORS and 153 // MAX_FRAGMENT_UNIFORM_VECTORS ([OpenGL ES 2.0] Table 6.20). 154 if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment) 155 { 156 ostream << "UNIFORM_VECTORS"; 157 break; 158 } 159 // For compute and geometry shaders, there are no definitions on 160 // "MAX_COMPUTE_UNIFORM_VECTORS" or "MAX_GEOMETRY_UNIFORM_VECTORS_EXT" 161 // ([OpenGL ES 3.1] Table 20.45, [EXT_geometry_shader] Table 20.43gs). 162 else 163 { 164 ostream << "UNIFORM_COMPONENTS"; 165 } 166 break; 167 case UniformType::Sampler: 168 ostream << "TEXTURE_IMAGE_UNITS"; 169 break; 170 case UniformType::Image: 171 ostream << "IMAGE_UNIFORMS"; 172 break; 173 case UniformType::AtomicCounter: 174 ostream << "ATOMIC_COUNTERS"; 175 break; 176 default: 177 UNREACHABLE(); 178 return ""; 179 } 180 181 if (shaderType == ShaderType::Geometry) 182 { 183 ostream << "_EXT"; 184 } 185 186 return ostream.str(); 187 } 188 189 void LogUniformsExceedLimit(ShaderType shaderType, 190 UniformType uniformType, 191 GLuint limit, 192 InfoLog &infoLog) 193 { 194 infoLog << GetShaderTypeString(shaderType) << " shader " 195 << GetUniformResourceNameString(uniformType) << "s count exceeds " 196 << GetUniformResourceLimitName(shaderType, uniformType) << "(" << limit << ")"; 197 } 198 199 // The purpose of this visitor is to capture the uniforms in a uniform block. Each new uniform is 200 // added to "uniformsOut". 201 class UniformBlockEncodingVisitor : public sh::VariableNameVisitor 202 { 203 public: 204 UniformBlockEncodingVisitor(const GetBlockMemberInfoFunc &getMemberInfo, 205 const std::string &namePrefix, 206 const std::string &mappedNamePrefix, 207 std::vector<LinkedUniform> *uniformsOut, 208 ShaderType shaderType, 209 int blockIndex) 210 : sh::VariableNameVisitor(namePrefix, mappedNamePrefix), 211 mGetMemberInfo(getMemberInfo), 212 mUniformsOut(uniformsOut), 213 mShaderType(shaderType), 214 mBlockIndex(blockIndex) 215 {} 216 217 void visitNamedVariable(const sh::ShaderVariable &variable, 218 bool isRowMajor, 219 const std::string &name, 220 const std::string &mappedName, 221 const std::vector<unsigned int> &arraySizes) override 222 { 223 // If getBlockMemberInfo returns false, the variable is optimized out. 224 sh::BlockMemberInfo variableInfo; 225 if (!mGetMemberInfo(name, mappedName, &variableInfo)) 226 return; 227 228 std::string nameWithArrayIndex = name; 229 std::string mappedNameWithArrayIndex = mappedName; 230 231 if (variable.isArray()) 232 { 233 nameWithArrayIndex += "[0]"; 234 mappedNameWithArrayIndex += "[0]"; 235 } 236 237 if (mBlockIndex == -1) 238 { 239 SetActive(mUniformsOut, nameWithArrayIndex, mShaderType, variable.active); 240 return; 241 } 242 243 LinkedUniform newUniform(variable.type, variable.precision, nameWithArrayIndex, 244 variable.arraySizes, -1, -1, -1, mBlockIndex, variableInfo); 245 newUniform.mappedName = mappedNameWithArrayIndex; 246 newUniform.setActive(mShaderType, variable.active); 247 248 // Since block uniforms have no location, we don't need to store them in the uniform 249 // locations list. 250 mUniformsOut->push_back(newUniform); 251 } 252 253 private: 254 const GetBlockMemberInfoFunc &mGetMemberInfo; 255 std::vector<LinkedUniform> *mUniformsOut; 256 const ShaderType mShaderType; 257 const int mBlockIndex; 258 }; 259 260 // The purpose of this visitor is to capture the buffer variables in a shader storage block. Each 261 // new buffer variable is stored in "bufferVariablesOut". 262 class ShaderStorageBlockVisitor : public sh::BlockEncoderVisitor 263 { 264 public: 265 ShaderStorageBlockVisitor(const GetBlockMemberInfoFunc &getMemberInfo, 266 const std::string &namePrefix, 267 const std::string &mappedNamePrefix, 268 std::vector<BufferVariable> *bufferVariablesOut, 269 ShaderType shaderType, 270 int blockIndex) 271 : sh::BlockEncoderVisitor(namePrefix, mappedNamePrefix, &mStubEncoder), 272 mGetMemberInfo(getMemberInfo), 273 mBufferVariablesOut(bufferVariablesOut), 274 mShaderType(shaderType), 275 mBlockIndex(blockIndex) 276 {} 277 278 void visitNamedVariable(const sh::ShaderVariable &variable, 279 bool isRowMajor, 280 const std::string &name, 281 const std::string &mappedName, 282 const std::vector<unsigned int> &arraySizes) override 283 { 284 if (mSkipEnabled) 285 return; 286 287 // If getBlockMemberInfo returns false, the variable is optimized out. 288 sh::BlockMemberInfo variableInfo; 289 if (!mGetMemberInfo(name, mappedName, &variableInfo)) 290 return; 291 292 std::string nameWithArrayIndex = name; 293 std::string mappedNameWithArrayIndex = mappedName; 294 295 if (variable.isArray()) 296 { 297 nameWithArrayIndex += "[0]"; 298 mappedNameWithArrayIndex += "[0]"; 299 } 300 301 if (mBlockIndex == -1) 302 { 303 SetActive(mBufferVariablesOut, nameWithArrayIndex, mShaderType, variable.active); 304 return; 305 } 306 307 BufferVariable newBufferVariable(variable.type, variable.precision, nameWithArrayIndex, 308 variable.arraySizes, mBlockIndex, variableInfo); 309 newBufferVariable.mappedName = mappedNameWithArrayIndex; 310 newBufferVariable.setActive(mShaderType, variable.active); 311 312 newBufferVariable.topLevelArraySize = mTopLevelArraySize; 313 314 mBufferVariablesOut->push_back(newBufferVariable); 315 } 316 317 private: 318 const GetBlockMemberInfoFunc &mGetMemberInfo; 319 std::vector<BufferVariable> *mBufferVariablesOut; 320 const ShaderType mShaderType; 321 const int mBlockIndex; 322 sh::StubBlockEncoder mStubEncoder; 323 }; 324 325 struct ShaderUniformCount 326 { 327 unsigned int vectorCount = 0; 328 unsigned int samplerCount = 0; 329 unsigned int imageCount = 0; 330 unsigned int atomicCounterCount = 0; 331 unsigned int fragmentInOutCount = 0; 332 }; 333 334 ShaderUniformCount &operator+=(ShaderUniformCount &lhs, const ShaderUniformCount &rhs) 335 { 336 lhs.vectorCount += rhs.vectorCount; 337 lhs.samplerCount += rhs.samplerCount; 338 lhs.imageCount += rhs.imageCount; 339 lhs.atomicCounterCount += rhs.atomicCounterCount; 340 lhs.fragmentInOutCount += rhs.fragmentInOutCount; 341 return lhs; 342 } 343 344 // The purpose of this visitor is to flatten struct and array uniforms into a list of singleton 345 // uniforms. They are stored in separate lists by uniform type so they can be sorted in order. 346 // Counts for each uniform category are stored and can be queried with "getCounts". 347 class FlattenUniformVisitor : public sh::VariableNameVisitor 348 { 349 public: 350 FlattenUniformVisitor(ShaderType shaderType, 351 const sh::ShaderVariable &uniform, 352 std::vector<LinkedUniform> *uniforms, 353 std::vector<LinkedUniform> *samplerUniforms, 354 std::vector<LinkedUniform> *imageUniforms, 355 std::vector<LinkedUniform> *atomicCounterUniforms, 356 std::vector<LinkedUniform> *inputAttachmentUniforms, 357 std::vector<UnusedUniform> *unusedUniforms) 358 : sh::VariableNameVisitor("", ""), 359 mShaderType(shaderType), 360 mMarkActive(uniform.active), 361 mMarkStaticUse(uniform.staticUse), 362 mBinding(uniform.binding), 363 mOffset(uniform.offset), 364 mLocation(uniform.location), 365 mUniforms(uniforms), 366 mSamplerUniforms(samplerUniforms), 367 mImageUniforms(imageUniforms), 368 mAtomicCounterUniforms(atomicCounterUniforms), 369 mInputAttachmentUniforms(inputAttachmentUniforms), 370 mUnusedUniforms(unusedUniforms) 371 {} 372 373 void visitNamedOpaqueObject(const sh::ShaderVariable &variable, 374 const std::string &name, 375 const std::string &mappedName, 376 const std::vector<unsigned int> &arraySizes) override 377 { 378 visitNamedVariable(variable, false, name, mappedName, arraySizes); 379 } 380 381 void visitNamedVariable(const sh::ShaderVariable &variable, 382 bool isRowMajor, 383 const std::string &name, 384 const std::string &mappedName, 385 const std::vector<unsigned int> &arraySizes) override 386 { 387 bool isSampler = IsSamplerType(variable.type); 388 bool isImage = IsImageType(variable.type); 389 bool isAtomicCounter = IsAtomicCounterType(variable.type); 390 bool isFragmentInOut = variable.isFragmentInOut; 391 std::vector<LinkedUniform> *uniformList = mUniforms; 392 if (isSampler) 393 { 394 uniformList = mSamplerUniforms; 395 } 396 else if (isImage) 397 { 398 uniformList = mImageUniforms; 399 } 400 else if (isAtomicCounter) 401 { 402 uniformList = mAtomicCounterUniforms; 403 } 404 else if (isFragmentInOut) 405 { 406 uniformList = mInputAttachmentUniforms; 407 } 408 409 std::string fullNameWithArrayIndex(name); 410 std::string fullMappedNameWithArrayIndex(mappedName); 411 412 if (variable.isArray()) 413 { 414 // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active 415 // Resources and including [0] at the end of array variable names. 416 fullNameWithArrayIndex += "[0]"; 417 fullMappedNameWithArrayIndex += "[0]"; 418 } 419 420 LinkedUniform *existingUniform = FindUniform(*uniformList, fullNameWithArrayIndex); 421 if (existingUniform) 422 { 423 if (getBinding() != -1) 424 { 425 existingUniform->binding = getBinding(); 426 } 427 if (getOffset() != -1) 428 { 429 existingUniform->offset = getOffset(); 430 } 431 if (mLocation != -1) 432 { 433 existingUniform->location = mLocation; 434 } 435 if (mMarkActive) 436 { 437 existingUniform->active = true; 438 existingUniform->setActive(mShaderType, true); 439 } 440 if (mMarkStaticUse) 441 { 442 existingUniform->staticUse = true; 443 } 444 } 445 else 446 { 447 LinkedUniform linkedUniform(variable.type, variable.precision, fullNameWithArrayIndex, 448 variable.arraySizes, getBinding(), getOffset(), mLocation, 449 -1, sh::kDefaultBlockMemberInfo); 450 linkedUniform.mappedName = fullMappedNameWithArrayIndex; 451 linkedUniform.active = mMarkActive; 452 linkedUniform.staticUse = mMarkStaticUse; 453 linkedUniform.outerArraySizes = arraySizes; 454 linkedUniform.texelFetchStaticUse = variable.texelFetchStaticUse; 455 linkedUniform.imageUnitFormat = variable.imageUnitFormat; 456 linkedUniform.isFragmentInOut = variable.isFragmentInOut; 457 if (variable.hasParentArrayIndex()) 458 { 459 linkedUniform.setParentArrayIndex(variable.parentArrayIndex()); 460 } 461 462 std::vector<unsigned int> arrayDims = arraySizes; 463 ASSERT(variable.arraySizes.size() == 1 || variable.arraySizes.size() == 0); 464 arrayDims.push_back(variable.arraySizes.empty() ? 1 : variable.arraySizes[0]); 465 466 size_t numDimensions = arraySizes.size(); 467 uint32_t arrayStride = 1; 468 for (size_t dimension = numDimensions; dimension > 0;) 469 { 470 --dimension; 471 arrayStride *= arrayDims[dimension + 1]; 472 linkedUniform.outerArrayOffset += arrayStride * mArrayElementStack[dimension]; 473 } 474 475 if (mMarkActive) 476 { 477 linkedUniform.setActive(mShaderType, true); 478 } 479 else 480 { 481 mUnusedUniforms->emplace_back( 482 linkedUniform.name, linkedUniform.isSampler(), linkedUniform.isImage(), 483 linkedUniform.isAtomicCounter(), linkedUniform.isFragmentInOut); 484 } 485 486 uniformList->push_back(linkedUniform); 487 } 488 489 unsigned int elementCount = variable.getBasicTypeElementCount(); 490 491 // Samplers and images aren't "real" uniforms, so they don't count towards register usage. 492 // Likewise, don't count "real" uniforms towards opaque count. 493 494 if (!IsOpaqueType(variable.type) && !isFragmentInOut) 495 { 496 mUniformCount.vectorCount += VariableRegisterCount(variable.type) * elementCount; 497 } 498 499 mUniformCount.samplerCount += (isSampler ? elementCount : 0); 500 mUniformCount.imageCount += (isImage ? elementCount : 0); 501 mUniformCount.atomicCounterCount += (isAtomicCounter ? elementCount : 0); 502 mUniformCount.fragmentInOutCount += (isFragmentInOut ? elementCount : 0); 503 504 if (mLocation != -1) 505 { 506 mLocation += elementCount; 507 } 508 } 509 510 void enterStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override 511 { 512 mStructStackSize++; 513 sh::VariableNameVisitor::enterStructAccess(structVar, isRowMajor); 514 } 515 516 void exitStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override 517 { 518 mStructStackSize--; 519 sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor); 520 } 521 522 void enterArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override 523 { 524 mArrayElementStack.push_back(arrayElement); 525 sh::VariableNameVisitor::enterArrayElement(arrayVar, arrayElement); 526 } 527 528 void exitArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override 529 { 530 mArrayElementStack.pop_back(); 531 sh::VariableNameVisitor::exitArrayElement(arrayVar, arrayElement); 532 } 533 534 ShaderUniformCount getCounts() const { return mUniformCount; } 535 536 private: 537 int getBinding() const { return mStructStackSize == 0 ? mBinding : -1; } 538 int getOffset() const { return mStructStackSize == 0 ? mOffset : -1; } 539 540 ShaderType mShaderType; 541 542 // Active and StaticUse are given separately because they are tracked at struct granularity. 543 bool mMarkActive; 544 bool mMarkStaticUse; 545 int mBinding; 546 int mOffset; 547 int mLocation; 548 std::vector<LinkedUniform> *mUniforms; 549 std::vector<LinkedUniform> *mSamplerUniforms; 550 std::vector<LinkedUniform> *mImageUniforms; 551 std::vector<LinkedUniform> *mAtomicCounterUniforms; 552 std::vector<LinkedUniform> *mInputAttachmentUniforms; 553 std::vector<UnusedUniform> *mUnusedUniforms; 554 std::vector<unsigned int> mArrayElementStack; 555 ShaderUniformCount mUniformCount; 556 unsigned int mStructStackSize = 0; 557 }; 558 559 class InterfaceBlockInfo final : angle::NonCopyable 560 { 561 public: 562 InterfaceBlockInfo(CustomBlockLayoutEncoderFactory *customEncoderFactory) 563 : mCustomEncoderFactory(customEncoderFactory) 564 {} 565 566 void getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks); 567 568 bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut); 569 bool getBlockMemberInfo(const std::string &name, 570 const std::string &mappedName, 571 sh::BlockMemberInfo *infoOut); 572 573 private: 574 size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock); 575 576 std::map<std::string, size_t> mBlockSizes; 577 sh::BlockLayoutMap mBlockLayout; 578 // Based on the interface block layout, the std140 or std430 encoders are used. On some 579 // platforms (currently only D3D), there could be another non-standard encoder used. 580 CustomBlockLayoutEncoderFactory *mCustomEncoderFactory; 581 }; 582 583 void InterfaceBlockInfo::getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks) 584 { 585 for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks) 586 { 587 if (!IsActiveInterfaceBlock(interfaceBlock)) 588 continue; 589 590 if (mBlockSizes.count(interfaceBlock.name) > 0) 591 continue; 592 593 size_t dataSize = getBlockInfo(interfaceBlock); 594 mBlockSizes[interfaceBlock.name] = dataSize; 595 } 596 } 597 598 size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock) 599 { 600 ASSERT(IsActiveInterfaceBlock(interfaceBlock)); 601 602 // define member uniforms 603 sh::Std140BlockEncoder std140Encoder; 604 sh::Std430BlockEncoder std430Encoder; 605 sh::BlockLayoutEncoder *customEncoder = nullptr; 606 sh::BlockLayoutEncoder *encoder = nullptr; 607 608 if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140) 609 { 610 encoder = &std140Encoder; 611 } 612 else if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD430) 613 { 614 encoder = &std430Encoder; 615 } 616 else if (mCustomEncoderFactory) 617 { 618 encoder = customEncoder = mCustomEncoderFactory->makeEncoder(); 619 } 620 else 621 { 622 UNREACHABLE(); 623 return 0; 624 } 625 626 sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder, 627 &mBlockLayout); 628 629 size_t offset = encoder->getCurrentOffset(); 630 631 SafeDelete(customEncoder); 632 633 return offset; 634 } 635 636 bool InterfaceBlockInfo::getBlockSize(const std::string &name, 637 const std::string &mappedName, 638 size_t *sizeOut) 639 { 640 size_t nameLengthWithoutArrayIndex; 641 ParseArrayIndex(name, &nameLengthWithoutArrayIndex); 642 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex); 643 auto sizeIter = mBlockSizes.find(baseName); 644 if (sizeIter == mBlockSizes.end()) 645 { 646 *sizeOut = 0; 647 return false; 648 } 649 650 *sizeOut = sizeIter->second; 651 return true; 652 } 653 654 bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name, 655 const std::string &mappedName, 656 sh::BlockMemberInfo *infoOut) 657 { 658 auto infoIter = mBlockLayout.find(name); 659 if (infoIter == mBlockLayout.end()) 660 { 661 *infoOut = sh::kDefaultBlockMemberInfo; 662 return false; 663 } 664 665 *infoOut = infoIter->second; 666 return true; 667 } 668 669 void GetFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings, 670 std::vector<const sh::ShaderVariable *> *filteredVaryingsOut) 671 { 672 for (const sh::ShaderVariable &varying : varyings) 673 { 674 // Built-in varyings obey special rules 675 if (varying.isBuiltIn()) 676 { 677 continue; 678 } 679 680 filteredVaryingsOut->push_back(&varying); 681 } 682 } 683 684 LinkMismatchError LinkValidateVaryings(const sh::ShaderVariable &outputVarying, 685 const sh::ShaderVariable &inputVarying, 686 int shaderVersion, 687 ShaderType frontShaderType, 688 ShaderType backShaderType, 689 bool isSeparable, 690 std::string *mismatchedStructFieldName) 691 { 692 // [ES 3.2 spec] 7.4.1 Shader Interface Matching: 693 // Tessellation control shader per-vertex output variables and blocks and tessellation control, 694 // tessellation evaluation, and geometry shader per-vertex input variables and blocks are 695 // required to be declared as arrays, with each element representing input or output values for 696 // a single vertex of a multi-vertex primitive. For the purposes of interface matching, such 697 // variables and blocks are treated as though they were not declared as arrays. 698 bool treatOutputAsNonArray = 699 (frontShaderType == ShaderType::TessControl && !outputVarying.isPatch); 700 bool treatInputAsNonArray = 701 ((backShaderType == ShaderType::TessControl || 702 backShaderType == ShaderType::TessEvaluation || backShaderType == ShaderType::Geometry) && 703 !inputVarying.isPatch); 704 705 // Skip the validation on the array sizes between a vertex output varying and a geometry input 706 // varying as it has been done before. 707 bool validatePrecision = isSeparable && (shaderVersion > 100); 708 LinkMismatchError linkError = LinkValidateProgramVariables( 709 outputVarying, inputVarying, validatePrecision, treatOutputAsNonArray, treatInputAsNonArray, 710 mismatchedStructFieldName); 711 if (linkError != LinkMismatchError::NO_MISMATCH) 712 { 713 return linkError; 714 } 715 716 // Explicit locations must match if the names match. 717 if (outputVarying.isSameNameAtLinkTime(inputVarying) && 718 outputVarying.location != inputVarying.location) 719 { 720 return LinkMismatchError::LOCATION_MISMATCH; 721 } 722 723 if (!sh::InterpolationTypesMatch(outputVarying.interpolation, inputVarying.interpolation)) 724 { 725 return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH; 726 } 727 728 if (shaderVersion == 100 && outputVarying.isInvariant != inputVarying.isInvariant) 729 { 730 return LinkMismatchError::INVARIANCE_MISMATCH; 731 } 732 733 return LinkMismatchError::NO_MISMATCH; 734 } 735 736 bool DoShaderVariablesMatch(int frontShaderVersion, 737 ShaderType frontShaderType, 738 ShaderType backShaderType, 739 const sh::ShaderVariable &input, 740 const sh::ShaderVariable &output, 741 bool isSeparable, 742 gl::InfoLog &infoLog) 743 { 744 bool namesMatch = input.isSameNameAtLinkTime(output); 745 bool locationsMatch = input.location != -1 && input.location == output.location; 746 747 // An output block is considered to match an input block in the subsequent 748 // shader if the two blocks have the same block name, and the members of the 749 // block match exactly in name, type, qualification, and declaration order. 750 // 751 // - For the purposes of shader interface matching, the gl_PointSize 752 // member of the intrinsically declared gl_PerVertex shader interface 753 // block is ignored. 754 // - Output blocks that do not match in name, but have a location and match 755 // in every other way listed above may be considered to match by some 756 // implementations, but not all - so this behaviour should not be relied 757 // upon. 758 759 // An output variable is considered to match an input variable in the subsequent 760 // shader if: 761 // 762 // - the two variables match in name, type, and qualification; or 763 // - the two variables are declared with the same location qualifier and 764 // match in type and qualification. 765 766 if (namesMatch || locationsMatch) 767 { 768 std::string mismatchedStructFieldName; 769 LinkMismatchError linkError = 770 LinkValidateVaryings(output, input, frontShaderVersion, frontShaderType, backShaderType, 771 isSeparable, &mismatchedStructFieldName); 772 if (linkError != LinkMismatchError::NO_MISMATCH) 773 { 774 LogLinkMismatch(infoLog, input.name, "varying", linkError, mismatchedStructFieldName, 775 frontShaderType, backShaderType); 776 return false; 777 } 778 779 return true; 780 } 781 782 return false; 783 } 784 785 const char *GetInterfaceBlockTypeString(sh::BlockType blockType) 786 { 787 switch (blockType) 788 { 789 case sh::BlockType::BLOCK_UNIFORM: 790 return "uniform block"; 791 case sh::BlockType::BLOCK_BUFFER: 792 return "shader storage block"; 793 default: 794 UNREACHABLE(); 795 return ""; 796 } 797 } 798 799 std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType) 800 { 801 std::ostringstream stream; 802 stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_"; 803 804 switch (blockType) 805 { 806 case sh::BlockType::BLOCK_UNIFORM: 807 stream << "UNIFORM_BUFFERS"; 808 break; 809 case sh::BlockType::BLOCK_BUFFER: 810 stream << "SHADER_STORAGE_BLOCKS"; 811 break; 812 default: 813 UNREACHABLE(); 814 return ""; 815 } 816 817 if (shaderType == ShaderType::Geometry) 818 { 819 stream << "_EXT"; 820 } 821 822 return stream.str(); 823 } 824 825 void LogInterfaceBlocksExceedLimit(InfoLog &infoLog, 826 ShaderType shaderType, 827 sh::BlockType blockType, 828 GLuint limit) 829 { 830 infoLog << GetShaderTypeString(shaderType) << " shader " 831 << GetInterfaceBlockTypeString(blockType) << " count exceeds " 832 << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")"; 833 } 834 835 bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks, 836 const std::vector<sh::InterfaceBlock> &interfaceBlocks, 837 ShaderType shaderType, 838 sh::BlockType blockType, 839 GLuint *combinedInterfaceBlocksCount, 840 InfoLog &infoLog) 841 { 842 GLuint blockCount = 0; 843 for (const sh::InterfaceBlock &block : interfaceBlocks) 844 { 845 if (IsActiveInterfaceBlock(block)) 846 { 847 blockCount += std::max(block.arraySize, 1u); 848 if (blockCount > maxInterfaceBlocks) 849 { 850 LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks); 851 return false; 852 } 853 } 854 } 855 856 // [OpenGL ES 3.1] Chapter 7.6.2 Page 105: 857 // If a uniform block is used by multiple shader stages, each such use counts separately 858 // against this combined limit. 859 // [OpenGL ES 3.1] Chapter 7.8 Page 111: 860 // If a shader storage block in a program is referenced by multiple shaders, each such 861 // reference counts separately against this combined limit. 862 if (combinedInterfaceBlocksCount) 863 { 864 *combinedInterfaceBlocksCount += blockCount; 865 } 866 867 return true; 868 } 869 } // anonymous namespace 870 871 UniformLinker::UniformLinker(const ShaderBitSet &activeShaderStages, 872 const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms) 873 : mActiveShaderStages(activeShaderStages), mShaderUniforms(shaderUniforms) 874 {} 875 876 UniformLinker::~UniformLinker() = default; 877 878 void UniformLinker::getResults(std::vector<LinkedUniform> *uniforms, 879 std::vector<UnusedUniform> *unusedUniformsOutOrNull, 880 std::vector<VariableLocation> *uniformLocationsOutOrNull) 881 { 882 uniforms->swap(mUniforms); 883 884 if (unusedUniformsOutOrNull) 885 { 886 unusedUniformsOutOrNull->swap(mUnusedUniforms); 887 } 888 889 if (uniformLocationsOutOrNull) 890 { 891 uniformLocationsOutOrNull->swap(mUniformLocations); 892 } 893 } 894 895 bool UniformLinker::link(const Caps &caps, 896 InfoLog &infoLog, 897 const ProgramAliasedBindings &uniformLocationBindings) 898 { 899 if (mActiveShaderStages[ShaderType::Vertex] && mActiveShaderStages[ShaderType::Fragment]) 900 { 901 if (!validateGraphicsUniforms(infoLog)) 902 { 903 return false; 904 } 905 } 906 907 // Flatten the uniforms list (nested fields) into a simple list (no nesting). 908 // Also check the maximum uniform vector and sampler counts. 909 if (!flattenUniformsAndCheckCaps(caps, infoLog)) 910 { 911 return false; 912 } 913 914 if (!checkMaxCombinedAtomicCounters(caps, infoLog)) 915 { 916 return false; 917 } 918 919 if (!indexUniforms(infoLog, uniformLocationBindings)) 920 { 921 return false; 922 } 923 924 return true; 925 } 926 927 bool UniformLinker::validateGraphicsUniforms(InfoLog &infoLog) const 928 { 929 // Check that uniforms defined in the graphics shaders are identical 930 std::map<std::string, ShaderUniform> linkedUniforms; 931 932 for (const ShaderType shaderType : mActiveShaderStages) 933 { 934 if (shaderType == ShaderType::Vertex) 935 { 936 for (const sh::ShaderVariable &vertexUniform : mShaderUniforms[ShaderType::Vertex]) 937 { 938 linkedUniforms[vertexUniform.name] = 939 std::make_pair(ShaderType::Vertex, &vertexUniform); 940 } 941 } 942 else 943 { 944 bool isLastShader = (shaderType == ShaderType::Fragment); 945 if (!validateGraphicsUniformsPerShader(shaderType, !isLastShader, &linkedUniforms, 946 infoLog)) 947 { 948 return false; 949 } 950 } 951 } 952 953 return true; 954 } 955 956 bool UniformLinker::validateGraphicsUniformsPerShader( 957 ShaderType shaderToLink, 958 bool extendLinkedUniforms, 959 std::map<std::string, ShaderUniform> *linkedUniforms, 960 InfoLog &infoLog) const 961 { 962 ASSERT(mActiveShaderStages[shaderToLink] && linkedUniforms); 963 964 for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderToLink]) 965 { 966 const auto &entry = linkedUniforms->find(uniform.name); 967 if (entry != linkedUniforms->end()) 968 { 969 const sh::ShaderVariable &linkedUniform = *(entry->second.second); 970 std::string mismatchedStructFieldName; 971 LinkMismatchError linkError = 972 LinkValidateUniforms(uniform, linkedUniform, &mismatchedStructFieldName); 973 if (linkError != LinkMismatchError::NO_MISMATCH) 974 { 975 LogLinkMismatch(infoLog, uniform.name, "uniform", linkError, 976 mismatchedStructFieldName, entry->second.first, shaderToLink); 977 return false; 978 } 979 } 980 else if (extendLinkedUniforms) 981 { 982 (*linkedUniforms)[uniform.name] = std::make_pair(shaderToLink, &uniform); 983 } 984 } 985 986 return true; 987 } 988 989 bool UniformLinker::indexUniforms(InfoLog &infoLog, 990 const ProgramAliasedBindings &uniformLocationBindings) 991 { 992 // Locations which have been allocated for an unused uniform. 993 std::set<GLuint> ignoredLocations; 994 995 int maxUniformLocation = -1; 996 997 // Gather uniform locations that have been set either using the bindUniformLocationCHROMIUM API 998 // or by using a location layout qualifier and check conflicts between them. 999 if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings, 1000 &ignoredLocations, &maxUniformLocation)) 1001 { 1002 return false; 1003 } 1004 1005 // Conflicts have been checked, now we can prune non-statically used uniforms. Code further down 1006 // the line relies on only having statically used uniforms in mUniforms. 1007 pruneUnusedUniforms(); 1008 1009 // Gather uniforms that have their location pre-set and uniforms that don't yet have a location. 1010 std::vector<VariableLocation> unlocatedUniforms; 1011 std::map<GLuint, VariableLocation> preLocatedUniforms; 1012 1013 for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) 1014 { 1015 const LinkedUniform &uniform = mUniforms[uniformIndex]; 1016 1017 if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) || 1018 IsAtomicCounterType(uniform.type) || uniform.isFragmentInOut) 1019 { 1020 continue; 1021 } 1022 1023 int preSetLocation = uniformLocationBindings.getBinding(uniform); 1024 int shaderLocation = uniform.location; 1025 1026 if (shaderLocation != -1) 1027 { 1028 preSetLocation = shaderLocation; 1029 } 1030 1031 unsigned int elementCount = uniform.getBasicTypeElementCount(); 1032 for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++) 1033 { 1034 VariableLocation location(arrayIndex, static_cast<unsigned int>(uniformIndex)); 1035 1036 if ((arrayIndex == 0 && preSetLocation != -1) || shaderLocation != -1) 1037 { 1038 int elementLocation = preSetLocation + arrayIndex; 1039 preLocatedUniforms[elementLocation] = location; 1040 } 1041 else 1042 { 1043 unlocatedUniforms.push_back(location); 1044 } 1045 } 1046 } 1047 1048 // Make enough space for all uniforms, with pre-set locations or not. 1049 mUniformLocations.resize( 1050 std::max(unlocatedUniforms.size() + preLocatedUniforms.size() + ignoredLocations.size(), 1051 static_cast<size_t>(maxUniformLocation + 1))); 1052 1053 // Assign uniforms with pre-set locations 1054 for (const auto &uniform : preLocatedUniforms) 1055 { 1056 mUniformLocations[uniform.first] = uniform.second; 1057 } 1058 1059 // Assign ignored uniforms 1060 for (const auto &ignoredLocation : ignoredLocations) 1061 { 1062 mUniformLocations[ignoredLocation].markIgnored(); 1063 } 1064 1065 // Automatically assign locations for the rest of the uniforms 1066 size_t nextUniformLocation = 0; 1067 for (const auto &unlocatedUniform : unlocatedUniforms) 1068 { 1069 while (mUniformLocations[nextUniformLocation].used() || 1070 mUniformLocations[nextUniformLocation].ignored) 1071 { 1072 nextUniformLocation++; 1073 } 1074 1075 ASSERT(nextUniformLocation < mUniformLocations.size()); 1076 mUniformLocations[nextUniformLocation] = unlocatedUniform; 1077 nextUniformLocation++; 1078 } 1079 1080 return true; 1081 } 1082 1083 bool UniformLinker::gatherUniformLocationsAndCheckConflicts( 1084 InfoLog &infoLog, 1085 const ProgramAliasedBindings &uniformLocationBindings, 1086 std::set<GLuint> *ignoredLocations, 1087 int *maxUniformLocation) 1088 { 1089 // All the locations where another uniform can't be located. 1090 std::set<GLuint> reservedLocations; 1091 1092 for (const LinkedUniform &uniform : mUniforms) 1093 { 1094 if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) || uniform.isFragmentInOut) 1095 { 1096 // The uniform of the fragment inout is not a normal uniform type. So, in the case of 1097 // the fragment inout, this routine should be skipped. 1098 continue; 1099 } 1100 1101 int apiBoundLocation = uniformLocationBindings.getBinding(uniform); 1102 int shaderLocation = uniform.location; 1103 1104 if (shaderLocation != -1) 1105 { 1106 unsigned int elementCount = uniform.getBasicTypeElementCount(); 1107 1108 for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++) 1109 { 1110 // GLSL ES 3.10 section 4.4.3 1111 int elementLocation = shaderLocation + arrayIndex; 1112 *maxUniformLocation = std::max(*maxUniformLocation, elementLocation); 1113 if (reservedLocations.find(elementLocation) != reservedLocations.end()) 1114 { 1115 infoLog << "Multiple uniforms bound to location " << elementLocation << "."; 1116 return false; 1117 } 1118 reservedLocations.insert(elementLocation); 1119 if (!uniform.active) 1120 { 1121 ignoredLocations->insert(elementLocation); 1122 } 1123 } 1124 } 1125 else if (apiBoundLocation != -1 && uniform.staticUse) 1126 { 1127 // Only the first location is reserved even if the uniform is an array. 1128 *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation); 1129 if (reservedLocations.find(apiBoundLocation) != reservedLocations.end()) 1130 { 1131 infoLog << "Multiple uniforms bound to location " << apiBoundLocation << "."; 1132 return false; 1133 } 1134 reservedLocations.insert(apiBoundLocation); 1135 if (!uniform.active) 1136 { 1137 ignoredLocations->insert(apiBoundLocation); 1138 } 1139 } 1140 } 1141 1142 // Record the uniform locations that were bound using the API for uniforms that were not found 1143 // from the shader. Other uniforms should not be assigned to those locations. 1144 for (const auto &locationBinding : uniformLocationBindings) 1145 { 1146 GLuint location = locationBinding.second.location; 1147 if (reservedLocations.find(location) == reservedLocations.end()) 1148 { 1149 ignoredLocations->insert(location); 1150 *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location)); 1151 } 1152 } 1153 1154 return true; 1155 } 1156 1157 void UniformLinker::pruneUnusedUniforms() 1158 { 1159 auto uniformIter = mUniforms.begin(); 1160 while (uniformIter != mUniforms.end()) 1161 { 1162 if (uniformIter->active) 1163 { 1164 ++uniformIter; 1165 } 1166 else 1167 { 1168 mUnusedUniforms.emplace_back(uniformIter->name, uniformIter->isSampler(), 1169 uniformIter->isImage(), uniformIter->isAtomicCounter(), 1170 uniformIter->isFragmentInOut); 1171 uniformIter = mUniforms.erase(uniformIter); 1172 } 1173 } 1174 } 1175 1176 bool UniformLinker::flattenUniformsAndCheckCapsForShader( 1177 ShaderType shaderType, 1178 const Caps &caps, 1179 std::vector<LinkedUniform> &samplerUniforms, 1180 std::vector<LinkedUniform> &imageUniforms, 1181 std::vector<LinkedUniform> &atomicCounterUniforms, 1182 std::vector<LinkedUniform> &inputAttachmentUniforms, 1183 std::vector<UnusedUniform> &unusedUniforms, 1184 InfoLog &infoLog) 1185 { 1186 ShaderUniformCount shaderUniformCount; 1187 for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderType]) 1188 { 1189 FlattenUniformVisitor flattener(shaderType, uniform, &mUniforms, &samplerUniforms, 1190 &imageUniforms, &atomicCounterUniforms, 1191 &inputAttachmentUniforms, &unusedUniforms); 1192 sh::TraverseShaderVariable(uniform, false, &flattener); 1193 1194 if (uniform.active) 1195 { 1196 shaderUniformCount += flattener.getCounts(); 1197 } 1198 else 1199 { 1200 unusedUniforms.emplace_back(uniform.name, IsSamplerType(uniform.type), 1201 IsImageType(uniform.type), 1202 IsAtomicCounterType(uniform.type), uniform.isFragmentInOut); 1203 } 1204 } 1205 1206 // This code does not do fine-grained component counting. 1207 GLuint maxUniformVectorsCount = GetMaximumShaderUniformVectors(shaderType, caps); 1208 if (shaderUniformCount.vectorCount > maxUniformVectorsCount) 1209 { 1210 GLuint maxUniforms = 0u; 1211 1212 // See comments in GetUniformResourceLimitName() 1213 if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment) 1214 { 1215 maxUniforms = maxUniformVectorsCount; 1216 } 1217 else 1218 { 1219 maxUniforms = maxUniformVectorsCount * 4; 1220 } 1221 1222 LogUniformsExceedLimit(shaderType, UniformType::Variable, maxUniforms, infoLog); 1223 return false; 1224 } 1225 1226 if (shaderUniformCount.samplerCount > 1227 static_cast<GLuint>(caps.maxShaderTextureImageUnits[shaderType])) 1228 { 1229 LogUniformsExceedLimit(shaderType, UniformType::Sampler, 1230 caps.maxShaderTextureImageUnits[shaderType], infoLog); 1231 return false; 1232 } 1233 1234 if (shaderUniformCount.imageCount > 1235 static_cast<GLuint>(caps.maxShaderImageUniforms[shaderType])) 1236 { 1237 LogUniformsExceedLimit(shaderType, UniformType::Image, 1238 caps.maxShaderImageUniforms[shaderType], infoLog); 1239 return false; 1240 } 1241 1242 if (shaderUniformCount.atomicCounterCount > 1243 static_cast<GLuint>(caps.maxShaderAtomicCounters[shaderType])) 1244 { 1245 LogUniformsExceedLimit(shaderType, UniformType::AtomicCounter, 1246 caps.maxShaderAtomicCounters[shaderType], infoLog); 1247 return false; 1248 } 1249 1250 return true; 1251 } 1252 1253 bool UniformLinker::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog) 1254 { 1255 std::vector<LinkedUniform> samplerUniforms; 1256 std::vector<LinkedUniform> imageUniforms; 1257 std::vector<LinkedUniform> atomicCounterUniforms; 1258 std::vector<LinkedUniform> inputAttachmentUniforms; 1259 std::vector<UnusedUniform> unusedUniforms; 1260 1261 for (const ShaderType shaderType : mActiveShaderStages) 1262 { 1263 if (!flattenUniformsAndCheckCapsForShader(shaderType, caps, samplerUniforms, imageUniforms, 1264 atomicCounterUniforms, inputAttachmentUniforms, 1265 unusedUniforms, infoLog)) 1266 { 1267 return false; 1268 } 1269 } 1270 1271 mUniforms.insert(mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end()); 1272 mUniforms.insert(mUniforms.end(), imageUniforms.begin(), imageUniforms.end()); 1273 mUniforms.insert(mUniforms.end(), atomicCounterUniforms.begin(), atomicCounterUniforms.end()); 1274 mUniforms.insert(mUniforms.end(), inputAttachmentUniforms.begin(), 1275 inputAttachmentUniforms.end()); 1276 mUnusedUniforms.insert(mUnusedUniforms.end(), unusedUniforms.begin(), unusedUniforms.end()); 1277 return true; 1278 } 1279 1280 bool UniformLinker::checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog) 1281 { 1282 unsigned int atomicCounterCount = 0; 1283 for (const auto &uniform : mUniforms) 1284 { 1285 if (IsAtomicCounterType(uniform.type) && uniform.active) 1286 { 1287 atomicCounterCount += uniform.getBasicTypeElementCount(); 1288 if (atomicCounterCount > static_cast<GLuint>(caps.maxCombinedAtomicCounters)) 1289 { 1290 infoLog << "atomic counter count exceeds MAX_COMBINED_ATOMIC_COUNTERS" 1291 << caps.maxCombinedAtomicCounters << ")."; 1292 return false; 1293 } 1294 } 1295 } 1296 return true; 1297 } 1298 1299 // InterfaceBlockLinker implementation. 1300 InterfaceBlockLinker::InterfaceBlockLinker() = default; 1301 1302 InterfaceBlockLinker::~InterfaceBlockLinker() = default; 1303 1304 void InterfaceBlockLinker::init(std::vector<InterfaceBlock> *blocksOut, 1305 std::vector<std::string> *unusedInterfaceBlocksOut) 1306 { 1307 mBlocksOut = blocksOut; 1308 mUnusedInterfaceBlocksOut = unusedInterfaceBlocksOut; 1309 } 1310 1311 void InterfaceBlockLinker::addShaderBlocks(ShaderType shaderType, 1312 const std::vector<sh::InterfaceBlock> *blocks) 1313 { 1314 mShaderBlocks[shaderType] = blocks; 1315 } 1316 1317 void InterfaceBlockLinker::linkBlocks(const GetBlockSizeFunc &getBlockSize, 1318 const GetBlockMemberInfoFunc &getMemberInfo) const 1319 { 1320 ASSERT(mBlocksOut->empty()); 1321 1322 std::set<std::string> visitedList; 1323 1324 for (const ShaderType shaderType : AllShaderTypes()) 1325 { 1326 if (!mShaderBlocks[shaderType]) 1327 { 1328 continue; 1329 } 1330 1331 for (const sh::InterfaceBlock &block : *mShaderBlocks[shaderType]) 1332 { 1333 if (!IsActiveInterfaceBlock(block)) 1334 { 1335 mUnusedInterfaceBlocksOut->push_back(block.name); 1336 continue; 1337 } 1338 1339 if (visitedList.count(block.name) == 0) 1340 { 1341 defineInterfaceBlock(getBlockSize, getMemberInfo, block, shaderType); 1342 visitedList.insert(block.name); 1343 continue; 1344 } 1345 1346 if (!block.active) 1347 { 1348 mUnusedInterfaceBlocksOut->push_back(block.name); 1349 continue; 1350 } 1351 1352 for (InterfaceBlock &priorBlock : *mBlocksOut) 1353 { 1354 if (block.name == priorBlock.name) 1355 { 1356 priorBlock.setActive(shaderType, true); 1357 1358 std::unique_ptr<sh::ShaderVariableVisitor> visitor( 1359 getVisitor(getMemberInfo, block.fieldPrefix(), block.fieldMappedPrefix(), 1360 shaderType, -1)); 1361 1362 sh::TraverseShaderVariables(block.fields, false, visitor.get()); 1363 } 1364 } 1365 } 1366 } 1367 } 1368 1369 void InterfaceBlockLinker::defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize, 1370 const GetBlockMemberInfoFunc &getMemberInfo, 1371 const sh::InterfaceBlock &interfaceBlock, 1372 ShaderType shaderType) const 1373 { 1374 size_t blockSize = 0; 1375 std::vector<unsigned int> blockIndexes; 1376 1377 int blockIndex = static_cast<int>(mBlocksOut->size()); 1378 // Track the first and last block member index to determine the range of active block members in 1379 // the block. 1380 size_t firstBlockMemberIndex = getCurrentBlockMemberIndex(); 1381 1382 std::unique_ptr<sh::ShaderVariableVisitor> visitor( 1383 getVisitor(getMemberInfo, interfaceBlock.fieldPrefix(), interfaceBlock.fieldMappedPrefix(), 1384 shaderType, blockIndex)); 1385 sh::TraverseShaderVariables(interfaceBlock.fields, false, visitor.get()); 1386 1387 size_t lastBlockMemberIndex = getCurrentBlockMemberIndex(); 1388 1389 for (size_t blockMemberIndex = firstBlockMemberIndex; blockMemberIndex < lastBlockMemberIndex; 1390 ++blockMemberIndex) 1391 { 1392 blockIndexes.push_back(static_cast<unsigned int>(blockMemberIndex)); 1393 } 1394 1395 unsigned int firstFieldArraySize = interfaceBlock.fields[0].getArraySizeProduct(); 1396 1397 for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.elementCount(); 1398 ++arrayElement) 1399 { 1400 std::string blockArrayName = interfaceBlock.name; 1401 std::string blockMappedArrayName = interfaceBlock.mappedName; 1402 if (interfaceBlock.isArray()) 1403 { 1404 blockArrayName += ArrayString(arrayElement); 1405 blockMappedArrayName += ArrayString(arrayElement); 1406 } 1407 1408 // Don't define this block at all if it's not active in the implementation. 1409 if (!getBlockSize(blockArrayName, blockMappedArrayName, &blockSize)) 1410 { 1411 continue; 1412 } 1413 1414 // ESSL 3.10 section 4.4.4 page 58: 1415 // Any uniform or shader storage block declared without a binding qualifier is initially 1416 // assigned to block binding point zero. 1417 int blockBinding = 1418 (interfaceBlock.binding == -1 ? 0 : interfaceBlock.binding + arrayElement); 1419 InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName, 1420 interfaceBlock.isArray(), arrayElement, firstFieldArraySize, 1421 blockBinding); 1422 block.memberIndexes = blockIndexes; 1423 block.setActive(shaderType, interfaceBlock.active); 1424 1425 // Since all block elements in an array share the same active interface blocks, they 1426 // will all be active once any block member is used. So, since interfaceBlock.name[0] 1427 // was active, here we will add every block element in the array. 1428 block.dataSize = static_cast<unsigned int>(blockSize); 1429 mBlocksOut->push_back(block); 1430 } 1431 } 1432 1433 // UniformBlockLinker implementation. 1434 UniformBlockLinker::UniformBlockLinker() = default; 1435 1436 UniformBlockLinker::~UniformBlockLinker() {} 1437 1438 void UniformBlockLinker::init(std::vector<InterfaceBlock> *blocksOut, 1439 std::vector<LinkedUniform> *uniformsOut, 1440 std::vector<std::string> *unusedInterfaceBlocksOut) 1441 { 1442 InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut); 1443 mUniformsOut = uniformsOut; 1444 } 1445 1446 size_t UniformBlockLinker::getCurrentBlockMemberIndex() const 1447 { 1448 return mUniformsOut->size(); 1449 } 1450 1451 sh::ShaderVariableVisitor *UniformBlockLinker::getVisitor( 1452 const GetBlockMemberInfoFunc &getMemberInfo, 1453 const std::string &namePrefix, 1454 const std::string &mappedNamePrefix, 1455 ShaderType shaderType, 1456 int blockIndex) const 1457 { 1458 return new UniformBlockEncodingVisitor(getMemberInfo, namePrefix, mappedNamePrefix, 1459 mUniformsOut, shaderType, blockIndex); 1460 } 1461 1462 // ShaderStorageBlockLinker implementation. 1463 ShaderStorageBlockLinker::ShaderStorageBlockLinker() = default; 1464 1465 ShaderStorageBlockLinker::~ShaderStorageBlockLinker() = default; 1466 1467 void ShaderStorageBlockLinker::init(std::vector<InterfaceBlock> *blocksOut, 1468 std::vector<BufferVariable> *bufferVariablesOut, 1469 std::vector<std::string> *unusedInterfaceBlocksOut) 1470 { 1471 InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut); 1472 mBufferVariablesOut = bufferVariablesOut; 1473 } 1474 1475 size_t ShaderStorageBlockLinker::getCurrentBlockMemberIndex() const 1476 { 1477 return mBufferVariablesOut->size(); 1478 } 1479 1480 sh::ShaderVariableVisitor *ShaderStorageBlockLinker::getVisitor( 1481 const GetBlockMemberInfoFunc &getMemberInfo, 1482 const std::string &namePrefix, 1483 const std::string &mappedNamePrefix, 1484 ShaderType shaderType, 1485 int blockIndex) const 1486 { 1487 return new ShaderStorageBlockVisitor(getMemberInfo, namePrefix, mappedNamePrefix, 1488 mBufferVariablesOut, shaderType, blockIndex); 1489 } 1490 1491 // AtomicCounterBufferLinker implementation. 1492 AtomicCounterBufferLinker::AtomicCounterBufferLinker() = default; 1493 1494 AtomicCounterBufferLinker::~AtomicCounterBufferLinker() = default; 1495 1496 void AtomicCounterBufferLinker::init(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut) 1497 { 1498 mAtomicCounterBuffersOut = atomicCounterBuffersOut; 1499 } 1500 1501 void AtomicCounterBufferLinker::link(const std::map<int, unsigned int> &sizeMap) const 1502 { 1503 for (auto &atomicCounterBuffer : *mAtomicCounterBuffersOut) 1504 { 1505 auto bufferSize = sizeMap.find(atomicCounterBuffer.binding); 1506 ASSERT(bufferSize != sizeMap.end()); 1507 atomicCounterBuffer.dataSize = bufferSize->second; 1508 } 1509 } 1510 1511 ProgramLinkedResources::ProgramLinkedResources() = default; 1512 1513 ProgramLinkedResources::~ProgramLinkedResources() = default; 1514 1515 LinkingVariables::LinkingVariables(const Context *context, const ProgramState &state) 1516 { 1517 for (ShaderType shaderType : kAllGraphicsShaderTypes) 1518 { 1519 Shader *shader = state.getAttachedShader(shaderType); 1520 if (shader) 1521 { 1522 outputVaryings[shaderType] = shader->getOutputVaryings(context); 1523 inputVaryings[shaderType] = shader->getInputVaryings(context); 1524 uniforms[shaderType] = shader->getUniforms(context); 1525 uniformBlocks[shaderType] = shader->getUniformBlocks(context); 1526 isShaderStageUsedBitset.set(shaderType); 1527 } 1528 } 1529 } 1530 1531 LinkingVariables::LinkingVariables(const ProgramPipelineState &state) 1532 { 1533 for (ShaderType shaderType : state.getExecutable().getLinkedShaderStages()) 1534 { 1535 const Program *program = state.getShaderProgram(shaderType); 1536 ASSERT(program); 1537 outputVaryings[shaderType] = program->getExecutable().getLinkedOutputVaryings(shaderType); 1538 inputVaryings[shaderType] = program->getExecutable().getLinkedInputVaryings(shaderType); 1539 uniforms[shaderType] = program->getState().getExecutable().getLinkedUniforms(shaderType); 1540 uniformBlocks[shaderType] = 1541 program->getState().getExecutable().getLinkedUniformBlocks(shaderType); 1542 isShaderStageUsedBitset.set(shaderType); 1543 } 1544 } 1545 1546 LinkingVariables::~LinkingVariables() = default; 1547 1548 void ProgramLinkedResources::init(std::vector<InterfaceBlock> *uniformBlocksOut, 1549 std::vector<LinkedUniform> *uniformsOut, 1550 std::vector<InterfaceBlock> *shaderStorageBlocksOut, 1551 std::vector<BufferVariable> *bufferVariablesOut, 1552 std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut) 1553 { 1554 uniformBlockLinker.init(uniformBlocksOut, uniformsOut, &unusedInterfaceBlocks); 1555 shaderStorageBlockLinker.init(shaderStorageBlocksOut, bufferVariablesOut, 1556 &unusedInterfaceBlocks); 1557 atomicCounterBufferLinker.init(atomicCounterBuffersOut); 1558 } 1559 1560 void ProgramLinkedResourcesLinker::linkResources(const Context *context, 1561 const ProgramState &programState, 1562 const ProgramLinkedResources &resources) const 1563 { 1564 // Gather uniform interface block info. 1565 InterfaceBlockInfo uniformBlockInfo(mCustomEncoderFactory); 1566 for (const ShaderType shaderType : AllShaderTypes()) 1567 { 1568 Shader *shader = programState.getAttachedShader(shaderType); 1569 if (shader) 1570 { 1571 uniformBlockInfo.getShaderBlockInfo(shader->getUniformBlocks(context)); 1572 } 1573 } 1574 1575 auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name, 1576 const std::string &mappedName, size_t *sizeOut) { 1577 return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut); 1578 }; 1579 1580 auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name, 1581 const std::string &mappedName, 1582 sh::BlockMemberInfo *infoOut) { 1583 return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut); 1584 }; 1585 1586 // Link uniform interface blocks. 1587 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo); 1588 1589 // Gather storage buffer interface block info. 1590 InterfaceBlockInfo shaderStorageBlockInfo(mCustomEncoderFactory); 1591 for (const ShaderType shaderType : AllShaderTypes()) 1592 { 1593 Shader *shader = programState.getAttachedShader(shaderType); 1594 if (shader) 1595 { 1596 shaderStorageBlockInfo.getShaderBlockInfo(shader->getShaderStorageBlocks(context)); 1597 } 1598 } 1599 auto getShaderStorageBlockSize = [&shaderStorageBlockInfo](const std::string &name, 1600 const std::string &mappedName, 1601 size_t *sizeOut) { 1602 return shaderStorageBlockInfo.getBlockSize(name, mappedName, sizeOut); 1603 }; 1604 1605 auto getShaderStorageBlockMemberInfo = [&shaderStorageBlockInfo](const std::string &name, 1606 const std::string &mappedName, 1607 sh::BlockMemberInfo *infoOut) { 1608 return shaderStorageBlockInfo.getBlockMemberInfo(name, mappedName, infoOut); 1609 }; 1610 1611 // Link storage buffer interface blocks. 1612 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize, 1613 getShaderStorageBlockMemberInfo); 1614 1615 // Gather and link atomic counter buffer interface blocks. 1616 std::map<int, unsigned int> sizeMap; 1617 getAtomicCounterBufferSizeMap(programState, sizeMap); 1618 resources.atomicCounterBufferLinker.link(sizeMap); 1619 } 1620 1621 void ProgramLinkedResourcesLinker::getAtomicCounterBufferSizeMap( 1622 const ProgramState &programState, 1623 std::map<int, unsigned int> &sizeMapOut) const 1624 { 1625 for (unsigned int index : programState.getAtomicCounterUniformRange()) 1626 { 1627 const LinkedUniform &glUniform = programState.getUniforms()[index]; 1628 1629 auto &bufferDataSize = sizeMapOut[glUniform.binding]; 1630 1631 // Calculate the size of the buffer by finding the end of the last uniform with the same 1632 // binding. The end of the uniform is calculated by finding the initial offset of the 1633 // uniform and adding size of the uniform. For arrays, the size is the number of elements 1634 // times the element size (should always by 4 for atomic_units). 1635 unsigned dataOffset = 1636 glUniform.offset + static_cast<unsigned int>(glUniform.getBasicTypeElementCount() * 1637 glUniform.getElementSize()); 1638 if (dataOffset > bufferDataSize) 1639 { 1640 bufferDataSize = dataOffset; 1641 } 1642 } 1643 } 1644 1645 bool LinkValidateProgramGlobalNames(InfoLog &infoLog, 1646 const ProgramExecutable &executable, 1647 const LinkingVariables &linkingVariables) 1648 { 1649 angle::HashMap<std::string, const sh::ShaderVariable *> uniformMap; 1650 using BlockAndFieldPair = std::pair<const sh::InterfaceBlock *, const sh::ShaderVariable *>; 1651 angle::HashMap<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap; 1652 1653 for (ShaderType shaderType : kAllGraphicsShaderTypes) 1654 { 1655 if (!linkingVariables.isShaderStageUsedBitset[shaderType]) 1656 { 1657 continue; 1658 } 1659 1660 // Build a map of Uniforms 1661 const std::vector<sh::ShaderVariable> &uniforms = linkingVariables.uniforms[shaderType]; 1662 for (const auto &uniform : uniforms) 1663 { 1664 uniformMap[uniform.name] = &uniform; 1665 } 1666 1667 // Build a map of Uniform Blocks 1668 // This will also detect any field name conflicts between Uniform Blocks without instance 1669 // names 1670 const std::vector<sh::InterfaceBlock> &uniformBlocks = 1671 linkingVariables.uniformBlocks[shaderType]; 1672 1673 for (const auto &uniformBlock : uniformBlocks) 1674 { 1675 // Only uniform blocks without an instance name can create a conflict with their field 1676 // names 1677 if (!uniformBlock.instanceName.empty()) 1678 { 1679 continue; 1680 } 1681 1682 for (const auto &field : uniformBlock.fields) 1683 { 1684 if (!uniformBlockFieldMap.count(field.name)) 1685 { 1686 // First time we've seen this uniform block field name, so add the 1687 // (Uniform Block, Field) pair immediately since there can't be a conflict yet 1688 BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field); 1689 std::vector<BlockAndFieldPair> newUniformBlockList; 1690 newUniformBlockList.push_back(blockAndFieldPair); 1691 uniformBlockFieldMap[field.name] = newUniformBlockList; 1692 continue; 1693 } 1694 1695 // We've seen this name before. 1696 // We need to check each of the uniform blocks that contain a field with this name 1697 // to see if there's a conflict or not. 1698 std::vector<BlockAndFieldPair> prevBlockFieldPairs = 1699 uniformBlockFieldMap[field.name]; 1700 for (const auto &prevBlockFieldPair : prevBlockFieldPairs) 1701 { 1702 const sh::InterfaceBlock *prevUniformBlock = prevBlockFieldPair.first; 1703 const sh::ShaderVariable *prevUniformBlockField = prevBlockFieldPair.second; 1704 1705 if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock)) 1706 { 1707 // The same uniform block should, by definition, contain the same field name 1708 continue; 1709 } 1710 1711 // The uniform blocks don't match, so check if the necessary field properties 1712 // also match 1713 if ((field.name == prevUniformBlockField->name) && 1714 (field.type == prevUniformBlockField->type) && 1715 (field.precision == prevUniformBlockField->precision)) 1716 { 1717 infoLog << "Name conflicts between uniform block field names: " 1718 << field.name; 1719 return false; 1720 } 1721 } 1722 1723 // No conflict, so record this pair 1724 BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field); 1725 uniformBlockFieldMap[field.name].push_back(blockAndFieldPair); 1726 } 1727 } 1728 } 1729 1730 // Validate no uniform names conflict with attribute names 1731 if (linkingVariables.isShaderStageUsedBitset[ShaderType::Vertex]) 1732 { 1733 // ESSL 3.00.6 section 4.3.5: 1734 // If a uniform variable name is declared in one stage (e.g., a vertex shader) 1735 // but not in another (e.g., a fragment shader), then that name is still 1736 // available in the other stage for a different use. 1737 std::unordered_set<std::string> uniforms; 1738 for (const sh::ShaderVariable &uniform : linkingVariables.uniforms[ShaderType::Vertex]) 1739 { 1740 uniforms.insert(uniform.name); 1741 } 1742 for (const auto &attrib : executable.getProgramInputs()) 1743 { 1744 if (uniforms.count(attrib.name)) 1745 { 1746 infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name; 1747 return false; 1748 } 1749 } 1750 } 1751 1752 // Validate no Uniform Block fields conflict with other Uniforms 1753 for (const auto &uniformBlockField : uniformBlockFieldMap) 1754 { 1755 const std::string &fieldName = uniformBlockField.first; 1756 if (uniformMap.count(fieldName)) 1757 { 1758 infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName; 1759 return false; 1760 } 1761 } 1762 1763 return true; 1764 } 1765 1766 // [OpenGL ES 3.2] Chapter 7.4.1 "Shader Interface Matching" 1767 bool LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> &outputVaryings, 1768 const std::vector<sh::ShaderVariable> &inputVaryings, 1769 ShaderType frontShaderType, 1770 ShaderType backShaderType, 1771 int frontShaderVersion, 1772 int backShaderVersion, 1773 bool isSeparable, 1774 gl::InfoLog &infoLog) 1775 { 1776 ASSERT(frontShaderVersion == backShaderVersion); 1777 1778 std::vector<const sh::ShaderVariable *> filteredInputVaryings; 1779 std::vector<const sh::ShaderVariable *> filteredOutputVaryings; 1780 1781 GetFilteredVaryings(inputVaryings, &filteredInputVaryings); 1782 GetFilteredVaryings(outputVaryings, &filteredOutputVaryings); 1783 1784 // Separable programs require the number of inputs and outputs match 1785 if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size()) 1786 { 1787 infoLog << GetShaderTypeString(backShaderType) 1788 << " does not consume all varyings generated by " 1789 << GetShaderTypeString(frontShaderType); 1790 return false; 1791 } 1792 if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size()) 1793 { 1794 infoLog << GetShaderTypeString(frontShaderType) 1795 << " does not generate all varyings consumed by " 1796 << GetShaderTypeString(backShaderType); 1797 return false; 1798 } 1799 1800 // All inputs must match all outputs 1801 for (const sh::ShaderVariable *input : filteredInputVaryings) 1802 { 1803 bool match = false; 1804 for (const sh::ShaderVariable *output : filteredOutputVaryings) 1805 { 1806 if (DoShaderVariablesMatch(frontShaderVersion, frontShaderType, backShaderType, *input, 1807 *output, isSeparable, infoLog)) 1808 { 1809 match = true; 1810 break; 1811 } 1812 } 1813 1814 // We permit unmatched, unreferenced varyings. Note that this specifically depends on 1815 // whether the input is statically used - a statically used input should fail this test even 1816 // if it is not active. GLSL ES 3.00.6 section 4.3.10. 1817 if (!match && input->staticUse) 1818 { 1819 const std::string &name = 1820 input->isShaderIOBlock ? input->structOrBlockName : input->name; 1821 infoLog << GetShaderTypeString(backShaderType) << " varying " << name 1822 << " does not match any " << GetShaderTypeString(frontShaderType) << " varying"; 1823 return false; 1824 } 1825 } 1826 1827 return true; 1828 } 1829 1830 LinkMismatchError LinkValidateProgramVariables(const sh::ShaderVariable &variable1, 1831 const sh::ShaderVariable &variable2, 1832 bool validatePrecision, 1833 bool treatVariable1AsNonArray, 1834 bool treatVariable2AsNonArray, 1835 std::string *mismatchedStructOrBlockMemberName) 1836 { 1837 if (variable1.type != variable2.type) 1838 { 1839 return LinkMismatchError::TYPE_MISMATCH; 1840 } 1841 1842 bool variable1IsArray = variable1.isArray(); 1843 bool variable2IsArray = variable2.isArray(); 1844 if (treatVariable1AsNonArray) 1845 { 1846 ASSERT(variable1IsArray); 1847 variable1IsArray = false; 1848 } 1849 if (treatVariable2AsNonArray) 1850 { 1851 ASSERT(variable2IsArray); 1852 variable2IsArray = false; 1853 } 1854 // TODO(anglebug.com/5557): Investigate interactions with arrays-of-arrays. 1855 if (variable1IsArray != variable2IsArray) 1856 { 1857 return LinkMismatchError::ARRAYNESS_MISMATCH; 1858 } 1859 if (!treatVariable1AsNonArray && !treatVariable2AsNonArray && 1860 variable1.arraySizes != variable2.arraySizes) 1861 { 1862 return LinkMismatchError::ARRAY_SIZE_MISMATCH; 1863 } 1864 if (validatePrecision && variable1.precision != variable2.precision) 1865 { 1866 return LinkMismatchError::PRECISION_MISMATCH; 1867 } 1868 if (!variable1.isShaderIOBlock && !variable2.isShaderIOBlock && 1869 variable1.structOrBlockName != variable2.structOrBlockName) 1870 { 1871 return LinkMismatchError::STRUCT_NAME_MISMATCH; 1872 } 1873 if (variable1.imageUnitFormat != variable2.imageUnitFormat) 1874 { 1875 return LinkMismatchError::FORMAT_MISMATCH; 1876 } 1877 1878 if (variable1.fields.size() != variable2.fields.size()) 1879 { 1880 return LinkMismatchError::FIELD_NUMBER_MISMATCH; 1881 } 1882 const unsigned int numMembers = static_cast<unsigned int>(variable1.fields.size()); 1883 for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) 1884 { 1885 const sh::ShaderVariable &member1 = variable1.fields[memberIndex]; 1886 const sh::ShaderVariable &member2 = variable2.fields[memberIndex]; 1887 1888 if (member1.name != member2.name) 1889 { 1890 return LinkMismatchError::FIELD_NAME_MISMATCH; 1891 } 1892 1893 if (member1.interpolation != member2.interpolation) 1894 { 1895 return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH; 1896 } 1897 1898 if (variable1.isShaderIOBlock && variable2.isShaderIOBlock) 1899 { 1900 if (member1.location != member2.location) 1901 { 1902 return LinkMismatchError::FIELD_LOCATION_MISMATCH; 1903 } 1904 1905 if (member1.structOrBlockName != member2.structOrBlockName) 1906 { 1907 return LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH; 1908 } 1909 } 1910 1911 LinkMismatchError linkErrorOnField = LinkValidateProgramVariables( 1912 member1, member2, validatePrecision, false, false, mismatchedStructOrBlockMemberName); 1913 if (linkErrorOnField != LinkMismatchError::NO_MISMATCH) 1914 { 1915 AddProgramVariableParentPrefix(member1.name, mismatchedStructOrBlockMemberName); 1916 return linkErrorOnField; 1917 } 1918 } 1919 1920 return LinkMismatchError::NO_MISMATCH; 1921 } 1922 1923 void AddProgramVariableParentPrefix(const std::string &parentName, std::string *mismatchedFieldName) 1924 { 1925 ASSERT(mismatchedFieldName); 1926 if (mismatchedFieldName->empty()) 1927 { 1928 *mismatchedFieldName = parentName; 1929 } 1930 else 1931 { 1932 std::ostringstream stream; 1933 stream << parentName << "." << *mismatchedFieldName; 1934 *mismatchedFieldName = stream.str(); 1935 } 1936 } 1937 1938 bool LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> &vertexVaryings, 1939 const std::vector<sh::ShaderVariable> &fragmentVaryings, 1940 int vertexShaderVersion, 1941 InfoLog &infoLog) 1942 { 1943 bool glPositionIsInvariant = false; 1944 bool glPointSizeIsInvariant = false; 1945 bool glFragCoordIsInvariant = false; 1946 bool glPointCoordIsInvariant = false; 1947 1948 for (const sh::ShaderVariable &varying : vertexVaryings) 1949 { 1950 if (!varying.isBuiltIn()) 1951 { 1952 continue; 1953 } 1954 if (varying.name.compare("gl_Position") == 0) 1955 { 1956 glPositionIsInvariant = varying.isInvariant; 1957 } 1958 else if (varying.name.compare("gl_PointSize") == 0) 1959 { 1960 glPointSizeIsInvariant = varying.isInvariant; 1961 } 1962 } 1963 1964 for (const sh::ShaderVariable &varying : fragmentVaryings) 1965 { 1966 if (!varying.isBuiltIn()) 1967 { 1968 continue; 1969 } 1970 if (varying.name.compare("gl_FragCoord") == 0) 1971 { 1972 glFragCoordIsInvariant = varying.isInvariant; 1973 } 1974 else if (varying.name.compare("gl_PointCoord") == 0) 1975 { 1976 glPointCoordIsInvariant = varying.isInvariant; 1977 } 1978 } 1979 1980 // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation, 1981 // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842. 1982 // Not requiring invariance to match is supported by: 1983 // dEQP, WebGL CTS, Nexus 5X GLES 1984 if (glFragCoordIsInvariant && !glPositionIsInvariant) 1985 { 1986 infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is " 1987 "declared invariant."; 1988 return false; 1989 } 1990 if (glPointCoordIsInvariant && !glPointSizeIsInvariant) 1991 { 1992 infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is " 1993 "declared invariant."; 1994 return false; 1995 } 1996 1997 return true; 1998 } 1999 2000 bool LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &outputVaryings, 2001 const std::vector<sh::ShaderVariable> &inputVaryings, 2002 ShaderType outputShaderType, 2003 ShaderType inputShaderType, 2004 int outputShaderVersion, 2005 int inputShaderVersion, 2006 InfoLog &infoLog) 2007 { 2008 ASSERT(outputShaderVersion == inputShaderVersion); 2009 2010 // Only ESSL 1.0 has restrictions on matching input and output invariance 2011 if (inputShaderVersion == 100 && outputShaderType == ShaderType::Vertex && 2012 inputShaderType == ShaderType::Fragment) 2013 { 2014 return LinkValidateBuiltInVaryingsInvariant(outputVaryings, inputVaryings, 2015 outputShaderVersion, infoLog); 2016 } 2017 2018 uint32_t sizeClipDistance = 0; 2019 uint32_t sizeCullDistance = 0; 2020 2021 for (const sh::ShaderVariable &varying : outputVaryings) 2022 { 2023 if (!varying.isBuiltIn()) 2024 { 2025 continue; 2026 } 2027 if (varying.name.compare("gl_ClipDistance") == 0) 2028 { 2029 sizeClipDistance = varying.getOutermostArraySize(); 2030 } 2031 else if (varying.name.compare("gl_CullDistance") == 0) 2032 { 2033 sizeCullDistance = varying.getOutermostArraySize(); 2034 } 2035 } 2036 2037 for (const sh::ShaderVariable &varying : inputVaryings) 2038 { 2039 if (!varying.isBuiltIn()) 2040 { 2041 continue; 2042 } 2043 if (varying.name.compare("gl_ClipDistance") == 0) 2044 { 2045 if (sizeClipDistance != varying.getOutermostArraySize()) 2046 { 2047 infoLog << "If either shader redeclares the built-in arrays gl_ClipDistance[] the " 2048 "array must have the same size in both shaders."; 2049 return false; 2050 } 2051 } 2052 else if (varying.name.compare("gl_CullDistance") == 0) 2053 { 2054 if (sizeCullDistance != varying.getOutermostArraySize()) 2055 { 2056 infoLog << "If either shader redeclares the built-in arrays gl_CullDistance[] the " 2057 "array must have the same size in both shaders."; 2058 return false; 2059 } 2060 } 2061 } 2062 return true; 2063 } 2064 2065 void LogAmbiguousFieldLinkMismatch(InfoLog &infoLog, 2066 const std::string &blockName1, 2067 const std::string &blockName2, 2068 const std::string &fieldName, 2069 ShaderType shaderType1, 2070 ShaderType shaderType2) 2071 { 2072 infoLog << "Ambiguous field '" << fieldName << "' in blocks '" << blockName1 << "' (" 2073 << GetShaderTypeString(shaderType1) << " shader) and '" << blockName2 << "' (" 2074 << GetShaderTypeString(shaderType2) << " shader) which don't have instance names."; 2075 } 2076 2077 bool ValidateInstancelessGraphicsInterfaceBlocksPerShader( 2078 const std::vector<sh::InterfaceBlock> &interfaceBlocks, 2079 ShaderType shaderType, 2080 InterfaceBlockMap *instancelessBlocksFields, 2081 InfoLog &infoLog) 2082 { 2083 ASSERT(instancelessBlocksFields); 2084 2085 for (const sh::InterfaceBlock &block : interfaceBlocks) 2086 { 2087 if (!block.instanceName.empty()) 2088 { 2089 continue; 2090 } 2091 2092 for (const sh::ShaderVariable &field : block.fields) 2093 { 2094 const auto &entry = instancelessBlocksFields->find(field.name); 2095 if (entry != instancelessBlocksFields->end()) 2096 { 2097 const sh::InterfaceBlock &linkedBlock = *(entry->second.second); 2098 if (block.name != linkedBlock.name) 2099 { 2100 LogAmbiguousFieldLinkMismatch(infoLog, block.name, linkedBlock.name, field.name, 2101 entry->second.first, shaderType); 2102 return false; 2103 } 2104 } 2105 else 2106 { 2107 (*instancelessBlocksFields)[field.name] = std::make_pair(shaderType, &block); 2108 } 2109 } 2110 } 2111 2112 return true; 2113 } 2114 2115 LinkMismatchError LinkValidateInterfaceBlockFields(const sh::ShaderVariable &blockField1, 2116 const sh::ShaderVariable &blockField2, 2117 bool webglCompatibility, 2118 std::string *mismatchedBlockFieldName) 2119 { 2120 if (blockField1.name != blockField2.name) 2121 { 2122 return LinkMismatchError::FIELD_NAME_MISMATCH; 2123 } 2124 2125 // If webgl, validate precision of UBO fields, otherwise don't. See Khronos bug 10287. 2126 LinkMismatchError linkError = LinkValidateProgramVariables( 2127 blockField1, blockField2, webglCompatibility, false, false, mismatchedBlockFieldName); 2128 if (linkError != LinkMismatchError::NO_MISMATCH) 2129 { 2130 AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName); 2131 return linkError; 2132 } 2133 2134 if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout) 2135 { 2136 AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName); 2137 return LinkMismatchError::MATRIX_PACKING_MISMATCH; 2138 } 2139 2140 return LinkMismatchError::NO_MISMATCH; 2141 } 2142 2143 LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1, 2144 const sh::InterfaceBlock &interfaceBlock2, 2145 bool webglCompatibility, 2146 std::string *mismatchedBlockFieldName) 2147 { 2148 // validate blocks for the same member types 2149 if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size()) 2150 { 2151 return LinkMismatchError::FIELD_NUMBER_MISMATCH; 2152 } 2153 if (interfaceBlock1.arraySize != interfaceBlock2.arraySize) 2154 { 2155 return LinkMismatchError::ARRAY_SIZE_MISMATCH; 2156 } 2157 if (interfaceBlock1.layout != interfaceBlock2.layout || 2158 interfaceBlock1.binding != interfaceBlock2.binding) 2159 { 2160 return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH; 2161 } 2162 if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty()) 2163 { 2164 return LinkMismatchError::INSTANCE_NAME_MISMATCH; 2165 } 2166 const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size()); 2167 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) 2168 { 2169 const sh::ShaderVariable &member1 = interfaceBlock1.fields[blockMemberIndex]; 2170 const sh::ShaderVariable &member2 = interfaceBlock2.fields[blockMemberIndex]; 2171 2172 LinkMismatchError linkError = LinkValidateInterfaceBlockFields( 2173 member1, member2, webglCompatibility, mismatchedBlockFieldName); 2174 if (linkError != LinkMismatchError::NO_MISMATCH) 2175 { 2176 return linkError; 2177 } 2178 } 2179 return LinkMismatchError::NO_MISMATCH; 2180 } 2181 2182 void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks, 2183 ShaderType shaderType, 2184 InterfaceBlockMap *linkedInterfaceBlocks) 2185 { 2186 ASSERT(linkedInterfaceBlocks); 2187 2188 for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks) 2189 { 2190 (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock); 2191 } 2192 } 2193 2194 bool ValidateGraphicsInterfaceBlocksPerShader( 2195 const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink, 2196 ShaderType shaderType, 2197 bool webglCompatibility, 2198 InterfaceBlockMap *linkedBlocks, 2199 InfoLog &infoLog) 2200 { 2201 ASSERT(linkedBlocks); 2202 2203 for (const sh::InterfaceBlock &block : interfaceBlocksToLink) 2204 { 2205 const auto &entry = linkedBlocks->find(block.name); 2206 if (entry != linkedBlocks->end()) 2207 { 2208 const sh::InterfaceBlock &linkedBlock = *(entry->second.second); 2209 std::string mismatchedStructFieldName; 2210 LinkMismatchError linkError = AreMatchingInterfaceBlocks( 2211 block, linkedBlock, webglCompatibility, &mismatchedStructFieldName); 2212 if (linkError != LinkMismatchError::NO_MISMATCH) 2213 { 2214 LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType), 2215 linkError, mismatchedStructFieldName, entry->second.first, 2216 shaderType); 2217 return false; 2218 } 2219 } 2220 else 2221 { 2222 (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block); 2223 } 2224 } 2225 2226 return true; 2227 } 2228 2229 bool ValidateInterfaceBlocksMatch( 2230 GLuint numShadersHasInterfaceBlocks, 2231 const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks, 2232 InfoLog &infoLog, 2233 bool webglCompatibility, 2234 InterfaceBlockMap *instancelessInterfaceBlocksFields) 2235 { 2236 for (ShaderType shaderType : kAllGraphicsShaderTypes) 2237 { 2238 // Validate that instanceless blocks of different names don't have fields of the same name. 2239 if (shaderInterfaceBlocks[shaderType] && 2240 !ValidateInstancelessGraphicsInterfaceBlocksPerShader( 2241 *shaderInterfaceBlocks[shaderType], shaderType, instancelessInterfaceBlocksFields, 2242 infoLog)) 2243 { 2244 return false; 2245 } 2246 } 2247 2248 if (numShadersHasInterfaceBlocks < 2u) 2249 { 2250 return true; 2251 } 2252 2253 ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]); 2254 2255 // Check that interface blocks defined in the graphics shaders are identical 2256 2257 InterfaceBlockMap linkedInterfaceBlocks; 2258 2259 bool interfaceBlockMapInitialized = false; 2260 for (ShaderType shaderType : kAllGraphicsShaderTypes) 2261 { 2262 if (!shaderInterfaceBlocks[shaderType]) 2263 { 2264 continue; 2265 } 2266 2267 if (!interfaceBlockMapInitialized) 2268 { 2269 InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType, 2270 &linkedInterfaceBlocks); 2271 interfaceBlockMapInitialized = true; 2272 } 2273 else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType], 2274 shaderType, webglCompatibility, 2275 &linkedInterfaceBlocks, infoLog)) 2276 { 2277 return false; 2278 } 2279 } 2280 2281 return true; 2282 } 2283 2284 bool LinkValidateProgramInterfaceBlocks(const Context *context, 2285 ShaderBitSet activeProgramStages, 2286 const ProgramLinkedResources &resources, 2287 InfoLog &infoLog, 2288 GLuint *combinedShaderStorageBlocksCountOut) 2289 { 2290 ASSERT(combinedShaderStorageBlocksCountOut); 2291 2292 const Caps &caps = context->getCaps(); 2293 const bool webglCompatibility = context->isWebGL(); 2294 const Version &version = context->getClientVersion(); 2295 2296 GLuint combinedUniformBlocksCount = 0u; 2297 GLuint numShadersHasUniformBlocks = 0u; 2298 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {}; 2299 InterfaceBlockMap instancelessInterfaceBlocksFields; 2300 2301 for (ShaderType shaderType : activeProgramStages) 2302 { 2303 const std::vector<sh::InterfaceBlock> &uniformBlocks = 2304 resources.uniformBlockLinker.getShaderBlocks(shaderType); 2305 if (!uniformBlocks.empty()) 2306 { 2307 if (!ValidateInterfaceBlocksCount( 2308 static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks, 2309 shaderType, sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog)) 2310 { 2311 return false; 2312 } 2313 2314 allShaderUniformBlocks[shaderType] = &uniformBlocks; 2315 ++numShadersHasUniformBlocks; 2316 } 2317 } 2318 2319 if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks)) 2320 { 2321 infoLog << "The sum of the number of active uniform blocks exceeds " 2322 "MAX_COMBINED_UNIFORM_BLOCKS (" 2323 << caps.maxCombinedUniformBlocks << ")."; 2324 return false; 2325 } 2326 2327 if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog, 2328 webglCompatibility, &instancelessInterfaceBlocksFields)) 2329 { 2330 return false; 2331 } 2332 2333 if (version >= Version(3, 1)) 2334 { 2335 *combinedShaderStorageBlocksCountOut = 0u; 2336 GLuint numShadersHasShaderStorageBlocks = 0u; 2337 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {}; 2338 for (ShaderType shaderType : activeProgramStages) 2339 { 2340 const std::vector<sh::InterfaceBlock> &shaderStorageBlocks = 2341 resources.shaderStorageBlockLinker.getShaderBlocks(shaderType); 2342 if (!shaderStorageBlocks.empty()) 2343 { 2344 if (!ValidateInterfaceBlocksCount( 2345 static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]), 2346 shaderStorageBlocks, shaderType, sh::BlockType::BLOCK_BUFFER, 2347 combinedShaderStorageBlocksCountOut, infoLog)) 2348 { 2349 return false; 2350 } 2351 2352 allShaderStorageBlocks[shaderType] = &shaderStorageBlocks; 2353 ++numShadersHasShaderStorageBlocks; 2354 } 2355 } 2356 2357 if (*combinedShaderStorageBlocksCountOut > 2358 static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks)) 2359 { 2360 infoLog << "The sum of the number of active shader storage blocks exceeds " 2361 "MAX_COMBINED_SHADER_STORAGE_BLOCKS (" 2362 << caps.maxCombinedShaderStorageBlocks << ")."; 2363 return false; 2364 } 2365 2366 if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks, 2367 infoLog, webglCompatibility, 2368 &instancelessInterfaceBlocksFields)) 2369 { 2370 return false; 2371 } 2372 } 2373 2374 return true; 2375 } 2376 2377 } // namespace gl