Program.cpp (126745B)
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.cpp: Implements 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 #include "libANGLE/Program.h" 11 12 #include <algorithm> 13 #include <utility> 14 15 #include "common/angle_version_info.h" 16 #include "common/bitset_utils.h" 17 #include "common/debug.h" 18 #include "common/platform.h" 19 #include "common/string_utils.h" 20 #include "common/utilities.h" 21 #include "compiler/translator/blocklayout.h" 22 #include "libANGLE/Context.h" 23 #include "libANGLE/ErrorStrings.h" 24 #include "libANGLE/MemoryProgramCache.h" 25 #include "libANGLE/ProgramLinkedResources.h" 26 #include "libANGLE/ResourceManager.h" 27 #include "libANGLE/Uniform.h" 28 #include "libANGLE/VaryingPacking.h" 29 #include "libANGLE/Version.h" 30 #include "libANGLE/capture/FrameCapture.h" 31 #include "libANGLE/features.h" 32 #include "libANGLE/histogram_macros.h" 33 #include "libANGLE/queryconversions.h" 34 #include "libANGLE/renderer/GLImplFactory.h" 35 #include "libANGLE/renderer/ProgramImpl.h" 36 #include "platform/FrontendFeatures_autogen.h" 37 #include "platform/PlatformMethods.h" 38 39 namespace gl 40 { 41 42 namespace 43 { 44 45 // This simplified cast function doesn't need to worry about advanced concepts like 46 // depth range values, or casting to bool. 47 template <typename DestT, typename SrcT> 48 DestT UniformStateQueryCast(SrcT value); 49 50 // From-Float-To-Integer Casts 51 template <> 52 GLint UniformStateQueryCast(GLfloat value) 53 { 54 return clampCast<GLint>(roundf(value)); 55 } 56 57 template <> 58 GLuint UniformStateQueryCast(GLfloat value) 59 { 60 return clampCast<GLuint>(roundf(value)); 61 } 62 63 // From-Integer-to-Integer Casts 64 template <> 65 GLint UniformStateQueryCast(GLuint value) 66 { 67 return clampCast<GLint>(value); 68 } 69 70 template <> 71 GLuint UniformStateQueryCast(GLint value) 72 { 73 return clampCast<GLuint>(value); 74 } 75 76 // From-Boolean-to-Anything Casts 77 template <> 78 GLfloat UniformStateQueryCast(GLboolean value) 79 { 80 return (ConvertToBool(value) ? 1.0f : 0.0f); 81 } 82 83 template <> 84 GLint UniformStateQueryCast(GLboolean value) 85 { 86 return (ConvertToBool(value) ? 1 : 0); 87 } 88 89 template <> 90 GLuint UniformStateQueryCast(GLboolean value) 91 { 92 return (ConvertToBool(value) ? 1u : 0u); 93 } 94 95 // Default to static_cast 96 template <typename DestT, typename SrcT> 97 DestT UniformStateQueryCast(SrcT value) 98 { 99 return static_cast<DestT>(value); 100 } 101 102 template <typename SrcT, typename DestT> 103 void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components) 104 { 105 for (int comp = 0; comp < components; ++comp) 106 { 107 // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint) 108 // Don't use SrcT stride directly since GLboolean has a stride of 1 byte. 109 size_t offset = comp * 4; 110 const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]); 111 dataOut[comp] = UniformStateQueryCast<DestT>(*typedSrcPointer); 112 } 113 } 114 115 template <typename VarT> 116 GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name) 117 { 118 std::string nameAsArrayName = name + "[0]"; 119 for (size_t index = 0; index < list.size(); index++) 120 { 121 const VarT &resource = list[index]; 122 if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName)) 123 { 124 return static_cast<GLuint>(index); 125 } 126 } 127 128 return GL_INVALID_INDEX; 129 } 130 131 GLint GetVariableLocation(const std::vector<sh::ShaderVariable> &list, 132 const std::vector<VariableLocation> &locationList, 133 const std::string &name) 134 { 135 size_t nameLengthWithoutArrayIndex; 136 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex); 137 138 for (size_t location = 0u; location < locationList.size(); ++location) 139 { 140 const VariableLocation &variableLocation = locationList[location]; 141 if (!variableLocation.used()) 142 { 143 continue; 144 } 145 146 const sh::ShaderVariable &variable = list[variableLocation.index]; 147 148 // Array output variables may be bound out of order, so we need to ensure we only pick the 149 // first element if given the base name. 150 if ((variable.name == name) && (variableLocation.arrayIndex == 0)) 151 { 152 return static_cast<GLint>(location); 153 } 154 if (variable.isArray() && variableLocation.arrayIndex == arrayIndex && 155 angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex)) 156 { 157 return static_cast<GLint>(location); 158 } 159 } 160 161 return -1; 162 } 163 164 GLint GetVariableLocation(const std::vector<LinkedUniform> &list, 165 const std::vector<VariableLocation> &locationList, 166 const std::string &name) 167 { 168 size_t nameLengthWithoutArrayIndex; 169 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex); 170 171 for (size_t location = 0u; location < locationList.size(); ++location) 172 { 173 const VariableLocation &variableLocation = locationList[location]; 174 if (!variableLocation.used()) 175 { 176 continue; 177 } 178 179 const LinkedUniform &variable = list[variableLocation.index]; 180 181 // Array output variables may be bound out of order, so we need to ensure we only pick the 182 // first element if given the base name. Uniforms don't allow this behavior and some code 183 // seemingly depends on the opposite behavior, so only enable it for output variables. 184 if (angle::BeginsWith(variable.name, name) && (variableLocation.arrayIndex == 0)) 185 { 186 if (name.length() == variable.name.length()) 187 { 188 ASSERT(name == variable.name); 189 // GLES 3.1 November 2016 page 87. 190 // The string exactly matches the name of the active variable. 191 return static_cast<GLint>(location); 192 } 193 if (name.length() + 3u == variable.name.length() && variable.isArray()) 194 { 195 ASSERT(name + "[0]" == variable.name); 196 // The string identifies the base name of an active array, where the string would 197 // exactly match the name of the variable if the suffix "[0]" were appended to the 198 // string. 199 return static_cast<GLint>(location); 200 } 201 } 202 if (variable.isArray() && variableLocation.arrayIndex == arrayIndex && 203 nameLengthWithoutArrayIndex + 3u == variable.name.length() && 204 angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex)) 205 { 206 ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name); 207 // The string identifies an active element of the array, where the string ends with the 208 // concatenation of the "[" character, an integer (with no "+" sign, extra leading 209 // zeroes, or whitespace) identifying an array element, and the "]" character, the 210 // integer is less than the number of active elements of the array variable, and where 211 // the string would exactly match the enumerated name of the array if the decimal 212 // integer were replaced with zero. 213 return static_cast<GLint>(location); 214 } 215 } 216 217 return -1; 218 } 219 220 void CopyStringToBuffer(GLchar *buffer, 221 const std::string &string, 222 GLsizei bufSize, 223 GLsizei *lengthOut) 224 { 225 ASSERT(bufSize > 0); 226 size_t length = std::min<size_t>(bufSize - 1, string.length()); 227 memcpy(buffer, string.c_str(), length); 228 buffer[length] = '\0'; 229 230 if (lengthOut) 231 { 232 *lengthOut = static_cast<GLsizei>(length); 233 } 234 } 235 236 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name) 237 { 238 std::vector<unsigned int> subscripts; 239 std::string baseName = ParseResourceName(name, &subscripts); 240 241 unsigned int numBlocks = static_cast<unsigned int>(list.size()); 242 for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++) 243 { 244 const auto &block = list[blockIndex]; 245 if (block.name == baseName) 246 { 247 const bool arrayElementZero = 248 (subscripts.empty() && (!block.isArray || block.arrayElement == 0)); 249 const bool arrayElementMatches = 250 (subscripts.size() == 1 && subscripts[0] == block.arrayElement); 251 if (arrayElementMatches || arrayElementZero) 252 { 253 return blockIndex; 254 } 255 } 256 } 257 258 return GL_INVALID_INDEX; 259 } 260 261 void GetInterfaceBlockName(const UniformBlockIndex index, 262 const std::vector<InterfaceBlock> &list, 263 GLsizei bufSize, 264 GLsizei *length, 265 GLchar *name) 266 { 267 ASSERT(index.value < list.size()); 268 269 const auto &block = list[index.value]; 270 271 if (bufSize > 0) 272 { 273 std::string blockName = block.name; 274 275 if (block.isArray) 276 { 277 blockName += ArrayString(block.arrayElement); 278 } 279 CopyStringToBuffer(name, blockName, bufSize, length); 280 } 281 } 282 283 void InitUniformBlockLinker(const Context *context, 284 const ProgramState &state, 285 UniformBlockLinker *blockLinker) 286 { 287 for (ShaderType shaderType : AllShaderTypes()) 288 { 289 Shader *shader = state.getAttachedShader(shaderType); 290 if (shader) 291 { 292 blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks(context)); 293 } 294 } 295 } 296 297 void InitShaderStorageBlockLinker(const Context *context, 298 const ProgramState &state, 299 ShaderStorageBlockLinker *blockLinker) 300 { 301 for (ShaderType shaderType : AllShaderTypes()) 302 { 303 Shader *shader = state.getAttachedShader(shaderType); 304 if (shader != nullptr) 305 { 306 blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks(context)); 307 } 308 } 309 } 310 } // anonymous namespace 311 312 const char *GetLinkMismatchErrorString(LinkMismatchError linkError) 313 { 314 switch (linkError) 315 { 316 case LinkMismatchError::TYPE_MISMATCH: 317 return "Type"; 318 case LinkMismatchError::ARRAYNESS_MISMATCH: 319 return "Array-ness"; 320 case LinkMismatchError::ARRAY_SIZE_MISMATCH: 321 return "Array size"; 322 case LinkMismatchError::PRECISION_MISMATCH: 323 return "Precision"; 324 case LinkMismatchError::STRUCT_NAME_MISMATCH: 325 return "Structure name"; 326 case LinkMismatchError::FIELD_NUMBER_MISMATCH: 327 return "Field number"; 328 case LinkMismatchError::FIELD_NAME_MISMATCH: 329 return "Field name"; 330 331 case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH: 332 return "Interpolation type"; 333 case LinkMismatchError::INVARIANCE_MISMATCH: 334 return "Invariance"; 335 336 case LinkMismatchError::BINDING_MISMATCH: 337 return "Binding layout qualifier"; 338 case LinkMismatchError::LOCATION_MISMATCH: 339 return "Location layout qualifier"; 340 case LinkMismatchError::OFFSET_MISMATCH: 341 return "Offset layout qualifier"; 342 case LinkMismatchError::INSTANCE_NAME_MISMATCH: 343 return "Instance name qualifier"; 344 case LinkMismatchError::FORMAT_MISMATCH: 345 return "Format qualifier"; 346 347 case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH: 348 return "Layout qualifier"; 349 case LinkMismatchError::MATRIX_PACKING_MISMATCH: 350 return "Matrix Packing"; 351 352 case LinkMismatchError::FIELD_LOCATION_MISMATCH: 353 return "Field location"; 354 case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH: 355 return "Field structure name"; 356 default: 357 UNREACHABLE(); 358 return ""; 359 } 360 } 361 362 void UpdateInterfaceVariable(std::vector<sh::ShaderVariable> *block, const sh::ShaderVariable &var) 363 { 364 if (!var.isStruct()) 365 { 366 block->emplace_back(var); 367 block->back().resetEffectiveLocation(); 368 } 369 370 for (const sh::ShaderVariable &field : var.fields) 371 { 372 ASSERT(!var.name.empty() || var.isShaderIOBlock); 373 374 // Shader I/O block naming is similar to UBOs and SSBOs: 375 // 376 // in Block 377 // { 378 // type field; // produces "field" 379 // }; 380 // 381 // in Block2 382 // { 383 // type field; // produces "Block2.field" 384 // } block2; 385 // 386 const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name; 387 const std::string prefix = var.name.empty() ? "" : baseName + "."; 388 389 if (!field.isStruct()) 390 { 391 sh::ShaderVariable fieldCopy = field; 392 fieldCopy.updateEffectiveLocation(var); 393 fieldCopy.name = prefix + field.name; 394 block->emplace_back(fieldCopy); 395 } 396 397 for (const sh::ShaderVariable &nested : field.fields) 398 { 399 sh::ShaderVariable nestedCopy = nested; 400 nestedCopy.updateEffectiveLocation(field); 401 nestedCopy.name = prefix + field.name + "." + nested.name; 402 block->emplace_back(nestedCopy); 403 } 404 } 405 } 406 407 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var) 408 { 409 stream->writeInt(var.binding); 410 stream->writeInt(var.dataSize); 411 412 for (ShaderType shaderType : AllShaderTypes()) 413 { 414 stream->writeBool(var.isActive(shaderType)); 415 } 416 417 stream->writeInt(var.memberIndexes.size()); 418 for (unsigned int memberCounterIndex : var.memberIndexes) 419 { 420 stream->writeInt(memberCounterIndex); 421 } 422 } 423 424 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var) 425 { 426 var->binding = stream->readInt<int>(); 427 var->dataSize = stream->readInt<unsigned int>(); 428 429 for (ShaderType shaderType : AllShaderTypes()) 430 { 431 var->setActive(shaderType, stream->readBool()); 432 } 433 434 size_t numMembers = stream->readInt<size_t>(); 435 for (size_t blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) 436 { 437 var->memberIndexes.push_back(stream->readInt<unsigned int>()); 438 } 439 } 440 441 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var) 442 { 443 WriteShaderVar(stream, var); 444 445 stream->writeInt(var.bufferIndex); 446 WriteBlockMemberInfo(stream, var.blockInfo); 447 stream->writeInt(var.topLevelArraySize); 448 449 for (ShaderType shaderType : AllShaderTypes()) 450 { 451 stream->writeBool(var.isActive(shaderType)); 452 } 453 } 454 455 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var) 456 { 457 LoadShaderVar(stream, var); 458 459 var->bufferIndex = stream->readInt<int>(); 460 LoadBlockMemberInfo(stream, &var->blockInfo); 461 var->topLevelArraySize = stream->readInt<int>(); 462 463 for (ShaderType shaderType : AllShaderTypes()) 464 { 465 var->setActive(shaderType, stream->readBool()); 466 } 467 } 468 469 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block) 470 { 471 stream->writeString(block.name); 472 stream->writeString(block.mappedName); 473 stream->writeBool(block.isArray); 474 stream->writeInt(block.arrayElement); 475 476 WriteShaderVariableBuffer(stream, block); 477 } 478 479 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block) 480 { 481 block->name = stream->readString(); 482 block->mappedName = stream->readString(); 483 block->isArray = stream->readBool(); 484 block->arrayElement = stream->readInt<unsigned int>(); 485 486 LoadShaderVariableBuffer(stream, block); 487 } 488 489 void WriteShInterfaceBlock(BinaryOutputStream *stream, const sh::InterfaceBlock &block) 490 { 491 stream->writeString(block.name); 492 stream->writeString(block.mappedName); 493 stream->writeString(block.instanceName); 494 stream->writeInt(block.arraySize); 495 stream->writeEnum(block.layout); 496 stream->writeBool(block.isRowMajorLayout); 497 stream->writeInt(block.binding); 498 stream->writeBool(block.staticUse); 499 stream->writeBool(block.active); 500 stream->writeEnum(block.blockType); 501 502 stream->writeInt<size_t>(block.fields.size()); 503 for (const sh::ShaderVariable &shaderVariable : block.fields) 504 { 505 WriteShaderVar(stream, shaderVariable); 506 } 507 } 508 509 void LoadShInterfaceBlock(BinaryInputStream *stream, sh::InterfaceBlock *block) 510 { 511 block->name = stream->readString(); 512 block->mappedName = stream->readString(); 513 block->instanceName = stream->readString(); 514 block->arraySize = stream->readInt<unsigned int>(); 515 block->layout = stream->readEnum<sh::BlockLayoutType>(); 516 block->isRowMajorLayout = stream->readBool(); 517 block->binding = stream->readInt<int>(); 518 block->staticUse = stream->readBool(); 519 block->active = stream->readBool(); 520 block->blockType = stream->readEnum<sh::BlockType>(); 521 522 block->fields.resize(stream->readInt<size_t>()); 523 for (sh::ShaderVariable &variable : block->fields) 524 { 525 LoadShaderVar(stream, &variable); 526 } 527 } 528 529 // Saves the linking context for later use in resolveLink(). 530 struct Program::LinkingState 531 { 532 std::shared_ptr<ProgramExecutable> linkedExecutable; 533 ProgramLinkedResources resources; 534 egl::BlobCache::Key programHash; 535 std::unique_ptr<rx::LinkEvent> linkEvent; 536 bool linkingFromBinary; 537 }; 538 539 const char *const g_fakepath = "C:\\fakepath"; 540 541 // InfoLog implementation. 542 InfoLog::InfoLog() : mLazyStream(nullptr) {} 543 544 InfoLog::~InfoLog() {} 545 546 size_t InfoLog::getLength() const 547 { 548 if (!mLazyStream) 549 { 550 return 0; 551 } 552 553 const std::string &logString = mLazyStream->str(); 554 return logString.empty() ? 0 : logString.length() + 1; 555 } 556 557 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const 558 { 559 size_t index = 0; 560 561 if (bufSize > 0) 562 { 563 const std::string logString(str()); 564 565 if (!logString.empty()) 566 { 567 index = std::min(static_cast<size_t>(bufSize) - 1, logString.length()); 568 memcpy(infoLog, logString.c_str(), index); 569 } 570 571 infoLog[index] = '\0'; 572 } 573 574 if (length) 575 { 576 *length = static_cast<GLsizei>(index); 577 } 578 } 579 580 // append a sanitized message to the program info log. 581 // The D3D compiler includes a fake file path in some of the warning or error 582 // messages, so lets remove all occurrences of this fake file path from the log. 583 void InfoLog::appendSanitized(const char *message) 584 { 585 ensureInitialized(); 586 587 std::string msg(message); 588 589 size_t found; 590 do 591 { 592 found = msg.find(g_fakepath); 593 if (found != std::string::npos) 594 { 595 msg.erase(found, strlen(g_fakepath)); 596 } 597 } while (found != std::string::npos); 598 599 if (!msg.empty()) 600 { 601 *mLazyStream << message << std::endl; 602 } 603 } 604 605 void InfoLog::reset() 606 { 607 if (mLazyStream) 608 { 609 mLazyStream.reset(nullptr); 610 } 611 } 612 613 bool InfoLog::empty() const 614 { 615 if (!mLazyStream) 616 { 617 return true; 618 } 619 620 return mLazyStream->rdbuf()->in_avail() == 0; 621 } 622 623 void LogLinkMismatch(InfoLog &infoLog, 624 const std::string &variableName, 625 const char *variableType, 626 LinkMismatchError linkError, 627 const std::string &mismatchedStructOrBlockFieldName, 628 ShaderType shaderType1, 629 ShaderType shaderType2) 630 { 631 std::ostringstream stream; 632 stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '" 633 << variableName; 634 635 if (!mismatchedStructOrBlockFieldName.empty()) 636 { 637 stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName; 638 } 639 640 stream << "' differ between " << GetShaderTypeString(shaderType1) << " and " 641 << GetShaderTypeString(shaderType2) << " shaders."; 642 643 infoLog << stream.str(); 644 } 645 646 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock) 647 { 648 // Only 'packed' blocks are allowed to be considered inactive. 649 return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED; 650 } 651 652 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var) 653 { 654 stream->writeInt(var.arrayStride); 655 stream->writeBool(var.isRowMajorMatrix); 656 stream->writeInt(var.matrixStride); 657 stream->writeInt(var.offset); 658 stream->writeInt(var.topLevelArrayStride); 659 } 660 661 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var) 662 { 663 var->arrayStride = stream->readInt<int>(); 664 var->isRowMajorMatrix = stream->readBool(); 665 var->matrixStride = stream->readInt<int>(); 666 var->offset = stream->readInt<int>(); 667 var->topLevelArrayStride = stream->readInt<int>(); 668 } 669 670 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var) 671 { 672 stream->writeInt(var.type); 673 stream->writeInt(var.precision); 674 stream->writeString(var.name); 675 stream->writeString(var.mappedName); 676 stream->writeIntVector(var.arraySizes); 677 stream->writeBool(var.staticUse); 678 stream->writeBool(var.active); 679 stream->writeInt<size_t>(var.fields.size()); 680 for (const sh::ShaderVariable &shaderVariable : var.fields) 681 { 682 WriteShaderVar(stream, shaderVariable); 683 } 684 stream->writeString(var.structOrBlockName); 685 stream->writeString(var.mappedStructOrBlockName); 686 stream->writeBool(var.isRowMajorLayout); 687 stream->writeInt(var.location); 688 stream->writeBool(var.hasImplicitLocation); 689 stream->writeInt(var.binding); 690 stream->writeInt(var.imageUnitFormat); 691 stream->writeInt(var.offset); 692 stream->writeBool(var.rasterOrdered); 693 stream->writeBool(var.readonly); 694 stream->writeBool(var.writeonly); 695 stream->writeBool(var.isFragmentInOut); 696 stream->writeInt(var.index); 697 stream->writeBool(var.yuv); 698 stream->writeEnum(var.interpolation); 699 stream->writeBool(var.isInvariant); 700 stream->writeBool(var.isShaderIOBlock); 701 stream->writeBool(var.isPatch); 702 stream->writeBool(var.texelFetchStaticUse); 703 stream->writeInt(var.getFlattenedOffsetInParentArrays()); 704 } 705 706 void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var) 707 { 708 var->type = stream->readInt<GLenum>(); 709 var->precision = stream->readInt<GLenum>(); 710 stream->readString(&var->name); 711 stream->readString(&var->mappedName); 712 stream->readIntVector<unsigned int>(&var->arraySizes); 713 var->staticUse = stream->readBool(); 714 var->active = stream->readBool(); 715 size_t elementCount = stream->readInt<size_t>(); 716 var->fields.resize(elementCount); 717 for (sh::ShaderVariable &variable : var->fields) 718 { 719 LoadShaderVar(stream, &variable); 720 } 721 stream->readString(&var->structOrBlockName); 722 stream->readString(&var->mappedStructOrBlockName); 723 var->isRowMajorLayout = stream->readBool(); 724 var->location = stream->readInt<int>(); 725 var->hasImplicitLocation = stream->readBool(); 726 var->binding = stream->readInt<int>(); 727 var->imageUnitFormat = stream->readInt<GLenum>(); 728 var->offset = stream->readInt<int>(); 729 var->rasterOrdered = stream->readBool(); 730 var->readonly = stream->readBool(); 731 var->writeonly = stream->readBool(); 732 var->isFragmentInOut = stream->readBool(); 733 var->index = stream->readInt<int>(); 734 var->yuv = stream->readBool(); 735 var->interpolation = stream->readEnum<sh::InterpolationType>(); 736 var->isInvariant = stream->readBool(); 737 var->isShaderIOBlock = stream->readBool(); 738 var->isPatch = stream->readBool(); 739 var->texelFetchStaticUse = stream->readBool(); 740 var->setParentArrayIndex(stream->readInt<int>()); 741 } 742 743 // VariableLocation implementation. 744 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {} 745 746 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index) 747 : arrayIndex(arrayIndex), index(index), ignored(false) 748 { 749 ASSERT(arrayIndex != GL_INVALID_INDEX); 750 } 751 752 // SamplerBindings implementation. 753 SamplerBinding::SamplerBinding(TextureType textureTypeIn, 754 GLenum samplerTypeIn, 755 SamplerFormat formatIn, 756 size_t elementCount) 757 : textureType(textureTypeIn), 758 samplerType(samplerTypeIn), 759 format(formatIn), 760 boundTextureUnits(elementCount, 0) 761 {} 762 763 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default; 764 765 SamplerBinding::~SamplerBinding() = default; 766 767 // ProgramBindings implementation. 768 ProgramBindings::ProgramBindings() {} 769 770 ProgramBindings::~ProgramBindings() {} 771 772 void ProgramBindings::bindLocation(GLuint index, const std::string &name) 773 { 774 mBindings[name] = index; 775 } 776 777 int ProgramBindings::getBindingByName(const std::string &name) const 778 { 779 auto iter = mBindings.find(name); 780 return (iter != mBindings.end()) ? iter->second : -1; 781 } 782 783 int ProgramBindings::getBinding(const sh::ShaderVariable &variable) const 784 { 785 return getBindingByName(variable.name); 786 } 787 788 ProgramBindings::const_iterator ProgramBindings::begin() const 789 { 790 return mBindings.begin(); 791 } 792 793 ProgramBindings::const_iterator ProgramBindings::end() const 794 { 795 return mBindings.end(); 796 } 797 798 std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const 799 { 800 return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end()); 801 } 802 803 // ProgramAliasedBindings implementation. 804 ProgramAliasedBindings::ProgramAliasedBindings() {} 805 806 ProgramAliasedBindings::~ProgramAliasedBindings() {} 807 808 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name) 809 { 810 mBindings[name] = ProgramBinding(index); 811 812 // EXT_blend_func_extended spec: "If it specifies the base name of an array, 813 // it identifies the resources associated with the first element of the array." 814 // 815 // Normalize array bindings so that "name" and "name[0]" map to the same entry. 816 // If this binding is of the form "name[0]", then mark the "name" binding as 817 // aliased but do not update it yet in case "name" is not actually an array. 818 size_t nameLengthWithoutArrayIndex; 819 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex); 820 if (arrayIndex == 0) 821 { 822 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex); 823 auto iter = mBindings.find(baseName); 824 if (iter != mBindings.end()) 825 { 826 iter->second.aliased = true; 827 } 828 } 829 } 830 831 int ProgramAliasedBindings::getBindingByName(const std::string &name) const 832 { 833 auto iter = mBindings.find(name); 834 return (iter != mBindings.end()) ? iter->second.location : -1; 835 } 836 837 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const 838 { 839 for (const auto &iter : mBindings) 840 { 841 if (iter.second.location == location) 842 { 843 return iter.second.location; 844 } 845 } 846 return -1; 847 } 848 849 int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const 850 { 851 const std::string &name = variable.name; 852 853 // Check with the normalized array name if applicable. 854 if (variable.isArray()) 855 { 856 size_t nameLengthWithoutArrayIndex; 857 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex); 858 if (arrayIndex == 0) 859 { 860 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex); 861 auto iter = mBindings.find(baseName); 862 // If "name" exists and is not aliased, that means it was modified more 863 // recently than its "name[0]" form and should be used instead of that. 864 if (iter != mBindings.end() && !iter->second.aliased) 865 { 866 return iter->second.location; 867 } 868 } 869 else if (arrayIndex == GL_INVALID_INDEX) 870 { 871 auto iter = mBindings.find(variable.name); 872 // If "name" exists and is not aliased, that means it was modified more 873 // recently than its "name[0]" form and should be used instead of that. 874 if (iter != mBindings.end() && !iter->second.aliased) 875 { 876 return iter->second.location; 877 } 878 // The base name was aliased, so use the name with the array notation. 879 return getBindingByName(name + "[0]"); 880 } 881 } 882 883 return getBindingByName(name); 884 } 885 886 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const 887 { 888 return mBindings.begin(); 889 } 890 891 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const 892 { 893 return mBindings.end(); 894 } 895 896 std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const 897 { 898 return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end()); 899 } 900 901 // ImageBinding implementation. 902 ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn) 903 : textureType(textureTypeIn), boundImageUnits(count, 0) 904 {} 905 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn) 906 : textureType(textureTypeIn) 907 { 908 for (size_t index = 0; index < count; ++index) 909 { 910 boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index)); 911 } 912 } 913 914 ImageBinding::ImageBinding(const ImageBinding &other) = default; 915 916 ImageBinding::~ImageBinding() = default; 917 918 // ProgramState implementation. 919 ProgramState::ProgramState() 920 : mLabel(), 921 mAttachedShaders{}, 922 mLocationsUsedForXfbExtension(0), 923 mBinaryRetrieveableHint(false), 924 mSeparable(false), 925 mNumViews(-1), 926 mDrawIDLocation(-1), 927 mBaseVertexLocation(-1), 928 mBaseInstanceLocation(-1), 929 mCachedBaseVertex(0), 930 mCachedBaseInstance(0), 931 mExecutable(new ProgramExecutable()) 932 { 933 mComputeShaderLocalSize.fill(1); 934 } 935 936 ProgramState::~ProgramState() 937 { 938 ASSERT(!hasAttachedShader()); 939 } 940 941 const std::string &ProgramState::getLabel() 942 { 943 return mLabel; 944 } 945 946 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const 947 { 948 ASSERT(shaderType != ShaderType::InvalidEnum); 949 return mAttachedShaders[shaderType]; 950 } 951 952 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const 953 { 954 return GetResourceIndexFromName(mExecutable->mUniforms, name); 955 } 956 957 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const 958 { 959 return GetResourceIndexFromName(mBufferVariables, name); 960 } 961 962 GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const 963 { 964 ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size()); 965 return mUniformLocations[location.value].index; 966 } 967 968 Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const 969 { 970 GLuint index = getUniformIndexFromLocation(location); 971 if (!isSamplerUniformIndex(index)) 972 { 973 return Optional<GLuint>::Invalid(); 974 } 975 976 return getSamplerIndexFromUniformIndex(index); 977 } 978 979 bool ProgramState::isSamplerUniformIndex(GLuint index) const 980 { 981 return mExecutable->mSamplerUniformRange.contains(index); 982 } 983 984 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const 985 { 986 ASSERT(isSamplerUniformIndex(uniformIndex)); 987 return uniformIndex - mExecutable->mSamplerUniformRange.low(); 988 } 989 990 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const 991 { 992 return mExecutable->getUniformIndexFromSamplerIndex(samplerIndex); 993 } 994 995 bool ProgramState::isImageUniformIndex(GLuint index) const 996 { 997 return mExecutable->mImageUniformRange.contains(index); 998 } 999 1000 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const 1001 { 1002 ASSERT(isImageUniformIndex(uniformIndex)); 1003 return uniformIndex - mExecutable->mImageUniformRange.low(); 1004 } 1005 1006 GLuint ProgramState::getAttributeLocation(const std::string &name) const 1007 { 1008 for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs) 1009 { 1010 if (attribute.name == name) 1011 { 1012 return attribute.location; 1013 } 1014 } 1015 1016 return static_cast<GLuint>(-1); 1017 } 1018 1019 bool ProgramState::hasAttachedShader() const 1020 { 1021 for (const Shader *shader : mAttachedShaders) 1022 { 1023 if (shader) 1024 { 1025 return true; 1026 } 1027 } 1028 return false; 1029 } 1030 1031 ShaderType ProgramState::getFirstAttachedShaderStageType() const 1032 { 1033 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages(); 1034 if (linkedStages.none()) 1035 { 1036 return ShaderType::InvalidEnum; 1037 } 1038 1039 return linkedStages.first(); 1040 } 1041 1042 ShaderType ProgramState::getLastAttachedShaderStageType() const 1043 { 1044 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages(); 1045 if (linkedStages.none()) 1046 { 1047 return ShaderType::InvalidEnum; 1048 } 1049 1050 return linkedStages.last(); 1051 } 1052 1053 ShaderType ProgramState::getAttachedTransformFeedbackStage() const 1054 { 1055 if (mAttachedShaders[ShaderType::Geometry]) 1056 { 1057 return ShaderType::Geometry; 1058 } 1059 if (mAttachedShaders[ShaderType::TessEvaluation]) 1060 { 1061 return ShaderType::TessEvaluation; 1062 } 1063 return ShaderType::Vertex; 1064 } 1065 1066 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle) 1067 : mSerial(factory->generateSerial()), 1068 mProgram(factory->createProgram(mState)), 1069 mValidated(false), 1070 mLinked(false), 1071 mDeleteStatus(false), 1072 mRefCount(0), 1073 mResourceManager(manager), 1074 mHandle(handle) 1075 { 1076 ASSERT(mProgram); 1077 1078 unlink(); 1079 } 1080 1081 Program::~Program() 1082 { 1083 ASSERT(!mProgram); 1084 } 1085 1086 void Program::onDestroy(const Context *context) 1087 { 1088 resolveLink(context); 1089 for (ShaderType shaderType : AllShaderTypes()) 1090 { 1091 if (mState.mAttachedShaders[shaderType]) 1092 { 1093 mState.mAttachedShaders[shaderType]->release(context); 1094 mState.mAttachedShaders[shaderType] = nullptr; 1095 } 1096 } 1097 1098 mProgram->destroy(context); 1099 1100 ASSERT(!mState.hasAttachedShader()); 1101 SafeDelete(mProgram); 1102 1103 delete this; 1104 } 1105 ShaderProgramID Program::id() const 1106 { 1107 ASSERT(!mLinkingState); 1108 return mHandle; 1109 } 1110 1111 angle::Result Program::setLabel(const Context *context, const std::string &label) 1112 { 1113 ASSERT(!mLinkingState); 1114 mState.mLabel = label; 1115 1116 if (mProgram) 1117 { 1118 return mProgram->onLabelUpdate(context); 1119 } 1120 return angle::Result::Continue; 1121 } 1122 1123 const std::string &Program::getLabel() const 1124 { 1125 ASSERT(!mLinkingState); 1126 return mState.mLabel; 1127 } 1128 1129 void Program::attachShader(Shader *shader) 1130 { 1131 ShaderType shaderType = shader->getType(); 1132 ASSERT(shaderType != ShaderType::InvalidEnum); 1133 1134 mState.mAttachedShaders[shaderType] = shader; 1135 mState.mAttachedShaders[shaderType]->addRef(); 1136 } 1137 1138 void Program::detachShader(const Context *context, Shader *shader) 1139 { 1140 resolveLink(context); 1141 ShaderType shaderType = shader->getType(); 1142 ASSERT(shaderType != ShaderType::InvalidEnum); 1143 1144 ASSERT(mState.mAttachedShaders[shaderType] == shader); 1145 shader->release(context); 1146 mState.mAttachedShaders[shaderType] = nullptr; 1147 } 1148 1149 int Program::getAttachedShadersCount() const 1150 { 1151 ASSERT(!mLinkingState); 1152 int numAttachedShaders = 0; 1153 for (const Shader *shader : mState.mAttachedShaders) 1154 { 1155 if (shader) 1156 { 1157 ++numAttachedShaders; 1158 } 1159 } 1160 1161 return numAttachedShaders; 1162 } 1163 1164 Shader *Program::getAttachedShader(ShaderType shaderType) const 1165 { 1166 ASSERT(!mLinkingState); 1167 return mState.getAttachedShader(shaderType); 1168 } 1169 1170 void Program::bindAttributeLocation(GLuint index, const char *name) 1171 { 1172 ASSERT(!mLinkingState); 1173 mAttributeBindings.bindLocation(index, name); 1174 } 1175 1176 void Program::bindUniformLocation(UniformLocation location, const char *name) 1177 { 1178 ASSERT(!mLinkingState); 1179 mState.mUniformLocationBindings.bindLocation(location.value, name); 1180 } 1181 1182 void Program::bindFragmentOutputLocation(GLuint index, const char *name) 1183 { 1184 mFragmentOutputLocations.bindLocation(index, name); 1185 } 1186 1187 void Program::bindFragmentOutputIndex(GLuint index, const char *name) 1188 { 1189 mFragmentOutputIndexes.bindLocation(index, name); 1190 } 1191 1192 angle::Result Program::link(const Context *context) 1193 { 1194 angle::Result result = linkImpl(context); 1195 1196 // Avoid having two ProgramExecutables if the link failed and the Program had successfully 1197 // linked previously. 1198 if (mLinkingState && mLinkingState->linkedExecutable) 1199 { 1200 mState.mExecutable = mLinkingState->linkedExecutable; 1201 } 1202 1203 return result; 1204 } 1205 1206 // The attached shaders are checked for linking errors by matching up their variables. 1207 // Uniform, input and output variables get collected. 1208 // The code gets compiled into binaries. 1209 angle::Result Program::linkImpl(const Context *context) 1210 { 1211 ASSERT(!mLinkingState); 1212 // Don't make any local variables pointing to anything within the ProgramExecutable, since 1213 // unlink() could make a new ProgramExecutable making any references/pointers invalid. 1214 auto *platform = ANGLEPlatformCurrent(); 1215 double startTime = platform->currentTime(platform); 1216 1217 // Unlink the program, but do not clear the validation-related caching yet, since we can still 1218 // use the previously linked program if linking the shaders fails. 1219 mLinked = false; 1220 1221 mState.mExecutable->resetInfoLog(); 1222 1223 // Validate we have properly attached shaders before checking the cache. 1224 if (!linkValidateShaders(context, mState.mExecutable->getInfoLog())) 1225 { 1226 return angle::Result::Continue; 1227 } 1228 1229 egl::BlobCache::Key programHash = {0}; 1230 MemoryProgramCache *cache = context->getMemoryProgramCache(); 1231 1232 // TODO: http://anglebug.com/4530: Enable program caching for separable programs 1233 if (cache && !isSeparable()) 1234 { 1235 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex()); 1236 angle::Result cacheResult = cache->getProgram(context, this, &programHash); 1237 ANGLE_TRY(cacheResult); 1238 1239 // Check explicitly for Continue, Incomplete means a cache miss 1240 if (cacheResult == angle::Result::Continue) 1241 { 1242 std::scoped_lock lock(mHistogramMutex); 1243 // Succeeded in loading the binaries in the front-end, back end may still be loading 1244 // asynchronously 1245 double delta = platform->currentTime(platform) - startTime; 1246 int us = static_cast<int>(delta * 1000000.0); 1247 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us); 1248 return angle::Result::Continue; 1249 } 1250 } 1251 1252 // Cache load failed, fall through to normal linking. 1253 unlink(); 1254 InfoLog &infoLog = mState.mExecutable->getInfoLog(); 1255 1256 // Re-link shaders after the unlink call. 1257 bool result = linkValidateShaders(context, infoLog); 1258 ASSERT(result); 1259 1260 std::unique_ptr<LinkingState> linkingState(new LinkingState()); 1261 ProgramMergedVaryings mergedVaryings; 1262 LinkingVariables linkingVariables(context, mState); 1263 ProgramLinkedResources &resources = linkingState->resources; 1264 1265 resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms, 1266 &mState.mExecutable->mShaderStorageBlocks, &mState.mBufferVariables, 1267 &mState.mExecutable->mAtomicCounterBuffers); 1268 1269 // TODO: Fix incomplete linking. http://anglebug.com/6358 1270 updateLinkedShaderStages(); 1271 1272 InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker); 1273 InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker); 1274 1275 if (mState.mAttachedShaders[ShaderType::Compute]) 1276 { 1277 GLuint combinedImageUniforms = 0; 1278 if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog)) 1279 { 1280 return angle::Result::Continue; 1281 } 1282 1283 GLuint combinedShaderStorageBlocks = 0u; 1284 if (!LinkValidateProgramInterfaceBlocks(context, 1285 mState.mExecutable->getLinkedShaderStages(), 1286 resources, infoLog, &combinedShaderStorageBlocks)) 1287 { 1288 return angle::Result::Continue; 1289 } 1290 1291 // [OpenGL ES 3.1] Chapter 8.22 Page 203: 1292 // A link error will be generated if the sum of the number of active image uniforms used in 1293 // all shaders, the number of active shader storage blocks, and the number of active 1294 // fragment shader outputs exceeds the implementation-dependent value of 1295 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES. 1296 if (combinedImageUniforms + combinedShaderStorageBlocks > 1297 static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources)) 1298 { 1299 infoLog 1300 << "The sum of the number of active image uniforms, active shader storage blocks " 1301 "and active fragment shader outputs exceeds " 1302 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES (" 1303 << context->getCaps().maxCombinedShaderOutputResources << ")"; 1304 return angle::Result::Continue; 1305 } 1306 } 1307 else 1308 { 1309 if (!linkAttributes(context, infoLog)) 1310 { 1311 return angle::Result::Continue; 1312 } 1313 1314 if (!linkVaryings(context, infoLog)) 1315 { 1316 return angle::Result::Continue; 1317 } 1318 1319 GLuint combinedImageUniforms = 0; 1320 if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog)) 1321 { 1322 return angle::Result::Continue; 1323 } 1324 1325 GLuint combinedShaderStorageBlocks = 0u; 1326 if (!LinkValidateProgramInterfaceBlocks(context, 1327 mState.mExecutable->getLinkedShaderStages(), 1328 resources, infoLog, &combinedShaderStorageBlocks)) 1329 { 1330 return angle::Result::Continue; 1331 } 1332 1333 if (!LinkValidateProgramGlobalNames(infoLog, getExecutable(), linkingVariables)) 1334 { 1335 return angle::Result::Continue; 1336 } 1337 1338 gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex]; 1339 if (vertexShader) 1340 { 1341 mState.mNumViews = vertexShader->getNumViews(context); 1342 mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits(); 1343 } 1344 1345 gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment]; 1346 if (fragmentShader) 1347 { 1348 if (!mState.mExecutable->linkValidateOutputVariables( 1349 context->getCaps(), context->getExtensions(), context->getClientVersion(), 1350 combinedImageUniforms, combinedShaderStorageBlocks, 1351 fragmentShader->getActiveOutputVariables(context), 1352 fragmentShader->getShaderVersion(context), mFragmentOutputLocations, 1353 mFragmentOutputIndexes)) 1354 { 1355 return angle::Result::Continue; 1356 } 1357 1358 mState.mExecutable->mHasDiscard = fragmentShader->hasDiscard(); 1359 mState.mExecutable->mEnablesPerSampleShading = 1360 fragmentShader->enablesPerSampleShading(); 1361 mState.mExecutable->mAdvancedBlendEquations = 1362 fragmentShader->getAdvancedBlendEquations(); 1363 mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits(); 1364 } 1365 1366 mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables); 1367 if (!mState.mExecutable->linkMergedVaryings( 1368 context, mergedVaryings, mState.mTransformFeedbackVaryingNames, linkingVariables, 1369 isSeparable(), &resources.varyingPacking)) 1370 { 1371 return angle::Result::Continue; 1372 } 1373 } 1374 1375 mState.mExecutable->saveLinkedStateInfo(context, mState); 1376 1377 mLinkingState = std::move(linkingState); 1378 mLinkingState->linkingFromBinary = false; 1379 mLinkingState->programHash = programHash; 1380 mLinkingState->linkEvent = mProgram->link(context, resources, infoLog, mergedVaryings); 1381 1382 // Must be after mProgram->link() to avoid misleading the linker about output variables. 1383 mState.updateProgramInterfaceInputs(context); 1384 mState.updateProgramInterfaceOutputs(context); 1385 1386 if (mState.mSeparable) 1387 { 1388 mLinkingState->linkedExecutable = mState.mExecutable; 1389 } 1390 1391 return angle::Result::Continue; 1392 } 1393 1394 bool Program::isLinking() const 1395 { 1396 return (mLinkingState.get() && mLinkingState->linkEvent && 1397 mLinkingState->linkEvent->isLinking()); 1398 } 1399 1400 void Program::resolveLinkImpl(const Context *context) 1401 { 1402 ASSERT(mLinkingState.get()); 1403 1404 angle::Result result = mLinkingState->linkEvent->wait(context); 1405 1406 mLinked = result == angle::Result::Continue; 1407 std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState); 1408 if (!mLinked) 1409 { 1410 mState.mExecutable->reset(false); 1411 return; 1412 } 1413 1414 if (linkingState->linkingFromBinary) 1415 { 1416 // All internal Program state is already loaded from the binary. 1417 return; 1418 } 1419 1420 initInterfaceBlockBindings(); 1421 1422 // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram, 1423 // Only successfully linked program can replace the executables. 1424 ASSERT(mLinked); 1425 1426 // Mark implementation-specific unreferenced uniforms as ignored. 1427 std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings(); 1428 mProgram->markUnusedUniformLocations(&mState.mUniformLocations, 1429 &mState.mExecutable->mSamplerBindings, imageBindings); 1430 1431 // Must be called after markUnusedUniformLocations. 1432 postResolveLink(context); 1433 1434 // Save to the program cache. 1435 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex()); 1436 MemoryProgramCache *cache = context->getMemoryProgramCache(); 1437 // TODO: http://anglebug.com/4530: Enable program caching for separable programs 1438 if (cache && !isSeparable() && 1439 (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() || 1440 !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)) 1441 { 1442 if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop) 1443 { 1444 // Don't fail linking if putting the program binary into the cache fails, the program is 1445 // still usable. 1446 ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, 1447 "Failed to save linked program to memory program cache."); 1448 } 1449 } 1450 } 1451 1452 void Program::updateLinkedShaderStages() 1453 { 1454 mState.mExecutable->resetLinkedShaderStages(); 1455 1456 for (const Shader *shader : mState.mAttachedShaders) 1457 { 1458 if (shader) 1459 { 1460 mState.mExecutable->setLinkedShaderStages(shader->getType()); 1461 } 1462 } 1463 } 1464 1465 void ProgramState::updateActiveSamplers() 1466 { 1467 mExecutable->mActiveSamplerRefCounts.fill(0); 1468 mExecutable->updateActiveSamplers(*this); 1469 } 1470 1471 void ProgramState::updateProgramInterfaceInputs(const Context *context) 1472 { 1473 const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType(); 1474 1475 if (firstAttachedShaderType == ShaderType::Vertex) 1476 { 1477 // Vertex attributes are already what we need, so nothing to do 1478 return; 1479 } 1480 1481 Shader *shader = getAttachedShader(firstAttachedShaderType); 1482 ASSERT(shader); 1483 1484 // Copy over each input varying, since the Shader could go away 1485 if (shader->getType() == ShaderType::Compute) 1486 { 1487 for (const sh::ShaderVariable &attribute : shader->getAllAttributes(context)) 1488 { 1489 // Compute Shaders have the following built-in input variables. 1490 // 1491 // in uvec3 gl_NumWorkGroups; 1492 // in uvec3 gl_WorkGroupID; 1493 // in uvec3 gl_LocalInvocationID; 1494 // in uvec3 gl_GlobalInvocationID; 1495 // in uint gl_LocalInvocationIndex; 1496 // They are all vecs or uints, so no special handling is required. 1497 mExecutable->mProgramInputs.emplace_back(attribute); 1498 } 1499 } 1500 else 1501 { 1502 for (const sh::ShaderVariable &varying : shader->getInputVaryings(context)) 1503 { 1504 UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying); 1505 } 1506 } 1507 } 1508 1509 void ProgramState::updateProgramInterfaceOutputs(const Context *context) 1510 { 1511 const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType(); 1512 1513 if (lastAttachedShaderType == ShaderType::Fragment) 1514 { 1515 // Fragment outputs are already what we need, so nothing to do 1516 return; 1517 } 1518 if (lastAttachedShaderType == ShaderType::Compute) 1519 { 1520 // If the program only contains a Compute Shader, then there are no user-defined outputs. 1521 return; 1522 } 1523 1524 Shader *shader = getAttachedShader(lastAttachedShaderType); 1525 ASSERT(shader); 1526 1527 // Copy over each output varying, since the Shader could go away 1528 for (const sh::ShaderVariable &varying : shader->getOutputVaryings(context)) 1529 { 1530 UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying); 1531 } 1532 } 1533 1534 // Returns the program object to an unlinked state, before re-linking, or at destruction 1535 void Program::unlink() 1536 { 1537 if (mLinkingState && mLinkingState->linkedExecutable) 1538 { 1539 // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of 1540 // the last successfully linked ProgramExecutable, so we don't lose any state information. 1541 mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable)); 1542 } 1543 mState.mExecutable->reset(true); 1544 1545 mState.mUniformLocations.clear(); 1546 mState.mBufferVariables.clear(); 1547 mState.mComputeShaderLocalSize.fill(1); 1548 mState.mNumViews = -1; 1549 mState.mDrawIDLocation = -1; 1550 mState.mBaseVertexLocation = -1; 1551 mState.mBaseInstanceLocation = -1; 1552 mState.mCachedBaseVertex = 0; 1553 mState.mCachedBaseInstance = 0; 1554 mState.mSpecConstUsageBits.reset(); 1555 1556 mValidated = false; 1557 1558 mLinked = false; 1559 } 1560 1561 angle::Result Program::loadBinary(const Context *context, 1562 GLenum binaryFormat, 1563 const void *binary, 1564 GLsizei length) 1565 { 1566 ASSERT(!mLinkingState); 1567 unlink(); 1568 InfoLog &infoLog = mState.mExecutable->getInfoLog(); 1569 1570 if (!angle::GetANGLEHasBinaryLoading()) 1571 { 1572 return angle::Result::Incomplete; 1573 } 1574 1575 ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE); 1576 if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) 1577 { 1578 infoLog << "Invalid program binary format."; 1579 return angle::Result::Incomplete; 1580 } 1581 1582 BinaryInputStream stream(binary, length); 1583 ANGLE_TRY(deserialize(context, stream, infoLog)); 1584 // Currently we require the full shader text to compute the program hash. 1585 // We could also store the binary in the internal program cache. 1586 1587 for (size_t uniformBlockIndex = 0; 1588 uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex) 1589 { 1590 mDirtyBits.set(uniformBlockIndex); 1591 } 1592 1593 // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple 1594 // implementations. In some implementations, a background thread is used to compile the 1595 // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with 1596 // the operation. 1597 1598 // We do not want to call LinkEvent::wait because that will cause the background thread 1599 // to finish its task before returning, thus defeating the purpose of background compilation. 1600 // We need to defer waiting on background compilation until the very last minute when we 1601 // absolutely need the results, such as when the developer binds the program or queries 1602 // for the completion status. 1603 1604 // If load returns nullptr, we know for sure that the binary is not compatible with the backend. 1605 // The loaded binary could have been read from the on-disk shader cache and be corrupted or 1606 // serialized with different revision and subsystem id than the currently loaded backend. 1607 // Returning 'Incomplete' to the caller results in link happening using the original shader 1608 // sources. 1609 angle::Result result; 1610 std::unique_ptr<LinkingState> linkingState; 1611 std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog); 1612 if (linkEvent) 1613 { 1614 linkingState = std::make_unique<LinkingState>(); 1615 linkingState->linkingFromBinary = true; 1616 linkingState->linkEvent = std::move(linkEvent); 1617 result = angle::Result::Continue; 1618 } 1619 else 1620 { 1621 result = angle::Result::Incomplete; 1622 } 1623 mLinkingState = std::move(linkingState); 1624 1625 return result; 1626 } 1627 1628 angle::Result Program::saveBinary(Context *context, 1629 GLenum *binaryFormat, 1630 void *binary, 1631 GLsizei bufSize, 1632 GLsizei *length) const 1633 { 1634 ASSERT(!mLinkingState); 1635 if (binaryFormat) 1636 { 1637 *binaryFormat = GL_PROGRAM_BINARY_ANGLE; 1638 } 1639 1640 angle::MemoryBuffer memoryBuf; 1641 ANGLE_TRY(serialize(context, &memoryBuf)); 1642 1643 GLsizei streamLength = static_cast<GLsizei>(memoryBuf.size()); 1644 const uint8_t *streamState = memoryBuf.data(); 1645 1646 if (streamLength > bufSize) 1647 { 1648 if (length) 1649 { 1650 *length = 0; 1651 } 1652 1653 // TODO: This should be moved to the validation layer but computing the size of the binary 1654 // before saving it causes the save to happen twice. It may be possible to write the binary 1655 // to a separate buffer, validate sizes and then copy it. 1656 ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION); 1657 } 1658 1659 if (binary) 1660 { 1661 char *ptr = reinterpret_cast<char *>(binary); 1662 1663 memcpy(ptr, streamState, streamLength); 1664 ptr += streamLength; 1665 1666 ASSERT(ptr - streamLength == binary); 1667 } 1668 1669 if (length) 1670 { 1671 *length = streamLength; 1672 } 1673 1674 return angle::Result::Continue; 1675 } 1676 1677 GLint Program::getBinaryLength(Context *context) const 1678 { 1679 ASSERT(!mLinkingState); 1680 if (!mLinked) 1681 { 1682 return 0; 1683 } 1684 1685 GLint length; 1686 angle::Result result = 1687 saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length); 1688 if (result != angle::Result::Continue) 1689 { 1690 return 0; 1691 } 1692 1693 return length; 1694 } 1695 1696 void Program::setBinaryRetrievableHint(bool retrievable) 1697 { 1698 ASSERT(!mLinkingState); 1699 // TODO(jmadill) : replace with dirty bits 1700 mProgram->setBinaryRetrievableHint(retrievable); 1701 mState.mBinaryRetrieveableHint = retrievable; 1702 } 1703 1704 bool Program::getBinaryRetrievableHint() const 1705 { 1706 ASSERT(!mLinkingState); 1707 return mState.mBinaryRetrieveableHint; 1708 } 1709 1710 void Program::setSeparable(bool separable) 1711 { 1712 ASSERT(!mLinkingState); 1713 // TODO(yunchao) : replace with dirty bits 1714 if (mState.mSeparable != separable) 1715 { 1716 mProgram->setSeparable(separable); 1717 mState.mSeparable = separable; 1718 } 1719 } 1720 1721 bool Program::isSeparable() const 1722 { 1723 ASSERT(!mLinkingState); 1724 return mState.mSeparable; 1725 } 1726 1727 void Program::deleteSelf(const Context *context) 1728 { 1729 ASSERT(mRefCount == 0 && mDeleteStatus); 1730 mResourceManager->deleteProgram(context, mHandle); 1731 } 1732 1733 unsigned int Program::getRefCount() const 1734 { 1735 return mRefCount; 1736 } 1737 1738 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const 1739 { 1740 ASSERT(!mLinkingState); 1741 int total = 0; 1742 1743 for (const Shader *shader : mState.mAttachedShaders) 1744 { 1745 if (shader && (total < maxCount)) 1746 { 1747 shaders[total] = shader->getHandle(); 1748 ++total; 1749 } 1750 } 1751 1752 if (count) 1753 { 1754 *count = total; 1755 } 1756 } 1757 1758 GLuint Program::getAttributeLocation(const std::string &name) const 1759 { 1760 ASSERT(!mLinkingState); 1761 return mState.getAttributeLocation(name); 1762 } 1763 1764 void Program::getActiveAttribute(GLuint index, 1765 GLsizei bufsize, 1766 GLsizei *length, 1767 GLint *size, 1768 GLenum *type, 1769 GLchar *name) const 1770 { 1771 ASSERT(!mLinkingState); 1772 if (!mLinked) 1773 { 1774 if (bufsize > 0) 1775 { 1776 name[0] = '\0'; 1777 } 1778 1779 if (length) 1780 { 1781 *length = 0; 1782 } 1783 1784 *type = GL_NONE; 1785 *size = 1; 1786 return; 1787 } 1788 1789 ASSERT(index < mState.mExecutable->getProgramInputs().size()); 1790 const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index]; 1791 1792 if (bufsize > 0) 1793 { 1794 CopyStringToBuffer(name, attrib.name, bufsize, length); 1795 } 1796 1797 // Always a single 'type' instance 1798 *size = 1; 1799 *type = attrib.type; 1800 } 1801 1802 GLint Program::getActiveAttributeCount() const 1803 { 1804 ASSERT(!mLinkingState); 1805 if (!mLinked) 1806 { 1807 return 0; 1808 } 1809 1810 return static_cast<GLint>(mState.mExecutable->getProgramInputs().size()); 1811 } 1812 1813 GLint Program::getActiveAttributeMaxLength() const 1814 { 1815 ASSERT(!mLinkingState); 1816 if (!mLinked) 1817 { 1818 return 0; 1819 } 1820 1821 size_t maxLength = 0; 1822 1823 for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs()) 1824 { 1825 maxLength = std::max(attrib.name.length() + 1, maxLength); 1826 } 1827 1828 return static_cast<GLint>(maxLength); 1829 } 1830 1831 const std::vector<sh::ShaderVariable> &Program::getAttributes() const 1832 { 1833 ASSERT(!mLinkingState); 1834 return mState.mExecutable->getProgramInputs(); 1835 } 1836 1837 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const 1838 { 1839 ASSERT(!mLinkingState); 1840 return mState.mComputeShaderLocalSize; 1841 } 1842 1843 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const 1844 { 1845 ASSERT(!mLinkingState && mState.mExecutable); 1846 return mState.mExecutable->getGeometryShaderInputPrimitiveType(); 1847 } 1848 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const 1849 { 1850 ASSERT(!mLinkingState && mState.mExecutable); 1851 return mState.mExecutable->getGeometryShaderOutputPrimitiveType(); 1852 } 1853 GLint Program::getGeometryShaderInvocations() const 1854 { 1855 ASSERT(!mLinkingState && mState.mExecutable); 1856 return mState.mExecutable->getGeometryShaderInvocations(); 1857 } 1858 GLint Program::getGeometryShaderMaxVertices() const 1859 { 1860 ASSERT(!mLinkingState && mState.mExecutable); 1861 return mState.mExecutable->getGeometryShaderMaxVertices(); 1862 } 1863 1864 GLint Program::getTessControlShaderVertices() const 1865 { 1866 ASSERT(!mLinkingState && mState.mExecutable); 1867 return mState.mExecutable->mTessControlShaderVertices; 1868 } 1869 1870 GLenum Program::getTessGenMode() const 1871 { 1872 ASSERT(!mLinkingState && mState.mExecutable); 1873 return mState.mExecutable->mTessGenMode; 1874 } 1875 1876 GLenum Program::getTessGenPointMode() const 1877 { 1878 ASSERT(!mLinkingState && mState.mExecutable); 1879 return mState.mExecutable->mTessGenPointMode; 1880 } 1881 1882 GLenum Program::getTessGenSpacing() const 1883 { 1884 ASSERT(!mLinkingState && mState.mExecutable); 1885 return mState.mExecutable->mTessGenSpacing; 1886 } 1887 1888 GLenum Program::getTessGenVertexOrder() const 1889 { 1890 ASSERT(!mLinkingState && mState.mExecutable); 1891 return mState.mExecutable->mTessGenVertexOrder; 1892 } 1893 1894 const sh::ShaderVariable &Program::getInputResource(size_t index) const 1895 { 1896 ASSERT(!mLinkingState); 1897 ASSERT(index < mState.mExecutable->getProgramInputs().size()); 1898 return mState.mExecutable->getProgramInputs()[index]; 1899 } 1900 1901 GLuint Program::getInputResourceIndex(const GLchar *name) const 1902 { 1903 ASSERT(!mLinkingState); 1904 const std::string nameString = StripLastArrayIndex(name); 1905 1906 for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++) 1907 { 1908 sh::ShaderVariable resource = getInputResource(index); 1909 if (resource.name == nameString) 1910 { 1911 return static_cast<GLuint>(index); 1912 } 1913 } 1914 1915 return GL_INVALID_INDEX; 1916 } 1917 1918 GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const 1919 { 1920 if (resource.isArray()) 1921 { 1922 return std::max(max, clampCast<GLint>((resource.name + "[0]").size())); 1923 } 1924 else 1925 { 1926 return std::max(max, clampCast<GLint>((resource.name).size())); 1927 } 1928 } 1929 1930 GLuint Program::getInputResourceMaxNameSize() const 1931 { 1932 GLint max = 0; 1933 1934 for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs()) 1935 { 1936 max = getResourceMaxNameSize(resource, max); 1937 } 1938 1939 return max; 1940 } 1941 1942 GLuint Program::getOutputResourceMaxNameSize() const 1943 { 1944 GLint max = 0; 1945 1946 for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables()) 1947 { 1948 max = getResourceMaxNameSize(resource, max); 1949 } 1950 1951 return max; 1952 } 1953 1954 GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const 1955 { 1956 if (variable.isBuiltIn()) 1957 { 1958 return GL_INVALID_INDEX; 1959 } 1960 1961 GLint location = variable.location; 1962 if (variable.isArray()) 1963 { 1964 size_t nameLengthWithoutArrayIndexOut; 1965 size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut); 1966 // The 'name' string may not contain the array notation "[0]" 1967 if (arrayIndex != GL_INVALID_INDEX) 1968 { 1969 location += arrayIndex; 1970 } 1971 } 1972 1973 return location; 1974 } 1975 1976 GLuint Program::getInputResourceLocation(const GLchar *name) const 1977 { 1978 const GLuint index = getInputResourceIndex(name); 1979 if (index == GL_INVALID_INDEX) 1980 { 1981 return index; 1982 } 1983 1984 const sh::ShaderVariable &variable = getInputResource(index); 1985 1986 return getResourceLocation(name, variable); 1987 } 1988 1989 GLuint Program::getOutputResourceLocation(const GLchar *name) const 1990 { 1991 const GLuint index = getOutputResourceIndex(name); 1992 if (index == GL_INVALID_INDEX) 1993 { 1994 return index; 1995 } 1996 1997 const sh::ShaderVariable &variable = getOutputResource(index); 1998 1999 return getResourceLocation(name, variable); 2000 } 2001 2002 GLuint Program::getOutputResourceIndex(const GLchar *name) const 2003 { 2004 ASSERT(!mLinkingState); 2005 const std::string nameString = StripLastArrayIndex(name); 2006 2007 for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++) 2008 { 2009 sh::ShaderVariable resource = getOutputResource(index); 2010 if (resource.name == nameString) 2011 { 2012 return static_cast<GLuint>(index); 2013 } 2014 } 2015 2016 return GL_INVALID_INDEX; 2017 } 2018 2019 size_t Program::getOutputResourceCount() const 2020 { 2021 ASSERT(!mLinkingState); 2022 return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0); 2023 } 2024 2025 void Program::getResourceName(const std::string name, 2026 GLsizei bufSize, 2027 GLsizei *length, 2028 GLchar *dest) const 2029 { 2030 if (length) 2031 { 2032 *length = 0; 2033 } 2034 2035 if (!mLinked) 2036 { 2037 if (bufSize > 0) 2038 { 2039 dest[0] = '\0'; 2040 } 2041 return; 2042 } 2043 2044 if (bufSize > 0) 2045 { 2046 CopyStringToBuffer(dest, name, bufSize, length); 2047 } 2048 } 2049 2050 void Program::getInputResourceName(GLuint index, 2051 GLsizei bufSize, 2052 GLsizei *length, 2053 GLchar *name) const 2054 { 2055 ASSERT(!mLinkingState); 2056 getResourceName(getInputResourceName(index), bufSize, length, name); 2057 } 2058 2059 void Program::getOutputResourceName(GLuint index, 2060 GLsizei bufSize, 2061 GLsizei *length, 2062 GLchar *name) const 2063 { 2064 ASSERT(!mLinkingState); 2065 getResourceName(getOutputResourceName(index), bufSize, length, name); 2066 } 2067 2068 void Program::getUniformResourceName(GLuint index, 2069 GLsizei bufSize, 2070 GLsizei *length, 2071 GLchar *name) const 2072 { 2073 ASSERT(!mLinkingState); 2074 ASSERT(index < mState.mExecutable->getUniforms().size()); 2075 getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name); 2076 } 2077 2078 void Program::getBufferVariableResourceName(GLuint index, 2079 GLsizei bufSize, 2080 GLsizei *length, 2081 GLchar *name) const 2082 { 2083 ASSERT(!mLinkingState); 2084 ASSERT(index < mState.mBufferVariables.size()); 2085 getResourceName(mState.mBufferVariables[index].name, bufSize, length, name); 2086 } 2087 2088 const std::string Program::getResourceName(const sh::ShaderVariable &resource) const 2089 { 2090 std::string resourceName = resource.name; 2091 2092 if (resource.isArray()) 2093 { 2094 resourceName += "[0]"; 2095 } 2096 2097 return resourceName; 2098 } 2099 2100 const std::string Program::getInputResourceName(GLuint index) const 2101 { 2102 ASSERT(!mLinkingState); 2103 const sh::ShaderVariable &resource = getInputResource(index); 2104 2105 return getResourceName(resource); 2106 } 2107 2108 const std::string Program::getOutputResourceName(GLuint index) const 2109 { 2110 ASSERT(!mLinkingState); 2111 const sh::ShaderVariable &resource = getOutputResource(index); 2112 2113 return getResourceName(resource); 2114 } 2115 2116 const sh::ShaderVariable &Program::getOutputResource(size_t index) const 2117 { 2118 ASSERT(!mLinkingState); 2119 ASSERT(index < mState.mExecutable->getOutputVariables().size()); 2120 return mState.mExecutable->getOutputVariables()[index]; 2121 } 2122 2123 const ProgramBindings &Program::getAttributeBindings() const 2124 { 2125 ASSERT(!mLinkingState); 2126 return mAttributeBindings; 2127 } 2128 const ProgramAliasedBindings &Program::getUniformLocationBindings() const 2129 { 2130 ASSERT(!mLinkingState); 2131 return mState.mUniformLocationBindings; 2132 } 2133 2134 const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const 2135 { 2136 ASSERT(!mLinkingState); 2137 return mFragmentOutputLocations; 2138 } 2139 2140 const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const 2141 { 2142 ASSERT(!mLinkingState); 2143 return mFragmentOutputIndexes; 2144 } 2145 2146 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const 2147 { 2148 ASSERT(!mLinkingState); 2149 return mState.mExecutable->getTransformFeedbackStrides(); 2150 } 2151 2152 GLint Program::getFragDataLocation(const std::string &name) const 2153 { 2154 ASSERT(!mLinkingState); 2155 GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(), 2156 mState.mExecutable->getOutputLocations(), name); 2157 if (primaryLocation != -1) 2158 { 2159 return primaryLocation; 2160 } 2161 return GetVariableLocation(mState.mExecutable->getOutputVariables(), 2162 mState.mExecutable->getSecondaryOutputLocations(), name); 2163 } 2164 2165 GLint Program::getFragDataIndex(const std::string &name) const 2166 { 2167 ASSERT(!mLinkingState); 2168 if (GetVariableLocation(mState.mExecutable->getOutputVariables(), 2169 mState.mExecutable->getOutputLocations(), name) != -1) 2170 { 2171 return 0; 2172 } 2173 if (GetVariableLocation(mState.mExecutable->getOutputVariables(), 2174 mState.mExecutable->getSecondaryOutputLocations(), name) != -1) 2175 { 2176 return 1; 2177 } 2178 return -1; 2179 } 2180 2181 void Program::getActiveUniform(GLuint index, 2182 GLsizei bufsize, 2183 GLsizei *length, 2184 GLint *size, 2185 GLenum *type, 2186 GLchar *name) const 2187 { 2188 ASSERT(!mLinkingState); 2189 if (mLinked) 2190 { 2191 // index must be smaller than getActiveUniformCount() 2192 ASSERT(index < mState.mExecutable->getUniforms().size()); 2193 const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index]; 2194 2195 if (bufsize > 0) 2196 { 2197 std::string string = uniform.name; 2198 CopyStringToBuffer(name, string, bufsize, length); 2199 } 2200 2201 *size = clampCast<GLint>(uniform.getBasicTypeElementCount()); 2202 *type = uniform.type; 2203 } 2204 else 2205 { 2206 if (bufsize > 0) 2207 { 2208 name[0] = '\0'; 2209 } 2210 2211 if (length) 2212 { 2213 *length = 0; 2214 } 2215 2216 *size = 0; 2217 *type = GL_NONE; 2218 } 2219 } 2220 2221 GLint Program::getActiveUniformCount() const 2222 { 2223 ASSERT(!mLinkingState); 2224 if (mLinked) 2225 { 2226 return static_cast<GLint>(mState.mExecutable->getUniforms().size()); 2227 } 2228 else 2229 { 2230 return 0; 2231 } 2232 } 2233 2234 size_t Program::getActiveBufferVariableCount() const 2235 { 2236 ASSERT(!mLinkingState); 2237 return mLinked ? mState.mBufferVariables.size() : 0; 2238 } 2239 2240 GLint Program::getActiveUniformMaxLength() const 2241 { 2242 ASSERT(!mLinkingState); 2243 size_t maxLength = 0; 2244 2245 if (mLinked) 2246 { 2247 for (const LinkedUniform &uniform : mState.mExecutable->getUniforms()) 2248 { 2249 if (!uniform.name.empty()) 2250 { 2251 size_t length = uniform.name.length() + 1u; 2252 if (uniform.isArray()) 2253 { 2254 length += 3; // Counting in "[0]". 2255 } 2256 maxLength = std::max(length, maxLength); 2257 } 2258 } 2259 } 2260 2261 return static_cast<GLint>(maxLength); 2262 } 2263 2264 bool Program::isValidUniformLocation(UniformLocation location) const 2265 { 2266 ASSERT(!mLinkingState); 2267 ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size())); 2268 return (location.value >= 0 && 2269 static_cast<size_t>(location.value) < mState.mUniformLocations.size() && 2270 mState.mUniformLocations[static_cast<size_t>(location.value)].used()); 2271 } 2272 2273 const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const 2274 { 2275 ASSERT(!mLinkingState); 2276 ASSERT(location.value >= 0 && 2277 static_cast<size_t>(location.value) < mState.mUniformLocations.size()); 2278 return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)]; 2279 } 2280 2281 const VariableLocation &Program::getUniformLocation(UniformLocation location) const 2282 { 2283 ASSERT(!mLinkingState); 2284 ASSERT(location.value >= 0 && 2285 static_cast<size_t>(location.value) < mState.mUniformLocations.size()); 2286 return mState.mUniformLocations[location.value]; 2287 } 2288 2289 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const 2290 { 2291 ASSERT(!mLinkingState); 2292 ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size())); 2293 return mState.mBufferVariables[index]; 2294 } 2295 2296 UniformLocation Program::getUniformLocation(const std::string &name) const 2297 { 2298 ASSERT(!mLinkingState); 2299 return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)}; 2300 } 2301 2302 GLuint Program::getUniformIndex(const std::string &name) const 2303 { 2304 ASSERT(!mLinkingState); 2305 return mState.getUniformIndexFromName(name); 2306 } 2307 2308 bool Program::shouldIgnoreUniform(UniformLocation location) const 2309 { 2310 if (location.value == -1) 2311 { 2312 return true; 2313 } 2314 2315 if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored) 2316 { 2317 return true; 2318 } 2319 2320 return false; 2321 } 2322 2323 template <typename UniformT, 2324 GLint UniformSize, 2325 void (rx::ProgramImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)> 2326 void Program::setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v) 2327 { 2328 ASSERT(!mLinkingState); 2329 if (shouldIgnoreUniform(location)) 2330 { 2331 return; 2332 } 2333 2334 const VariableLocation &locationInfo = mState.mUniformLocations[location.value]; 2335 GLsizei clampedCount = clampUniformCount(locationInfo, count, UniformSize, v); 2336 (mProgram->*SetUniformFunc)(location.value, clampedCount, v); 2337 onStateChange(angle::SubjectMessage::ProgramUniformUpdated); 2338 } 2339 2340 void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v) 2341 { 2342 setUniformGeneric<GLfloat, 1, &rx::ProgramImpl::setUniform1fv>(location, count, v); 2343 } 2344 2345 void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v) 2346 { 2347 setUniformGeneric<GLfloat, 2, &rx::ProgramImpl::setUniform2fv>(location, count, v); 2348 } 2349 2350 void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v) 2351 { 2352 setUniformGeneric<GLfloat, 3, &rx::ProgramImpl::setUniform3fv>(location, count, v); 2353 } 2354 2355 void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v) 2356 { 2357 setUniformGeneric<GLfloat, 4, &rx::ProgramImpl::setUniform4fv>(location, count, v); 2358 } 2359 2360 void Program::setUniform1iv(Context *context, 2361 UniformLocation location, 2362 GLsizei count, 2363 const GLint *v) 2364 { 2365 ASSERT(!mLinkingState); 2366 if (shouldIgnoreUniform(location)) 2367 { 2368 return; 2369 } 2370 2371 const VariableLocation &locationInfo = mState.mUniformLocations[location.value]; 2372 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v); 2373 2374 mProgram->setUniform1iv(location.value, clampedCount, v); 2375 2376 if (mState.isSamplerUniformIndex(locationInfo.index)) 2377 { 2378 updateSamplerUniform(context, locationInfo, clampedCount, v); 2379 } 2380 else 2381 { 2382 onStateChange(angle::SubjectMessage::ProgramUniformUpdated); 2383 } 2384 } 2385 2386 void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v) 2387 { 2388 setUniformGeneric<GLint, 2, &rx::ProgramImpl::setUniform2iv>(location, count, v); 2389 } 2390 2391 void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v) 2392 { 2393 setUniformGeneric<GLint, 3, &rx::ProgramImpl::setUniform3iv>(location, count, v); 2394 } 2395 2396 void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v) 2397 { 2398 setUniformGeneric<GLint, 4, &rx::ProgramImpl::setUniform4iv>(location, count, v); 2399 } 2400 2401 void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v) 2402 { 2403 setUniformGeneric<GLuint, 1, &rx::ProgramImpl::setUniform1uiv>(location, count, v); 2404 } 2405 2406 void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v) 2407 { 2408 setUniformGeneric<GLuint, 2, &rx::ProgramImpl::setUniform2uiv>(location, count, v); 2409 } 2410 2411 void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v) 2412 { 2413 setUniformGeneric<GLuint, 3, &rx::ProgramImpl::setUniform3uiv>(location, count, v); 2414 } 2415 2416 void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v) 2417 { 2418 setUniformGeneric<GLuint, 4, &rx::ProgramImpl::setUniform4uiv>(location, count, v); 2419 } 2420 2421 template < 2422 typename UniformT, 2423 GLint MatrixC, 2424 GLint MatrixR, 2425 void (rx::ProgramImpl::*SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)> 2426 void Program::setUniformMatrixGeneric(UniformLocation location, 2427 GLsizei count, 2428 GLboolean transpose, 2429 const UniformT *v) 2430 { 2431 ASSERT(!mLinkingState); 2432 if (shouldIgnoreUniform(location)) 2433 { 2434 return; 2435 } 2436 2437 GLsizei clampedCount = clampMatrixUniformCount<MatrixC, MatrixR>(location, count, transpose, v); 2438 (mProgram->*SetUniformMatrixFunc)(location.value, clampedCount, transpose, v); 2439 onStateChange(angle::SubjectMessage::ProgramUniformUpdated); 2440 } 2441 2442 void Program::setUniformMatrix2fv(UniformLocation location, 2443 GLsizei count, 2444 GLboolean transpose, 2445 const GLfloat *v) 2446 { 2447 setUniformMatrixGeneric<GLfloat, 2, 2, &rx::ProgramImpl::setUniformMatrix2fv>(location, count, 2448 transpose, v); 2449 } 2450 2451 void Program::setUniformMatrix3fv(UniformLocation location, 2452 GLsizei count, 2453 GLboolean transpose, 2454 const GLfloat *v) 2455 { 2456 setUniformMatrixGeneric<GLfloat, 3, 3, &rx::ProgramImpl::setUniformMatrix3fv>(location, count, 2457 transpose, v); 2458 } 2459 2460 void Program::setUniformMatrix4fv(UniformLocation location, 2461 GLsizei count, 2462 GLboolean transpose, 2463 const GLfloat *v) 2464 { 2465 setUniformMatrixGeneric<GLfloat, 4, 4, &rx::ProgramImpl::setUniformMatrix4fv>(location, count, 2466 transpose, v); 2467 } 2468 2469 void Program::setUniformMatrix2x3fv(UniformLocation location, 2470 GLsizei count, 2471 GLboolean transpose, 2472 const GLfloat *v) 2473 { 2474 setUniformMatrixGeneric<GLfloat, 2, 3, &rx::ProgramImpl::setUniformMatrix2x3fv>(location, count, 2475 transpose, v); 2476 } 2477 2478 void Program::setUniformMatrix2x4fv(UniformLocation location, 2479 GLsizei count, 2480 GLboolean transpose, 2481 const GLfloat *v) 2482 { 2483 setUniformMatrixGeneric<GLfloat, 2, 4, &rx::ProgramImpl::setUniformMatrix2x4fv>(location, count, 2484 transpose, v); 2485 } 2486 2487 void Program::setUniformMatrix3x2fv(UniformLocation location, 2488 GLsizei count, 2489 GLboolean transpose, 2490 const GLfloat *v) 2491 { 2492 setUniformMatrixGeneric<GLfloat, 3, 2, &rx::ProgramImpl::setUniformMatrix3x2fv>(location, count, 2493 transpose, v); 2494 } 2495 2496 void Program::setUniformMatrix3x4fv(UniformLocation location, 2497 GLsizei count, 2498 GLboolean transpose, 2499 const GLfloat *v) 2500 { 2501 setUniformMatrixGeneric<GLfloat, 3, 4, &rx::ProgramImpl::setUniformMatrix3x4fv>(location, count, 2502 transpose, v); 2503 } 2504 2505 void Program::setUniformMatrix4x2fv(UniformLocation location, 2506 GLsizei count, 2507 GLboolean transpose, 2508 const GLfloat *v) 2509 { 2510 setUniformMatrixGeneric<GLfloat, 4, 2, &rx::ProgramImpl::setUniformMatrix4x2fv>(location, count, 2511 transpose, v); 2512 } 2513 2514 void Program::setUniformMatrix4x3fv(UniformLocation location, 2515 GLsizei count, 2516 GLboolean transpose, 2517 const GLfloat *v) 2518 { 2519 setUniformMatrixGeneric<GLfloat, 4, 3, &rx::ProgramImpl::setUniformMatrix4x3fv>(location, count, 2520 transpose, v); 2521 } 2522 2523 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const 2524 { 2525 ASSERT(!mLinkingState); 2526 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index); 2527 const std::vector<GLuint> &boundTextureUnits = 2528 mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits; 2529 return (uniformLocation.arrayIndex < boundTextureUnits.size()) 2530 ? boundTextureUnits[uniformLocation.arrayIndex] 2531 : 0; 2532 } 2533 2534 GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const 2535 { 2536 ASSERT(!mLinkingState); 2537 GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index); 2538 2539 const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings(); 2540 const std::vector<GLuint> &boundImageUnits = imageBindings[imageIndex].boundImageUnits; 2541 return boundImageUnits[uniformLocation.arrayIndex]; 2542 } 2543 2544 void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const 2545 { 2546 ASSERT(!mLinkingState); 2547 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value]; 2548 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index]; 2549 2550 if (uniform.isSampler()) 2551 { 2552 *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation)); 2553 return; 2554 } 2555 else if (uniform.isImage()) 2556 { 2557 *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation)); 2558 return; 2559 } 2560 2561 const GLenum nativeType = gl::VariableComponentType(uniform.type); 2562 if (nativeType == GL_FLOAT) 2563 { 2564 mProgram->getUniformfv(context, location.value, v); 2565 } 2566 else 2567 { 2568 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type)); 2569 } 2570 } 2571 2572 void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const 2573 { 2574 ASSERT(!mLinkingState); 2575 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value]; 2576 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index]; 2577 2578 if (uniform.isSampler()) 2579 { 2580 *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation)); 2581 return; 2582 } 2583 else if (uniform.isImage()) 2584 { 2585 *v = static_cast<GLint>(getImageUniformBinding(uniformLocation)); 2586 return; 2587 } 2588 2589 const GLenum nativeType = gl::VariableComponentType(uniform.type); 2590 if (nativeType == GL_INT || nativeType == GL_BOOL) 2591 { 2592 mProgram->getUniformiv(context, location.value, v); 2593 } 2594 else 2595 { 2596 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type)); 2597 } 2598 } 2599 2600 void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const 2601 { 2602 ASSERT(!mLinkingState); 2603 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value]; 2604 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index]; 2605 2606 if (uniform.isSampler()) 2607 { 2608 *v = getSamplerUniformBinding(uniformLocation); 2609 return; 2610 } 2611 else if (uniform.isImage()) 2612 { 2613 *v = getImageUniformBinding(uniformLocation); 2614 return; 2615 } 2616 2617 const GLenum nativeType = VariableComponentType(uniform.type); 2618 if (nativeType == GL_UNSIGNED_INT) 2619 { 2620 mProgram->getUniformuiv(context, location.value, v); 2621 } 2622 else 2623 { 2624 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type)); 2625 } 2626 } 2627 2628 void Program::flagForDeletion() 2629 { 2630 ASSERT(!mLinkingState); 2631 mDeleteStatus = true; 2632 } 2633 2634 bool Program::isFlaggedForDeletion() const 2635 { 2636 ASSERT(!mLinkingState); 2637 return mDeleteStatus; 2638 } 2639 2640 void Program::validate(const Caps &caps) 2641 { 2642 ASSERT(!mLinkingState); 2643 mState.mExecutable->resetInfoLog(); 2644 InfoLog &infoLog = mState.mExecutable->getInfoLog(); 2645 2646 if (mLinked) 2647 { 2648 mValidated = ConvertToBool(mProgram->validate(caps, &infoLog)); 2649 } 2650 else 2651 { 2652 infoLog << "Program has not been successfully linked."; 2653 } 2654 } 2655 2656 bool Program::isValidated() const 2657 { 2658 ASSERT(!mLinkingState); 2659 return mValidated; 2660 } 2661 2662 void Program::getActiveUniformBlockName(const Context *context, 2663 const UniformBlockIndex blockIndex, 2664 GLsizei bufSize, 2665 GLsizei *length, 2666 GLchar *blockName) const 2667 { 2668 ASSERT(!mLinkingState); 2669 GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length, 2670 blockName); 2671 } 2672 2673 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex, 2674 GLsizei bufSize, 2675 GLsizei *length, 2676 GLchar *blockName) const 2677 { 2678 ASSERT(!mLinkingState); 2679 GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize, 2680 length, blockName); 2681 } 2682 2683 template <typename T> 2684 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const 2685 { 2686 int maxLength = 0; 2687 2688 if (mLinked) 2689 { 2690 for (const T &resource : resources) 2691 { 2692 if (!resource.name.empty()) 2693 { 2694 int length = static_cast<int>(resource.nameWithArrayIndex().length()); 2695 maxLength = std::max(length + 1, maxLength); 2696 } 2697 } 2698 } 2699 2700 return maxLength; 2701 } 2702 2703 GLint Program::getActiveUniformBlockMaxNameLength() const 2704 { 2705 ASSERT(!mLinkingState); 2706 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks()); 2707 } 2708 2709 GLint Program::getActiveShaderStorageBlockMaxNameLength() const 2710 { 2711 ASSERT(!mLinkingState); 2712 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks()); 2713 } 2714 2715 GLuint Program::getUniformBlockIndex(const std::string &name) const 2716 { 2717 ASSERT(!mLinkingState); 2718 return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name); 2719 } 2720 2721 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const 2722 { 2723 ASSERT(!mLinkingState); 2724 return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name); 2725 } 2726 2727 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const 2728 { 2729 ASSERT(!mLinkingState); 2730 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount())); 2731 return mState.mExecutable->getUniformBlocks()[index]; 2732 } 2733 2734 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const 2735 { 2736 ASSERT(!mLinkingState); 2737 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount())); 2738 return mState.mExecutable->getShaderStorageBlocks()[index]; 2739 } 2740 2741 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding) 2742 { 2743 ASSERT(!mLinkingState); 2744 mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding; 2745 mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value, 2746 uniformBlockBinding != 0); 2747 mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value); 2748 } 2749 2750 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const 2751 { 2752 ASSERT(!mLinkingState); 2753 return mState.getUniformBlockBinding(uniformBlockIndex); 2754 } 2755 2756 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const 2757 { 2758 ASSERT(!mLinkingState); 2759 return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex); 2760 } 2761 2762 void Program::setTransformFeedbackVaryings(GLsizei count, 2763 const GLchar *const *varyings, 2764 GLenum bufferMode) 2765 { 2766 ASSERT(!mLinkingState); 2767 mState.mTransformFeedbackVaryingNames.resize(count); 2768 for (GLsizei i = 0; i < count; i++) 2769 { 2770 mState.mTransformFeedbackVaryingNames[i] = varyings[i]; 2771 } 2772 2773 mState.mExecutable->mTransformFeedbackBufferMode = bufferMode; 2774 } 2775 2776 void Program::getTransformFeedbackVarying(GLuint index, 2777 GLsizei bufSize, 2778 GLsizei *length, 2779 GLsizei *size, 2780 GLenum *type, 2781 GLchar *name) const 2782 { 2783 ASSERT(!mLinkingState); 2784 if (mLinked) 2785 { 2786 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size()); 2787 const auto &var = mState.mExecutable->mLinkedTransformFeedbackVaryings[index]; 2788 std::string varName = var.nameWithArrayIndex(); 2789 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length())); 2790 if (length) 2791 { 2792 *length = lastNameIdx; 2793 } 2794 if (size) 2795 { 2796 *size = var.size(); 2797 } 2798 if (type) 2799 { 2800 *type = var.type; 2801 } 2802 if (name) 2803 { 2804 memcpy(name, varName.c_str(), lastNameIdx); 2805 name[lastNameIdx] = '\0'; 2806 } 2807 } 2808 } 2809 2810 GLsizei Program::getTransformFeedbackVaryingCount() const 2811 { 2812 ASSERT(!mLinkingState); 2813 if (mLinked) 2814 { 2815 return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size()); 2816 } 2817 else 2818 { 2819 return 0; 2820 } 2821 } 2822 2823 GLsizei Program::getTransformFeedbackVaryingMaxLength() const 2824 { 2825 ASSERT(!mLinkingState); 2826 if (mLinked) 2827 { 2828 GLsizei maxSize = 0; 2829 for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings) 2830 { 2831 maxSize = 2832 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1)); 2833 } 2834 2835 return maxSize; 2836 } 2837 else 2838 { 2839 return 0; 2840 } 2841 } 2842 2843 GLenum Program::getTransformFeedbackBufferMode() const 2844 { 2845 ASSERT(!mLinkingState); 2846 return mState.mExecutable->getTransformFeedbackBufferMode(); 2847 } 2848 2849 bool Program::linkValidateShaders(const Context *context, InfoLog &infoLog) 2850 { 2851 const ShaderMap<Shader *> &shaders = mState.mAttachedShaders; 2852 2853 bool isComputeShaderAttached = shaders[ShaderType::Compute] != nullptr; 2854 bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] || 2855 shaders[ShaderType::TessControl] || 2856 shaders[ShaderType::TessEvaluation] || 2857 shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment]; 2858 // Check whether we both have a compute and non-compute shaders attached. 2859 // If there are of both types attached, then linking should fail. 2860 // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram 2861 if (isComputeShaderAttached && isGraphicsShaderAttached) 2862 { 2863 infoLog << "Both compute and graphics shaders are attached to the same program."; 2864 return false; 2865 } 2866 2867 Optional<int> version; 2868 for (ShaderType shaderType : kAllGraphicsShaderTypes) 2869 { 2870 Shader *shader = shaders[shaderType]; 2871 ASSERT(!shader || shader->getType() == shaderType); 2872 if (!shader) 2873 { 2874 continue; 2875 } 2876 2877 if (!shader->isCompiled(context)) 2878 { 2879 infoLog << ShaderTypeToString(shaderType) << " shader is not compiled."; 2880 return false; 2881 } 2882 2883 if (!version.valid()) 2884 { 2885 version = shader->getShaderVersion(context); 2886 } 2887 else if (version != shader->getShaderVersion(context)) 2888 { 2889 infoLog << ShaderTypeToString(shaderType) 2890 << " shader version does not match other shader versions."; 2891 return false; 2892 } 2893 } 2894 2895 if (isComputeShaderAttached) 2896 { 2897 ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute); 2898 2899 mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize(context); 2900 2901 // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs 2902 // If the work group size is not specified, a link time error should occur. 2903 if (!mState.mComputeShaderLocalSize.isDeclared()) 2904 { 2905 infoLog << "Work group size is not specified."; 2906 return false; 2907 } 2908 } 2909 else 2910 { 2911 if (!isGraphicsShaderAttached) 2912 { 2913 infoLog << "No compiled shaders."; 2914 return false; 2915 } 2916 2917 bool hasVertex = shaders[ShaderType::Vertex] != nullptr; 2918 bool hasFragment = shaders[ShaderType::Fragment] != nullptr; 2919 if (!isSeparable() && (!hasVertex || !hasFragment)) 2920 { 2921 infoLog 2922 << "The program must contain objects to form both a vertex and fragment shader."; 2923 return false; 2924 } 2925 2926 bool hasTessControl = shaders[ShaderType::TessControl] != nullptr; 2927 bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr; 2928 if (!isSeparable() && (hasTessControl != hasTessEvaluation)) 2929 { 2930 infoLog << "Tessellation control and evaluation shaders must be specified together."; 2931 return false; 2932 } 2933 2934 Shader *geometryShader = shaders[ShaderType::Geometry]; 2935 if (shaders[ShaderType::Geometry]) 2936 { 2937 // [GL_EXT_geometry_shader] Chapter 7 2938 // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading 2939 // Language Specification, as well as any of the following reasons: 2940 // * One or more of the shader objects attached to <program> are not compiled 2941 // successfully. 2942 // * The shaders do not use the same shader language version. 2943 // * <program> contains objects to form a geometry shader, and 2944 // - <program> is not separable and contains no objects to form a vertex shader; or 2945 // - the input primitive type, output primitive type, or maximum output vertex count 2946 // is not specified in the compiled geometry shader object. 2947 ASSERT(geometryShader->getType() == ShaderType::Geometry); 2948 2949 Optional<PrimitiveMode> inputPrimitive = 2950 geometryShader->getGeometryShaderInputPrimitiveType(context); 2951 if (!inputPrimitive.valid()) 2952 { 2953 infoLog << "Input primitive type is not specified in the geometry shader."; 2954 return false; 2955 } 2956 2957 Optional<PrimitiveMode> outputPrimitive = 2958 geometryShader->getGeometryShaderOutputPrimitiveType(context); 2959 if (!outputPrimitive.valid()) 2960 { 2961 infoLog << "Output primitive type is not specified in the geometry shader."; 2962 return false; 2963 } 2964 2965 Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices(context); 2966 if (!maxVertices.valid()) 2967 { 2968 infoLog << "'max_vertices' is not specified in the geometry shader."; 2969 return false; 2970 } 2971 2972 mState.mExecutable->mGeometryShaderInputPrimitiveType = inputPrimitive.value(); 2973 mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value(); 2974 mState.mExecutable->mGeometryShaderMaxVertices = maxVertices.value(); 2975 mState.mExecutable->mGeometryShaderInvocations = 2976 geometryShader->getGeometryShaderInvocations(context); 2977 } 2978 2979 Shader *tessControlShader = shaders[ShaderType::TessControl]; 2980 if (tessControlShader) 2981 { 2982 int tcsShaderVertices = tessControlShader->getTessControlShaderVertices(context); 2983 if (tcsShaderVertices == 0) 2984 { 2985 // In tessellation control shader, output vertices should be specified at least 2986 // once. 2987 // > GLSL ES Version 3.20.6 spec: 2988 // > 4.4.2. Output Layout Qualifiers 2989 // > Tessellation Control Outputs 2990 // > ... 2991 // > There must be at least one layout qualifier specifying an output patch vertex 2992 // > count in any program containing a tessellation control shader. 2993 infoLog << "In Tessellation Control Shader, at least one layout qualifier " 2994 "specifying an output patch vertex count must exist."; 2995 return false; 2996 } 2997 2998 mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices; 2999 } 3000 3001 Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation]; 3002 if (tessEvaluationShader) 3003 { 3004 GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode(context); 3005 if (tesPrimitiveMode == 0) 3006 { 3007 // In tessellation evaluation shader, a primitive mode should be specified at least 3008 // once. 3009 // > GLSL ES Version 3.20.6 spec: 3010 // > 4.4.1. Input Layout Qualifiers 3011 // > Tessellation Evaluation Inputs 3012 // > ... 3013 // > The tessellation evaluation shader object in a program must declare a primitive 3014 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode 3015 // > identifiers is optional. 3016 infoLog << "The Tessellation Evaluation Shader object in a program must declare a " 3017 "primitive mode in its input layout."; 3018 return false; 3019 } 3020 3021 mState.mExecutable->mTessGenMode = tesPrimitiveMode; 3022 mState.mExecutable->mTessGenSpacing = tessEvaluationShader->getTessGenSpacing(context); 3023 mState.mExecutable->mTessGenVertexOrder = 3024 tessEvaluationShader->getTessGenVertexOrder(context); 3025 mState.mExecutable->mTessGenPointMode = 3026 tessEvaluationShader->getTessGenPointMode(context); 3027 } 3028 } 3029 3030 return true; 3031 } 3032 3033 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const 3034 { 3035 ASSERT(!mLinkingState); 3036 for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size(); 3037 ++tfIndex) 3038 { 3039 const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex]; 3040 if (tf.nameWithArrayIndex() == name) 3041 { 3042 return tfIndex; 3043 } 3044 } 3045 return GL_INVALID_INDEX; 3046 } 3047 3048 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const 3049 { 3050 ASSERT(!mLinkingState); 3051 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size()); 3052 return mState.mExecutable->mLinkedTransformFeedbackVaryings[index]; 3053 } 3054 3055 bool Program::hasDrawIDUniform() const 3056 { 3057 ASSERT(!mLinkingState); 3058 return mState.mDrawIDLocation >= 0; 3059 } 3060 3061 void Program::setDrawIDUniform(GLint drawid) 3062 { 3063 ASSERT(!mLinkingState); 3064 ASSERT(mState.mDrawIDLocation >= 0); 3065 mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid); 3066 } 3067 3068 bool Program::hasBaseVertexUniform() const 3069 { 3070 ASSERT(!mLinkingState); 3071 return mState.mBaseVertexLocation >= 0; 3072 } 3073 3074 void Program::setBaseVertexUniform(GLint baseVertex) 3075 { 3076 ASSERT(!mLinkingState); 3077 ASSERT(mState.mBaseVertexLocation >= 0); 3078 if (baseVertex == mState.mCachedBaseVertex) 3079 { 3080 return; 3081 } 3082 mState.mCachedBaseVertex = baseVertex; 3083 mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex); 3084 } 3085 3086 bool Program::hasBaseInstanceUniform() const 3087 { 3088 ASSERT(!mLinkingState); 3089 return mState.mBaseInstanceLocation >= 0; 3090 } 3091 3092 void Program::setBaseInstanceUniform(GLuint baseInstance) 3093 { 3094 ASSERT(!mLinkingState); 3095 ASSERT(mState.mBaseInstanceLocation >= 0); 3096 if (baseInstance == mState.mCachedBaseInstance) 3097 { 3098 return; 3099 } 3100 mState.mCachedBaseInstance = baseInstance; 3101 GLint baseInstanceInt = baseInstance; 3102 mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt); 3103 } 3104 3105 bool Program::linkVaryings(const Context *context, InfoLog &infoLog) const 3106 { 3107 ShaderType previousShaderType = ShaderType::InvalidEnum; 3108 for (ShaderType shaderType : kAllGraphicsShaderTypes) 3109 { 3110 Shader *currentShader = mState.mAttachedShaders[shaderType]; 3111 if (!currentShader) 3112 { 3113 continue; 3114 } 3115 3116 if (previousShaderType != ShaderType::InvalidEnum) 3117 { 3118 Shader *previousShader = mState.mAttachedShaders[previousShaderType]; 3119 const std::vector<sh::ShaderVariable> &outputVaryings = 3120 previousShader->getOutputVaryings(context); 3121 3122 if (!LinkValidateShaderInterfaceMatching( 3123 outputVaryings, currentShader->getInputVaryings(context), previousShaderType, 3124 currentShader->getType(), previousShader->getShaderVersion(context), 3125 currentShader->getShaderVersion(context), isSeparable(), infoLog)) 3126 { 3127 return false; 3128 } 3129 } 3130 previousShaderType = currentShader->getType(); 3131 } 3132 3133 // TODO: http://anglebug.com/3571 and http://anglebug.com/3572 3134 // Need to move logic of validating builtin varyings inside the for-loop above. 3135 // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance` 3136 // can be redeclared in Geometry or Tessellation shaders as well. 3137 Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex]; 3138 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment]; 3139 if (vertexShader && fragmentShader && 3140 !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(context), 3141 fragmentShader->getInputVaryings(context), 3142 vertexShader->getType(), fragmentShader->getType(), 3143 vertexShader->getShaderVersion(context), 3144 fragmentShader->getShaderVersion(context), infoLog)) 3145 { 3146 return false; 3147 } 3148 3149 return true; 3150 } 3151 3152 bool Program::linkUniforms(const Context *context, 3153 std::vector<UnusedUniform> *unusedUniformsOutOrNull, 3154 GLuint *combinedImageUniformsOut, 3155 InfoLog &infoLog) 3156 { 3157 // Initialize executable shader map. 3158 ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms; 3159 for (Shader *shader : mState.mAttachedShaders) 3160 { 3161 if (shader) 3162 { 3163 shaderUniforms[shader->getType()] = shader->getUniforms(context); 3164 } 3165 } 3166 3167 if (!mState.mExecutable->linkUniforms(context, shaderUniforms, infoLog, 3168 mState.mUniformLocationBindings, combinedImageUniformsOut, 3169 unusedUniformsOutOrNull, &mState.mUniformLocations)) 3170 { 3171 return false; 3172 } 3173 3174 if (context->getClientVersion() >= Version(3, 1)) 3175 { 3176 GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size()); 3177 3178 if (locationSize > context->getCaps().maxUniformLocations) 3179 { 3180 infoLog << "Exceeded maximum uniform location size"; 3181 return false; 3182 } 3183 } 3184 3185 return true; 3186 } 3187 3188 // Assigns locations to all attributes (except built-ins) from the bindings and program locations. 3189 bool Program::linkAttributes(const Context *context, InfoLog &infoLog) 3190 { 3191 const Caps &caps = context->getCaps(); 3192 const Limitations &limitations = context->getLimitations(); 3193 bool webglCompatibility = context->isWebGL(); 3194 int shaderVersion = -1; 3195 unsigned int usedLocations = 0; 3196 3197 Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex); 3198 3199 if (!vertexShader) 3200 { 3201 // No vertex shader, so no attributes, so nothing to do 3202 return true; 3203 } 3204 3205 shaderVersion = vertexShader->getShaderVersion(context); 3206 if (shaderVersion >= 300) 3207 { 3208 // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes - 3209 // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after 3210 // aliasing checks. 3211 mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes(context); 3212 } 3213 else 3214 { 3215 // In GLSL ES 1.00.17 we only do aliasing checks for active attributes. 3216 mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes(context); 3217 } 3218 3219 GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes); 3220 std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr); 3221 3222 // Assign locations to attributes that have a binding location and check for attribute aliasing. 3223 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs) 3224 { 3225 // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or 3226 // structures, so we don't need to worry about adjusting their names or generating entries 3227 // for each member/element (unlike uniforms for example). 3228 ASSERT(!attribute.isArray() && !attribute.isStruct()); 3229 3230 int bindingLocation = mAttributeBindings.getBinding(attribute); 3231 if (attribute.location == -1 && bindingLocation != -1) 3232 { 3233 attribute.location = bindingLocation; 3234 } 3235 3236 if (attribute.location != -1) 3237 { 3238 // Location is set by glBindAttribLocation or by location layout qualifier 3239 const int regs = VariableRegisterCount(attribute.type); 3240 3241 if (static_cast<GLuint>(regs + attribute.location) > maxAttribs) 3242 { 3243 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location 3244 << " is too big to fit"; 3245 3246 return false; 3247 } 3248 3249 for (int reg = 0; reg < regs; reg++) 3250 { 3251 const int regLocation = attribute.location + reg; 3252 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation]; 3253 3254 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error. 3255 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some 3256 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug. 3257 // In D3D 9 and 11, aliasing is not supported, so check a limitation. 3258 if (linkedAttribute) 3259 { 3260 if (shaderVersion >= 300 || webglCompatibility || 3261 limitations.noVertexAttributeAliasing) 3262 { 3263 infoLog << "Attribute '" << attribute.name << "' aliases attribute '" 3264 << linkedAttribute->name << "' at location " << regLocation; 3265 return false; 3266 } 3267 } 3268 else 3269 { 3270 usedAttribMap[regLocation] = &attribute; 3271 } 3272 3273 usedLocations |= 1 << regLocation; 3274 } 3275 } 3276 } 3277 3278 // Assign locations to attributes that don't have a binding location. 3279 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs) 3280 { 3281 // Not set by glBindAttribLocation or by location layout qualifier 3282 if (attribute.location == -1) 3283 { 3284 int regs = VariableRegisterCount(attribute.type); 3285 int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs); 3286 3287 if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs) 3288 { 3289 infoLog << "Too many attributes (" << attribute.name << ")"; 3290 return false; 3291 } 3292 3293 attribute.location = availableIndex; 3294 } 3295 } 3296 3297 ASSERT(mState.mExecutable->mAttributesTypeMask.none()); 3298 ASSERT(mState.mExecutable->mAttributesMask.none()); 3299 3300 // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier 3301 // shader versions we're only processing active attributes to begin with. 3302 if (shaderVersion >= 300) 3303 { 3304 for (auto attributeIter = mState.mExecutable->getProgramInputs().begin(); 3305 attributeIter != mState.mExecutable->getProgramInputs().end();) 3306 { 3307 if (attributeIter->active) 3308 { 3309 ++attributeIter; 3310 } 3311 else 3312 { 3313 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter); 3314 } 3315 } 3316 } 3317 3318 for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs()) 3319 { 3320 ASSERT(attribute.active); 3321 ASSERT(attribute.location != -1); 3322 unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type)); 3323 3324 unsigned int location = static_cast<unsigned int>(attribute.location); 3325 for (unsigned int r = 0; r < regs; r++) 3326 { 3327 // Built-in active program inputs don't have a bound attribute. 3328 if (!attribute.isBuiltIn()) 3329 { 3330 mState.mExecutable->mActiveAttribLocationsMask.set(location); 3331 mState.mExecutable->mMaxActiveAttribLocation = 3332 std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1); 3333 3334 ComponentType componentType = 3335 GLenumToComponentType(VariableComponentType(attribute.type)); 3336 3337 SetComponentTypeMask(componentType, location, 3338 &mState.mExecutable->mAttributesTypeMask); 3339 mState.mExecutable->mAttributesMask.set(location); 3340 3341 location++; 3342 } 3343 } 3344 } 3345 3346 return true; 3347 } 3348 3349 void Program::setUniformValuesFromBindingQualifiers() 3350 { 3351 for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange()) 3352 { 3353 const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex]; 3354 if (samplerUniform.binding != -1) 3355 { 3356 UniformLocation location = getUniformLocation(samplerUniform.name); 3357 ASSERT(location.value != -1); 3358 std::vector<GLint> boundTextureUnits; 3359 for (unsigned int elementIndex = 0; 3360 elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex) 3361 { 3362 boundTextureUnits.push_back(samplerUniform.binding + elementIndex); 3363 } 3364 3365 // Here we pass nullptr to avoid a large chain of calls that need a non-const Context. 3366 // We know it's safe not to notify the Context because this is only called after link. 3367 setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()), 3368 boundTextureUnits.data()); 3369 } 3370 } 3371 } 3372 3373 void Program::initInterfaceBlockBindings() 3374 { 3375 // Set initial bindings from shader. 3376 for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount(); 3377 blockIndex++) 3378 { 3379 InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex]; 3380 bindUniformBlock({blockIndex}, uniformBlock.binding); 3381 } 3382 } 3383 3384 void Program::updateSamplerUniform(Context *context, 3385 const VariableLocation &locationInfo, 3386 GLsizei clampedCount, 3387 const GLint *v) 3388 { 3389 ASSERT(mState.isSamplerUniformIndex(locationInfo.index)); 3390 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index); 3391 SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex]; 3392 std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits; 3393 3394 if (locationInfo.arrayIndex >= boundTextureUnits.size()) 3395 { 3396 return; 3397 } 3398 GLsizei safeUniformCount = std::min( 3399 clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex)); 3400 3401 // Update the sampler uniforms. 3402 for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex) 3403 { 3404 GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex]; 3405 GLint newTextureUnit = v[arrayIndex]; 3406 3407 if (oldTextureUnit == newTextureUnit) 3408 { 3409 continue; 3410 } 3411 3412 // Update sampler's bound textureUnit 3413 boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit; 3414 3415 // Update the reference counts. 3416 uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit]; 3417 uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit]; 3418 ASSERT(oldRefCount > 0); 3419 ASSERT(newRefCount < std::numeric_limits<uint32_t>::max()); 3420 oldRefCount--; 3421 newRefCount++; 3422 3423 // Check for binding type change. 3424 TextureType newSamplerType = mState.mExecutable->mActiveSamplerTypes[newTextureUnit]; 3425 TextureType oldSamplerType = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit]; 3426 SamplerFormat newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit]; 3427 SamplerFormat oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit]; 3428 bool newSamplerYUV = mState.mExecutable->mActiveSamplerYUV.test(newTextureUnit); 3429 3430 if (newRefCount == 1) 3431 { 3432 mState.mExecutable->setActive(newTextureUnit, samplerBinding, 3433 mState.mExecutable->getUniforms()[locationInfo.index]); 3434 } 3435 else 3436 { 3437 if (newSamplerType != samplerBinding.textureType || 3438 newSamplerYUV != IsSamplerYUVType(samplerBinding.samplerType)) 3439 { 3440 mState.mExecutable->hasSamplerTypeConflict(newTextureUnit); 3441 } 3442 3443 if (newSamplerFormat != samplerBinding.format) 3444 { 3445 mState.mExecutable->hasSamplerFormatConflict(newTextureUnit); 3446 } 3447 } 3448 3449 // Unset previously active sampler. 3450 if (oldRefCount == 0) 3451 { 3452 mState.mExecutable->setInactive(oldTextureUnit); 3453 } 3454 else 3455 { 3456 if (oldSamplerType == TextureType::InvalidEnum || 3457 oldSamplerFormat == SamplerFormat::InvalidEnum) 3458 { 3459 // Previous conflict. Check if this new change fixed the conflict. 3460 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit); 3461 } 3462 } 3463 3464 // Update the observing PPO's executable, if any. 3465 // Do this before any of the Context work, since that uses the current ProgramExecutable, 3466 // which will be the PPO's if this Program is bound to it, rather than this Program's. 3467 if (isSeparable()) 3468 { 3469 onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged); 3470 } 3471 3472 // Notify context. 3473 if (context) 3474 { 3475 context->onSamplerUniformChange(newTextureUnit); 3476 context->onSamplerUniformChange(oldTextureUnit); 3477 } 3478 } 3479 3480 // Invalidate the validation cache. 3481 getExecutable().resetCachedValidateSamplersResult(); 3482 // Inform any PPOs this Program may be bound to. 3483 onStateChange(angle::SubjectMessage::SamplerUniformsUpdated); 3484 } 3485 3486 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex) 3487 { 3488 mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex, 3489 mExecutable->mSamplerBindings); 3490 } 3491 3492 template <typename T> 3493 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo, 3494 GLsizei count, 3495 int vectorSize, 3496 const T *v) 3497 { 3498 if (count == 1) 3499 return 1; 3500 3501 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index]; 3502 3503 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array 3504 // element index used, as reported by GetActiveUniform, will be ignored by the GL." 3505 unsigned int remainingElements = 3506 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex; 3507 GLsizei maxElementCount = 3508 static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents()); 3509 3510 if (count * vectorSize > maxElementCount) 3511 { 3512 return maxElementCount / vectorSize; 3513 } 3514 3515 return count; 3516 } 3517 3518 template <size_t cols, size_t rows, typename T> 3519 GLsizei Program::clampMatrixUniformCount(UniformLocation location, 3520 GLsizei count, 3521 GLboolean transpose, 3522 const T *v) 3523 { 3524 const VariableLocation &locationInfo = mState.mUniformLocations[location.value]; 3525 3526 if (!transpose) 3527 { 3528 return clampUniformCount(locationInfo, count, cols * rows, v); 3529 } 3530 3531 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index]; 3532 3533 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array 3534 // element index used, as reported by GetActiveUniform, will be ignored by the GL." 3535 unsigned int remainingElements = 3536 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex; 3537 return std::min(count, static_cast<GLsizei>(remainingElements)); 3538 } 3539 3540 // Driver differences mean that doing the uniform value cast ourselves gives consistent results. 3541 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT. 3542 template <typename DestT> 3543 void Program::getUniformInternal(const Context *context, 3544 DestT *dataOut, 3545 UniformLocation location, 3546 GLenum nativeType, 3547 int components) const 3548 { 3549 switch (nativeType) 3550 { 3551 case GL_BOOL: 3552 { 3553 GLint tempValue[16] = {0}; 3554 mProgram->getUniformiv(context, location.value, tempValue); 3555 UniformStateQueryCastLoop<GLboolean>( 3556 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components); 3557 break; 3558 } 3559 case GL_INT: 3560 { 3561 GLint tempValue[16] = {0}; 3562 mProgram->getUniformiv(context, location.value, tempValue); 3563 UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue), 3564 components); 3565 break; 3566 } 3567 case GL_UNSIGNED_INT: 3568 { 3569 GLuint tempValue[16] = {0}; 3570 mProgram->getUniformuiv(context, location.value, tempValue); 3571 UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue), 3572 components); 3573 break; 3574 } 3575 case GL_FLOAT: 3576 { 3577 GLfloat tempValue[16] = {0}; 3578 mProgram->getUniformfv(context, location.value, tempValue); 3579 UniformStateQueryCastLoop<GLfloat>( 3580 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components); 3581 break; 3582 } 3583 default: 3584 UNREACHABLE(); 3585 break; 3586 } 3587 } 3588 3589 angle::Result Program::syncState(const Context *context) 3590 { 3591 if (mDirtyBits.any()) 3592 { 3593 ASSERT(!mLinkingState); 3594 ANGLE_TRY(mProgram->syncState(context, mDirtyBits)); 3595 mDirtyBits.reset(); 3596 } 3597 3598 return angle::Result::Continue; 3599 } 3600 3601 angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const 3602 { 3603 BinaryOutputStream stream; 3604 3605 stream.writeBytes(reinterpret_cast<const unsigned char *>(angle::GetANGLECommitHash()), 3606 angle::GetANGLECommitHashSize()); 3607 3608 // nullptr context is supported when computing binary length. 3609 if (context) 3610 { 3611 stream.writeInt(context->getClientVersion().major); 3612 stream.writeInt(context->getClientVersion().minor); 3613 } 3614 else 3615 { 3616 stream.writeInt(2); 3617 stream.writeInt(0); 3618 } 3619 3620 // Must be before mExecutable->save(), since it uses the value. 3621 stream.writeBool(mState.mSeparable); 3622 3623 mState.mExecutable->save(mState.mSeparable, &stream); 3624 3625 const auto &computeLocalSize = mState.getComputeShaderLocalSize(); 3626 3627 stream.writeInt(computeLocalSize[0]); 3628 stream.writeInt(computeLocalSize[1]); 3629 stream.writeInt(computeLocalSize[2]); 3630 3631 stream.writeInt(mState.mNumViews); 3632 stream.writeInt(mState.mSpecConstUsageBits.bits()); 3633 3634 stream.writeInt(mState.getUniformLocations().size()); 3635 for (const auto &variable : mState.getUniformLocations()) 3636 { 3637 stream.writeInt(variable.arrayIndex); 3638 stream.writeIntOrNegOne(variable.index); 3639 stream.writeBool(variable.ignored); 3640 } 3641 3642 stream.writeInt(mState.getBufferVariables().size()); 3643 for (const BufferVariable &bufferVariable : mState.getBufferVariables()) 3644 { 3645 WriteBufferVariable(&stream, bufferVariable); 3646 } 3647 3648 // Warn the app layer if saving a binary with unsupported transform feedback. 3649 if (!mState.getLinkedTransformFeedbackVaryings().empty() && 3650 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled) 3651 { 3652 ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, 3653 "Saving program binary with transform feedback, which is not supported " 3654 "on this driver."); 3655 } 3656 3657 if (context->getShareGroup()->getFrameCaptureShared()->enabled()) 3658 { 3659 // Serialize the source for each stage for re-use during capture 3660 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages()) 3661 { 3662 gl::Shader *shader = getAttachedShader(shaderType); 3663 if (shader) 3664 { 3665 stream.writeString(shader->getSourceString()); 3666 } 3667 else 3668 { 3669 // If we don't have an attached shader, which would occur if this program was 3670 // created via glProgramBinary, pull from our cached copy 3671 const angle::ProgramSources &cachedLinkedSources = 3672 context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id()); 3673 const std::string &cachedSourceString = cachedLinkedSources[shaderType]; 3674 ASSERT(!cachedSourceString.empty()); 3675 stream.writeString(cachedSourceString.c_str()); 3676 } 3677 } 3678 } 3679 3680 mProgram->save(context, &stream); 3681 3682 ASSERT(binaryOut); 3683 if (!binaryOut->resize(stream.length())) 3684 { 3685 std::stringstream sstream; 3686 sstream << "Failed to allocate enough memory to serialize a program. (" << stream.length() 3687 << " bytes )"; 3688 ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW, 3689 sstream.str().c_str()); 3690 return angle::Result::Incomplete; 3691 } 3692 memcpy(binaryOut->data(), stream.data(), stream.length()); 3693 return angle::Result::Continue; 3694 } 3695 3696 angle::Result Program::deserialize(const Context *context, 3697 BinaryInputStream &stream, 3698 InfoLog &infoLog) 3699 { 3700 std::vector<uint8_t> commitString(angle::GetANGLECommitHashSize(), 0); 3701 stream.readBytes(commitString.data(), commitString.size()); 3702 if (memcmp(commitString.data(), angle::GetANGLECommitHash(), commitString.size()) != 0) 3703 { 3704 infoLog << "Invalid program binary version."; 3705 return angle::Result::Stop; 3706 } 3707 3708 int majorVersion = stream.readInt<int>(); 3709 int minorVersion = stream.readInt<int>(); 3710 if (majorVersion != context->getClientMajorVersion() || 3711 minorVersion != context->getClientMinorVersion()) 3712 { 3713 infoLog << "Cannot load program binaries across different ES context versions."; 3714 return angle::Result::Stop; 3715 } 3716 3717 // Must be before mExecutable->load(), since it uses the value. 3718 mState.mSeparable = stream.readBool(); 3719 3720 mState.mExecutable->load(mState.mSeparable, &stream); 3721 3722 mState.mComputeShaderLocalSize[0] = stream.readInt<int>(); 3723 mState.mComputeShaderLocalSize[1] = stream.readInt<int>(); 3724 mState.mComputeShaderLocalSize[2] = stream.readInt<int>(); 3725 3726 mState.mNumViews = stream.readInt<int>(); 3727 3728 static_assert(sizeof(mState.mSpecConstUsageBits.bits()) == sizeof(uint32_t)); 3729 mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>()); 3730 3731 const size_t uniformIndexCount = stream.readInt<size_t>(); 3732 ASSERT(mState.mUniformLocations.empty()); 3733 for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex) 3734 { 3735 VariableLocation variable; 3736 stream.readInt(&variable.arrayIndex); 3737 stream.readInt(&variable.index); 3738 stream.readBool(&variable.ignored); 3739 3740 mState.mUniformLocations.push_back(variable); 3741 } 3742 3743 size_t bufferVariableCount = stream.readInt<size_t>(); 3744 ASSERT(mState.mBufferVariables.empty()); 3745 for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex) 3746 { 3747 BufferVariable bufferVariable; 3748 LoadBufferVariable(&stream, &bufferVariable); 3749 mState.mBufferVariables.push_back(bufferVariable); 3750 } 3751 3752 static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8, 3753 "Too many shader types"); 3754 3755 // Reject programs that use transform feedback varyings if the hardware cannot support them. 3756 if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 && 3757 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled) 3758 { 3759 infoLog << "Current driver does not support transform feedback in binary programs."; 3760 return angle::Result::Stop; 3761 } 3762 3763 if (!mState.mAttachedShaders[ShaderType::Compute]) 3764 { 3765 mState.mExecutable->updateTransformFeedbackStrides(); 3766 } 3767 3768 postResolveLink(context); 3769 mState.mExecutable->updateCanDrawWith(); 3770 3771 if (context->getShareGroup()->getFrameCaptureShared()->enabled()) 3772 { 3773 // Extract the source for each stage from the program binary 3774 angle::ProgramSources sources; 3775 3776 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages()) 3777 { 3778 std::string shaderSource = stream.readString(); 3779 ASSERT(shaderSource.length() > 0); 3780 sources[shaderType] = std::move(shaderSource); 3781 } 3782 3783 // Store it for use during mid-execution capture 3784 context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(), 3785 std::move(sources)); 3786 } 3787 3788 return angle::Result::Continue; 3789 } 3790 3791 void Program::postResolveLink(const gl::Context *context) 3792 { 3793 mState.updateActiveSamplers(); 3794 mState.mExecutable->mActiveImageShaderBits.fill({}); 3795 mState.mExecutable->updateActiveImages(getExecutable()); 3796 3797 setUniformValuesFromBindingQualifiers(); 3798 3799 if (context->getExtensions().multiDrawANGLE) 3800 { 3801 mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value; 3802 } 3803 3804 if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE) 3805 { 3806 mState.mBaseVertexLocation = getUniformLocation("gl_BaseVertex").value; 3807 mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value; 3808 } 3809 } 3810 } // namespace gl