ProgramExecutable.cpp (69227B)
1 // 2 // Copyright 2020 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 // ProgramExecutable.cpp: Collects the interfaces common to both Programs and 7 // ProgramPipelines in order to execute/draw with either. 8 9 #include "libANGLE/ProgramExecutable.h" 10 11 #include "common/string_utils.h" 12 #include "libANGLE/Context.h" 13 #include "libANGLE/Program.h" 14 #include "libANGLE/Shader.h" 15 16 namespace gl 17 { 18 namespace 19 { 20 bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name) 21 { 22 std::vector<unsigned int> subscripts; 23 std::string baseName = ParseResourceName(name, &subscripts); 24 for (const std::string &nameInSet : nameSet) 25 { 26 std::vector<unsigned int> arrayIndices; 27 std::string arrayName = ParseResourceName(nameInSet, &arrayIndices); 28 if (baseName == arrayName && 29 (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices)) 30 { 31 return true; 32 } 33 } 34 return false; 35 } 36 37 // Find the matching varying or field by name. 38 const sh::ShaderVariable *FindOutputVaryingOrField(const ProgramMergedVaryings &varyings, 39 ShaderType stage, 40 const std::string &name) 41 { 42 const sh::ShaderVariable *var = nullptr; 43 for (const ProgramVaryingRef &ref : varyings) 44 { 45 if (ref.frontShaderStage != stage) 46 { 47 continue; 48 } 49 50 const sh::ShaderVariable *varying = ref.get(stage); 51 if (varying->name == name) 52 { 53 var = varying; 54 break; 55 } 56 GLuint fieldIndex = 0; 57 var = varying->findField(name, &fieldIndex); 58 if (var != nullptr) 59 { 60 break; 61 } 62 } 63 return var; 64 } 65 66 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations, 67 unsigned int baseLocation, 68 unsigned int elementCount, 69 const std::vector<VariableLocation> &reservedLocations, 70 unsigned int variableIndex) 71 { 72 if (baseLocation + elementCount > outputLocations.size()) 73 { 74 elementCount = baseLocation < outputLocations.size() 75 ? static_cast<unsigned int>(outputLocations.size() - baseLocation) 76 : 0; 77 } 78 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++) 79 { 80 const unsigned int location = baseLocation + elementIndex; 81 if (outputLocations[location].used()) 82 { 83 VariableLocation locationInfo(elementIndex, variableIndex); 84 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) == 85 reservedLocations.end()) 86 { 87 return true; 88 } 89 } 90 } 91 return false; 92 } 93 94 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations, 95 unsigned int baseLocation, 96 unsigned int elementCount, 97 const std::vector<VariableLocation> &reservedLocations, 98 unsigned int variableIndex, 99 sh::ShaderVariable &outputVariable) 100 { 101 if (baseLocation + elementCount > outputLocations.size()) 102 { 103 outputLocations.resize(baseLocation + elementCount); 104 } 105 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++) 106 { 107 VariableLocation locationInfo(elementIndex, variableIndex); 108 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) == 109 reservedLocations.end()) 110 { 111 outputVariable.location = baseLocation; 112 const unsigned int location = baseLocation + elementIndex; 113 outputLocations[location] = locationInfo; 114 } 115 } 116 } 117 118 int GetOutputLocationForLink(const ProgramAliasedBindings &fragmentOutputLocations, 119 const sh::ShaderVariable &outputVariable) 120 { 121 if (outputVariable.location != -1) 122 { 123 return outputVariable.location; 124 } 125 int apiLocation = fragmentOutputLocations.getBinding(outputVariable); 126 if (apiLocation != -1) 127 { 128 return apiLocation; 129 } 130 return -1; 131 } 132 133 bool IsOutputSecondaryForLink(const ProgramAliasedBindings &fragmentOutputIndexes, 134 const sh::ShaderVariable &outputVariable) 135 { 136 if (outputVariable.index != -1) 137 { 138 ASSERT(outputVariable.index == 0 || outputVariable.index == 1); 139 return (outputVariable.index == 1); 140 } 141 int apiIndex = fragmentOutputIndexes.getBinding(outputVariable); 142 if (apiIndex != -1) 143 { 144 // Index layout qualifier from the shader takes precedence, so the index from the API is 145 // checked only if the index was not set in the shader. This is not specified in the EXT 146 // spec, but is specified in desktop OpenGL specs. 147 return (apiIndex == 1); 148 } 149 // EXT_blend_func_extended: Outputs get index 0 by default. 150 return false; 151 } 152 153 RangeUI AddUniforms(const ShaderMap<Program *> &programs, 154 ShaderBitSet activeShaders, 155 std::vector<LinkedUniform> &outputUniforms, 156 const std::function<RangeUI(const ProgramState &)> &getRange) 157 { 158 unsigned int startRange = static_cast<unsigned int>(outputUniforms.size()); 159 for (ShaderType shaderType : activeShaders) 160 { 161 const ProgramState &programState = programs[shaderType]->getState(); 162 const std::vector<LinkedUniform> &programUniforms = programState.getUniforms(); 163 const RangeUI uniformRange = getRange(programState); 164 165 outputUniforms.insert(outputUniforms.end(), programUniforms.begin() + uniformRange.low(), 166 programUniforms.begin() + uniformRange.high()); 167 } 168 return RangeUI(startRange, static_cast<unsigned int>(outputUniforms.size())); 169 } 170 171 template <typename BlockT> 172 void AppendActiveBlocks(ShaderType shaderType, 173 const std::vector<BlockT> &blocksIn, 174 std::vector<BlockT> &blocksOut) 175 { 176 for (const BlockT &block : blocksIn) 177 { 178 if (block.isActive(shaderType)) 179 { 180 blocksOut.push_back(block); 181 } 182 } 183 } 184 } // anonymous namespace 185 186 ProgramExecutable::ProgramExecutable() 187 : mMaxActiveAttribLocation(0), 188 mAttributesTypeMask(0), 189 mAttributesMask(0), 190 mActiveSamplerRefCounts{}, 191 mCanDrawWith(false), 192 mYUVOutput(false), 193 mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS), 194 mDefaultUniformRange(0, 0), 195 mSamplerUniformRange(0, 0), 196 mImageUniformRange(0, 0), 197 mAtomicCounterUniformRange(0, 0), 198 mFragmentInoutRange(0, 0), 199 mHasDiscard(false), 200 mEnablesPerSampleShading(false), 201 // [GL_EXT_geometry_shader] Table 20.22 202 mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles), 203 mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip), 204 mGeometryShaderInvocations(1), 205 mGeometryShaderMaxVertices(0), 206 mTessControlShaderVertices(0), 207 mTessGenMode(GL_NONE), 208 mTessGenSpacing(GL_NONE), 209 mTessGenVertexOrder(GL_NONE), 210 mTessGenPointMode(GL_NONE) 211 { 212 reset(true); 213 } 214 215 ProgramExecutable::ProgramExecutable(const ProgramExecutable &other) 216 : mLinkedShaderStages(other.mLinkedShaderStages), 217 mActiveAttribLocationsMask(other.mActiveAttribLocationsMask), 218 mMaxActiveAttribLocation(other.mMaxActiveAttribLocation), 219 mAttributesTypeMask(other.mAttributesTypeMask), 220 mAttributesMask(other.mAttributesMask), 221 mActiveSamplersMask(other.mActiveSamplersMask), 222 mActiveSamplerRefCounts(other.mActiveSamplerRefCounts), 223 mActiveSamplerTypes(other.mActiveSamplerTypes), 224 mActiveSamplerYUV(other.mActiveSamplerYUV), 225 mActiveSamplerFormats(other.mActiveSamplerFormats), 226 mActiveSamplerShaderBits(other.mActiveSamplerShaderBits), 227 mActiveImagesMask(other.mActiveImagesMask), 228 mActiveImageShaderBits(other.mActiveImageShaderBits), 229 mCanDrawWith(other.mCanDrawWith), 230 mOutputVariables(other.mOutputVariables), 231 mOutputLocations(other.mOutputLocations), 232 mSecondaryOutputLocations(other.mSecondaryOutputLocations), 233 mYUVOutput(other.mYUVOutput), 234 mProgramInputs(other.mProgramInputs), 235 mLinkedTransformFeedbackVaryings(other.mLinkedTransformFeedbackVaryings), 236 mTransformFeedbackStrides(other.mTransformFeedbackStrides), 237 mTransformFeedbackBufferMode(other.mTransformFeedbackBufferMode), 238 mUniforms(other.mUniforms), 239 mDefaultUniformRange(other.mDefaultUniformRange), 240 mSamplerUniformRange(other.mSamplerUniformRange), 241 mImageUniformRange(other.mImageUniformRange), 242 mAtomicCounterUniformRange(other.mAtomicCounterUniformRange), 243 mUniformBlocks(other.mUniformBlocks), 244 mActiveUniformBlockBindings(other.mActiveUniformBlockBindings), 245 mAtomicCounterBuffers(other.mAtomicCounterBuffers), 246 mShaderStorageBlocks(other.mShaderStorageBlocks), 247 mFragmentInoutRange(other.mFragmentInoutRange), 248 mHasDiscard(other.mHasDiscard), 249 mEnablesPerSampleShading(other.mEnablesPerSampleShading), 250 mAdvancedBlendEquations(other.mAdvancedBlendEquations) 251 { 252 reset(true); 253 } 254 255 ProgramExecutable::~ProgramExecutable() = default; 256 257 void ProgramExecutable::reset(bool clearInfoLog) 258 { 259 if (clearInfoLog) 260 { 261 resetInfoLog(); 262 } 263 mActiveAttribLocationsMask.reset(); 264 mAttributesTypeMask.reset(); 265 mAttributesMask.reset(); 266 mMaxActiveAttribLocation = 0; 267 268 mActiveSamplersMask.reset(); 269 mActiveSamplerRefCounts = {}; 270 mActiveSamplerTypes.fill(TextureType::InvalidEnum); 271 mActiveSamplerYUV.reset(); 272 mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum); 273 274 mActiveImagesMask.reset(); 275 276 mProgramInputs.clear(); 277 mLinkedTransformFeedbackVaryings.clear(); 278 mTransformFeedbackStrides.clear(); 279 mUniforms.clear(); 280 mUniformBlocks.clear(); 281 mActiveUniformBlockBindings.reset(); 282 mShaderStorageBlocks.clear(); 283 mAtomicCounterBuffers.clear(); 284 mOutputVariables.clear(); 285 mOutputLocations.clear(); 286 mActiveOutputVariablesMask.reset(); 287 mSecondaryOutputLocations.clear(); 288 mYUVOutput = false; 289 mSamplerBindings.clear(); 290 mImageBindings.clear(); 291 292 mDefaultUniformRange = RangeUI(0, 0); 293 mSamplerUniformRange = RangeUI(0, 0); 294 mImageUniformRange = RangeUI(0, 0); 295 mAtomicCounterUniformRange = RangeUI(0, 0); 296 297 mFragmentInoutRange = RangeUI(0, 0); 298 mHasDiscard = false; 299 mEnablesPerSampleShading = false; 300 mAdvancedBlendEquations.reset(); 301 302 mGeometryShaderInputPrimitiveType = PrimitiveMode::Triangles; 303 mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip; 304 mGeometryShaderInvocations = 1; 305 mGeometryShaderMaxVertices = 0; 306 307 mTessControlShaderVertices = 0; 308 mTessGenMode = GL_NONE; 309 mTessGenSpacing = GL_NONE; 310 mTessGenVertexOrder = GL_NONE; 311 mTessGenPointMode = GL_NONE; 312 313 mOutputVariableTypes.clear(); 314 mDrawBufferTypeMask.reset(); 315 } 316 317 void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream) 318 { 319 static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8, 320 "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and " 321 "mask fit into 32 bits each"); 322 mAttributesTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>()); 323 mAttributesMask = gl::AttributesMask(stream->readInt<uint32_t>()); 324 mActiveAttribLocationsMask = gl::AttributesMask(stream->readInt<uint32_t>()); 325 mMaxActiveAttribLocation = stream->readInt<unsigned int>(); 326 327 unsigned int fragmentInoutRangeLow = stream->readInt<uint32_t>(); 328 unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>(); 329 mFragmentInoutRange = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh); 330 331 mHasDiscard = stream->readBool(); 332 mEnablesPerSampleShading = stream->readBool(); 333 334 static_assert(sizeof(mAdvancedBlendEquations.bits()) == sizeof(uint32_t)); 335 mAdvancedBlendEquations = BlendEquationBitSet(stream->readInt<uint32_t>()); 336 337 mLinkedShaderStages = ShaderBitSet(stream->readInt<uint8_t>()); 338 339 mGeometryShaderInputPrimitiveType = stream->readEnum<PrimitiveMode>(); 340 mGeometryShaderOutputPrimitiveType = stream->readEnum<PrimitiveMode>(); 341 mGeometryShaderInvocations = stream->readInt<int>(); 342 mGeometryShaderMaxVertices = stream->readInt<int>(); 343 344 mTessControlShaderVertices = stream->readInt<int>(); 345 mTessGenMode = stream->readInt<GLenum>(); 346 mTessGenSpacing = stream->readInt<GLenum>(); 347 mTessGenVertexOrder = stream->readInt<GLenum>(); 348 mTessGenPointMode = stream->readInt<GLenum>(); 349 350 size_t attribCount = stream->readInt<size_t>(); 351 ASSERT(getProgramInputs().empty()); 352 for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) 353 { 354 sh::ShaderVariable attrib; 355 LoadShaderVar(stream, &attrib); 356 attrib.location = stream->readInt<int>(); 357 mProgramInputs.push_back(attrib); 358 } 359 360 size_t uniformCount = stream->readInt<size_t>(); 361 ASSERT(getUniforms().empty()); 362 for (size_t uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex) 363 { 364 LinkedUniform uniform; 365 LoadShaderVar(stream, &uniform); 366 367 uniform.bufferIndex = stream->readInt<int>(); 368 LoadBlockMemberInfo(stream, &uniform.blockInfo); 369 370 stream->readIntVector<unsigned int>(&uniform.outerArraySizes); 371 uniform.outerArrayOffset = stream->readInt<unsigned int>(); 372 373 uniform.typeInfo = &GetUniformTypeInfo(uniform.type); 374 375 // Active shader info 376 for (ShaderType shaderType : gl::AllShaderTypes()) 377 { 378 uniform.setActive(shaderType, stream->readBool()); 379 } 380 381 mUniforms.push_back(uniform); 382 } 383 384 size_t uniformBlockCount = stream->readInt<size_t>(); 385 ASSERT(getUniformBlocks().empty()); 386 for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) 387 { 388 InterfaceBlock uniformBlock; 389 LoadInterfaceBlock(stream, &uniformBlock); 390 mUniformBlocks.push_back(uniformBlock); 391 392 mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0); 393 } 394 395 size_t shaderStorageBlockCount = stream->readInt<size_t>(); 396 ASSERT(getShaderStorageBlocks().empty()); 397 for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount; 398 ++shaderStorageBlockIndex) 399 { 400 InterfaceBlock shaderStorageBlock; 401 LoadInterfaceBlock(stream, &shaderStorageBlock); 402 mShaderStorageBlocks.push_back(shaderStorageBlock); 403 } 404 405 size_t atomicCounterBufferCount = stream->readInt<size_t>(); 406 ASSERT(getAtomicCounterBuffers().empty()); 407 for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex) 408 { 409 AtomicCounterBuffer atomicCounterBuffer; 410 LoadShaderVariableBuffer(stream, &atomicCounterBuffer); 411 412 mAtomicCounterBuffers.push_back(atomicCounterBuffer); 413 } 414 415 size_t transformFeedbackVaryingCount = stream->readInt<size_t>(); 416 ASSERT(mLinkedTransformFeedbackVaryings.empty()); 417 for (size_t transformFeedbackVaryingIndex = 0; 418 transformFeedbackVaryingIndex < transformFeedbackVaryingCount; 419 ++transformFeedbackVaryingIndex) 420 { 421 sh::ShaderVariable varying; 422 stream->readIntVector<unsigned int>(&varying.arraySizes); 423 stream->readInt(&varying.type); 424 stream->readString(&varying.name); 425 426 GLuint arrayIndex = stream->readInt<GLuint>(); 427 428 mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex); 429 } 430 431 mTransformFeedbackBufferMode = stream->readInt<GLint>(); 432 433 size_t outputCount = stream->readInt<size_t>(); 434 ASSERT(getOutputVariables().empty()); 435 for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex) 436 { 437 sh::ShaderVariable output; 438 LoadShaderVar(stream, &output); 439 output.location = stream->readInt<int>(); 440 output.index = stream->readInt<int>(); 441 mOutputVariables.push_back(output); 442 } 443 444 size_t outputVarCount = stream->readInt<size_t>(); 445 ASSERT(getOutputLocations().empty()); 446 for (size_t outputIndex = 0; outputIndex < outputVarCount; ++outputIndex) 447 { 448 VariableLocation locationData; 449 stream->readInt(&locationData.arrayIndex); 450 stream->readInt(&locationData.index); 451 stream->readBool(&locationData.ignored); 452 mOutputLocations.push_back(locationData); 453 } 454 455 mActiveOutputVariablesMask = 456 gl::DrawBufferMask(stream->readInt<gl::DrawBufferMask::value_type>()); 457 458 size_t outputTypeCount = stream->readInt<size_t>(); 459 for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex) 460 { 461 mOutputVariableTypes.push_back(stream->readInt<GLenum>()); 462 } 463 464 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t), 465 "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit " 466 "into 32 bits each"); 467 mDrawBufferTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>()); 468 469 stream->readBool(&mYUVOutput); 470 471 size_t secondaryOutputVarCount = stream->readInt<size_t>(); 472 ASSERT(getSecondaryOutputLocations().empty()); 473 for (size_t outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex) 474 { 475 VariableLocation locationData; 476 stream->readInt(&locationData.arrayIndex); 477 stream->readInt(&locationData.index); 478 stream->readBool(&locationData.ignored); 479 mSecondaryOutputLocations.push_back(locationData); 480 } 481 482 unsigned int defaultUniformRangeLow = stream->readInt<unsigned int>(); 483 unsigned int defaultUniformRangeHigh = stream->readInt<unsigned int>(); 484 mDefaultUniformRange = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh); 485 486 unsigned int samplerRangeLow = stream->readInt<unsigned int>(); 487 unsigned int samplerRangeHigh = stream->readInt<unsigned int>(); 488 mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh); 489 490 size_t samplerCount = stream->readInt<size_t>(); 491 for (size_t samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex) 492 { 493 TextureType textureType = stream->readEnum<TextureType>(); 494 GLenum samplerType = stream->readInt<GLenum>(); 495 SamplerFormat format = stream->readEnum<SamplerFormat>(); 496 size_t bindingCount = stream->readInt<size_t>(); 497 mSamplerBindings.emplace_back(textureType, samplerType, format, bindingCount); 498 } 499 500 unsigned int imageRangeLow = stream->readInt<unsigned int>(); 501 unsigned int imageRangeHigh = stream->readInt<unsigned int>(); 502 mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh); 503 504 size_t imageBindingCount = stream->readInt<size_t>(); 505 for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex) 506 { 507 size_t elementCount = stream->readInt<size_t>(); 508 TextureType textureType = static_cast<TextureType>(stream->readInt<unsigned int>()); 509 ImageBinding imageBinding(elementCount, textureType); 510 for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex) 511 { 512 imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>(); 513 } 514 mImageBindings.emplace_back(imageBinding); 515 } 516 517 unsigned int atomicCounterRangeLow = stream->readInt<unsigned int>(); 518 unsigned int atomicCounterRangeHigh = stream->readInt<unsigned int>(); 519 mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh); 520 521 // These values are currently only used by PPOs, so only load them when the program is marked 522 // separable to save memory. 523 if (isSeparable) 524 { 525 for (ShaderType shaderType : mLinkedShaderStages) 526 { 527 mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>()); 528 for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType]) 529 { 530 LoadShaderVar(stream, &variable); 531 } 532 mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>()); 533 for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType]) 534 { 535 LoadShaderVar(stream, &variable); 536 } 537 mLinkedUniforms[shaderType].resize(stream->readInt<size_t>()); 538 for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType]) 539 { 540 LoadShaderVar(stream, &variable); 541 } 542 mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>()); 543 for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType]) 544 { 545 LoadShInterfaceBlock(stream, &shaderStorageBlock); 546 } 547 mLinkedShaderVersions[shaderType] = stream->readInt<int>(); 548 } 549 } 550 } 551 552 void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) const 553 { 554 static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8, 555 "All bits of mAttributesTypeMask types and mask fit into 32 bits each"); 556 stream->writeInt(static_cast<uint32_t>(mAttributesTypeMask.to_ulong())); 557 stream->writeInt(static_cast<uint32_t>(mAttributesMask.to_ulong())); 558 stream->writeInt(static_cast<uint32_t>(mActiveAttribLocationsMask.to_ulong())); 559 stream->writeInt(mMaxActiveAttribLocation); 560 561 stream->writeInt(mFragmentInoutRange.low()); 562 stream->writeInt(mFragmentInoutRange.high()); 563 564 stream->writeBool(mHasDiscard); 565 stream->writeBool(mEnablesPerSampleShading); 566 stream->writeInt(mAdvancedBlendEquations.bits()); 567 568 stream->writeInt(mLinkedShaderStages.bits()); 569 570 ASSERT(mGeometryShaderInvocations >= 1 && mGeometryShaderMaxVertices >= 0); 571 stream->writeEnum(mGeometryShaderInputPrimitiveType); 572 stream->writeEnum(mGeometryShaderOutputPrimitiveType); 573 stream->writeInt(mGeometryShaderInvocations); 574 stream->writeInt(mGeometryShaderMaxVertices); 575 576 stream->writeInt(mTessControlShaderVertices); 577 stream->writeInt(mTessGenMode); 578 stream->writeInt(mTessGenSpacing); 579 stream->writeInt(mTessGenVertexOrder); 580 stream->writeInt(mTessGenPointMode); 581 582 stream->writeInt(getProgramInputs().size()); 583 for (const sh::ShaderVariable &attrib : getProgramInputs()) 584 { 585 WriteShaderVar(stream, attrib); 586 stream->writeInt(attrib.location); 587 } 588 589 stream->writeInt(getUniforms().size()); 590 for (const LinkedUniform &uniform : getUniforms()) 591 { 592 WriteShaderVar(stream, uniform); 593 594 stream->writeInt(uniform.bufferIndex); 595 WriteBlockMemberInfo(stream, uniform.blockInfo); 596 597 stream->writeIntVector(uniform.outerArraySizes); 598 stream->writeInt(uniform.outerArrayOffset); 599 600 // Active shader info 601 for (ShaderType shaderType : gl::AllShaderTypes()) 602 { 603 stream->writeBool(uniform.isActive(shaderType)); 604 } 605 } 606 607 stream->writeInt(getUniformBlocks().size()); 608 for (const InterfaceBlock &uniformBlock : getUniformBlocks()) 609 { 610 WriteInterfaceBlock(stream, uniformBlock); 611 } 612 613 stream->writeInt(getShaderStorageBlocks().size()); 614 for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks()) 615 { 616 WriteInterfaceBlock(stream, shaderStorageBlock); 617 } 618 619 stream->writeInt(mAtomicCounterBuffers.size()); 620 for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers()) 621 { 622 WriteShaderVariableBuffer(stream, atomicCounterBuffer); 623 } 624 625 stream->writeInt(getLinkedTransformFeedbackVaryings().size()); 626 for (const auto &var : getLinkedTransformFeedbackVaryings()) 627 { 628 stream->writeIntVector(var.arraySizes); 629 stream->writeInt(var.type); 630 stream->writeString(var.name); 631 632 stream->writeIntOrNegOne(var.arrayIndex); 633 } 634 635 stream->writeInt(getTransformFeedbackBufferMode()); 636 637 stream->writeInt(getOutputVariables().size()); 638 for (const sh::ShaderVariable &output : getOutputVariables()) 639 { 640 WriteShaderVar(stream, output); 641 stream->writeInt(output.location); 642 stream->writeInt(output.index); 643 } 644 645 stream->writeInt(getOutputLocations().size()); 646 for (const auto &outputVar : getOutputLocations()) 647 { 648 stream->writeInt(outputVar.arrayIndex); 649 stream->writeIntOrNegOne(outputVar.index); 650 stream->writeBool(outputVar.ignored); 651 } 652 653 stream->writeInt(static_cast<int>(mActiveOutputVariablesMask.to_ulong())); 654 655 stream->writeInt(mOutputVariableTypes.size()); 656 for (const auto &outputVariableType : mOutputVariableTypes) 657 { 658 stream->writeInt(outputVariableType); 659 } 660 661 static_assert( 662 IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t), 663 "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits"); 664 stream->writeInt(static_cast<int>(mDrawBufferTypeMask.to_ulong())); 665 666 stream->writeBool(mYUVOutput); 667 668 stream->writeInt(getSecondaryOutputLocations().size()); 669 for (const auto &outputVar : getSecondaryOutputLocations()) 670 { 671 stream->writeInt(outputVar.arrayIndex); 672 stream->writeIntOrNegOne(outputVar.index); 673 stream->writeBool(outputVar.ignored); 674 } 675 676 stream->writeInt(getDefaultUniformRange().low()); 677 stream->writeInt(getDefaultUniformRange().high()); 678 679 stream->writeInt(getSamplerUniformRange().low()); 680 stream->writeInt(getSamplerUniformRange().high()); 681 682 stream->writeInt(getSamplerBindings().size()); 683 for (const auto &samplerBinding : getSamplerBindings()) 684 { 685 stream->writeEnum(samplerBinding.textureType); 686 stream->writeInt(samplerBinding.samplerType); 687 stream->writeEnum(samplerBinding.format); 688 stream->writeInt(samplerBinding.boundTextureUnits.size()); 689 } 690 691 stream->writeInt(getImageUniformRange().low()); 692 stream->writeInt(getImageUniformRange().high()); 693 694 stream->writeInt(getImageBindings().size()); 695 for (const auto &imageBinding : getImageBindings()) 696 { 697 stream->writeInt(imageBinding.boundImageUnits.size()); 698 stream->writeInt(static_cast<unsigned int>(imageBinding.textureType)); 699 for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i) 700 { 701 stream->writeInt(imageBinding.boundImageUnits[i]); 702 } 703 } 704 705 stream->writeInt(getAtomicCounterUniformRange().low()); 706 stream->writeInt(getAtomicCounterUniformRange().high()); 707 708 // These values are currently only used by PPOs, so only save them when the program is marked 709 // separable to save memory. 710 if (isSeparable) 711 { 712 for (ShaderType shaderType : mLinkedShaderStages) 713 { 714 stream->writeInt(mLinkedOutputVaryings[shaderType].size()); 715 for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType]) 716 { 717 WriteShaderVar(stream, shaderVariable); 718 } 719 stream->writeInt(mLinkedInputVaryings[shaderType].size()); 720 for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType]) 721 { 722 WriteShaderVar(stream, shaderVariable); 723 } 724 stream->writeInt(mLinkedUniforms[shaderType].size()); 725 for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType]) 726 { 727 WriteShaderVar(stream, shaderVariable); 728 } 729 stream->writeInt(mLinkedUniformBlocks[shaderType].size()); 730 for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType]) 731 { 732 WriteShInterfaceBlock(stream, shaderStorageBlock); 733 } 734 stream->writeInt(mLinkedShaderVersions[shaderType]); 735 } 736 } 737 } 738 739 int ProgramExecutable::getInfoLogLength() const 740 { 741 return static_cast<int>(mInfoLog.getLength()); 742 } 743 744 void ProgramExecutable::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const 745 { 746 return mInfoLog.getLog(bufSize, length, infoLog); 747 } 748 749 std::string ProgramExecutable::getInfoLogString() const 750 { 751 return mInfoLog.str(); 752 } 753 754 bool ProgramExecutable::isAttribLocationActive(size_t attribLocation) const 755 { 756 ASSERT(attribLocation < mActiveAttribLocationsMask.size()); 757 return mActiveAttribLocationsMask[attribLocation]; 758 } 759 760 AttributesMask ProgramExecutable::getAttributesMask() const 761 { 762 return mAttributesMask; 763 } 764 765 bool ProgramExecutable::hasDefaultUniforms() const 766 { 767 return !getDefaultUniformRange().empty(); 768 } 769 770 bool ProgramExecutable::hasTextures() const 771 { 772 return !getSamplerBindings().empty(); 773 } 774 775 bool ProgramExecutable::hasUniformBuffers() const 776 { 777 return !mUniformBlocks.empty(); 778 } 779 780 bool ProgramExecutable::hasStorageBuffers() const 781 { 782 return !mShaderStorageBlocks.empty(); 783 } 784 785 bool ProgramExecutable::hasAtomicCounterBuffers() const 786 { 787 return !mAtomicCounterBuffers.empty(); 788 } 789 790 bool ProgramExecutable::hasImages() const 791 { 792 return !mImageBindings.empty(); 793 } 794 795 bool ProgramExecutable::usesFramebufferFetch() const 796 { 797 return (mFragmentInoutRange.length() > 0); 798 } 799 800 GLuint ProgramExecutable::getUniformIndexFromImageIndex(GLuint imageIndex) const 801 { 802 ASSERT(imageIndex < mImageUniformRange.length()); 803 return imageIndex + mImageUniformRange.low(); 804 } 805 806 GLuint ProgramExecutable::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const 807 { 808 ASSERT(samplerIndex < mSamplerUniformRange.length()); 809 return samplerIndex + mSamplerUniformRange.low(); 810 } 811 812 void ProgramExecutable::setActive(size_t textureUnit, 813 const SamplerBinding &samplerBinding, 814 const gl::LinkedUniform &samplerUniform) 815 { 816 mActiveSamplersMask.set(textureUnit); 817 mActiveSamplerTypes[textureUnit] = samplerBinding.textureType; 818 mActiveSamplerYUV[textureUnit] = IsSamplerYUVType(samplerBinding.samplerType); 819 mActiveSamplerFormats[textureUnit] = samplerBinding.format; 820 mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders(); 821 } 822 823 void ProgramExecutable::setInactive(size_t textureUnit) 824 { 825 mActiveSamplersMask.reset(textureUnit); 826 mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum; 827 mActiveSamplerYUV.reset(textureUnit); 828 mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum; 829 mActiveSamplerShaderBits[textureUnit].reset(); 830 } 831 832 void ProgramExecutable::hasSamplerTypeConflict(size_t textureUnit) 833 { 834 // Conflicts are marked with InvalidEnum 835 mActiveSamplerYUV.reset(textureUnit); 836 mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum; 837 } 838 839 void ProgramExecutable::hasSamplerFormatConflict(size_t textureUnit) 840 { 841 // Conflicts are marked with InvalidEnum 842 mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum; 843 } 844 845 void ProgramExecutable::updateActiveSamplers(const ProgramState &programState) 846 { 847 const std::vector<SamplerBinding> &samplerBindings = programState.getSamplerBindings(); 848 849 for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex) 850 { 851 const SamplerBinding &samplerBinding = samplerBindings[samplerIndex]; 852 853 for (GLint textureUnit : samplerBinding.boundTextureUnits) 854 { 855 if (++mActiveSamplerRefCounts[textureUnit] == 1) 856 { 857 uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(samplerIndex); 858 setActive(textureUnit, samplerBinding, programState.getUniforms()[uniformIndex]); 859 } 860 else 861 { 862 if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType || 863 mActiveSamplerYUV.test(textureUnit) != 864 IsSamplerYUVType(samplerBinding.samplerType)) 865 { 866 hasSamplerTypeConflict(textureUnit); 867 } 868 869 if (mActiveSamplerFormats[textureUnit] != samplerBinding.format) 870 { 871 hasSamplerFormatConflict(textureUnit); 872 } 873 } 874 mActiveSamplersMask.set(textureUnit); 875 } 876 } 877 878 // Invalidate the validation cache. 879 resetCachedValidateSamplersResult(); 880 } 881 882 void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable) 883 { 884 const std::vector<ImageBinding> &imageBindings = executable.getImageBindings(); 885 for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex) 886 { 887 const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex); 888 889 uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex); 890 const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex]; 891 const ShaderBitSet shaderBits = imageUniform.activeShaders(); 892 for (GLint imageUnit : imageBinding.boundImageUnits) 893 { 894 mActiveImagesMask.set(imageUnit); 895 mActiveImageShaderBits[imageUnit] |= shaderBits; 896 } 897 } 898 } 899 900 void ProgramExecutable::setSamplerUniformTextureTypeAndFormat( 901 size_t textureUnitIndex, 902 std::vector<SamplerBinding> &samplerBindings) 903 { 904 bool foundBinding = false; 905 TextureType foundType = TextureType::InvalidEnum; 906 bool foundYUV = false; 907 SamplerFormat foundFormat = SamplerFormat::InvalidEnum; 908 909 for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex) 910 { 911 const SamplerBinding &binding = samplerBindings[samplerIndex]; 912 913 // A conflict exists if samplers of different types are sourced by the same texture unit. 914 // We need to check all bound textures to detect this error case. 915 for (GLuint textureUnit : binding.boundTextureUnits) 916 { 917 if (textureUnit != textureUnitIndex) 918 { 919 continue; 920 } 921 922 if (!foundBinding) 923 { 924 foundBinding = true; 925 foundType = binding.textureType; 926 foundYUV = IsSamplerYUVType(binding.samplerType); 927 foundFormat = binding.format; 928 uint32_t uniformIndex = getUniformIndexFromSamplerIndex(samplerIndex); 929 setActive(textureUnit, binding, mUniforms[uniformIndex]); 930 } 931 else 932 { 933 if (foundType != binding.textureType || 934 foundYUV != IsSamplerYUVType(binding.samplerType)) 935 { 936 hasSamplerTypeConflict(textureUnit); 937 } 938 939 if (foundFormat != binding.format) 940 { 941 hasSamplerFormatConflict(textureUnit); 942 } 943 } 944 } 945 } 946 } 947 948 void ProgramExecutable::updateCanDrawWith() 949 { 950 mCanDrawWith = hasLinkedShaderStage(ShaderType::Vertex); 951 } 952 953 void ProgramExecutable::saveLinkedStateInfo(const Context *context, const ProgramState &state) 954 { 955 for (ShaderType shaderType : getLinkedShaderStages()) 956 { 957 Shader *shader = state.getAttachedShader(shaderType); 958 ASSERT(shader); 959 mLinkedOutputVaryings[shaderType] = shader->getOutputVaryings(context); 960 mLinkedInputVaryings[shaderType] = shader->getInputVaryings(context); 961 mLinkedShaderVersions[shaderType] = shader->getShaderVersion(context); 962 mLinkedUniforms[shaderType] = shader->getUniforms(context); 963 mLinkedUniformBlocks[shaderType] = shader->getUniformBlocks(context); 964 } 965 } 966 967 bool ProgramExecutable::isYUVOutput() const 968 { 969 return mYUVOutput; 970 } 971 972 ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const 973 { 974 return GetLastPreFragmentStage(mLinkedShaderStages); 975 } 976 977 bool ProgramExecutable::linkMergedVaryings( 978 const Context *context, 979 const ProgramMergedVaryings &mergedVaryings, 980 const std::vector<std::string> &transformFeedbackVaryingNames, 981 const LinkingVariables &linkingVariables, 982 bool isSeparable, 983 ProgramVaryingPacking *varyingPacking) 984 { 985 ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset); 986 987 if (!linkValidateTransformFeedback(context, mergedVaryings, tfStage, 988 transformFeedbackVaryingNames)) 989 { 990 return false; 991 } 992 993 // Map the varyings to the register file 994 // In WebGL, we use a slightly different handling for packing variables. 995 gl::PackMode packMode = PackMode::ANGLE_RELAXED; 996 if (context->getLimitations().noFlexibleVaryingPacking) 997 { 998 // D3D9 pack mode is strictly more strict than WebGL, so takes priority. 999 packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9; 1000 } 1001 else if (context->isWebGL()) 1002 { 1003 packMode = PackMode::WEBGL_STRICT; 1004 } 1005 1006 // Build active shader stage map. 1007 ShaderBitSet activeShadersMask; 1008 for (ShaderType shaderType : kAllGraphicsShaderTypes) 1009 { 1010 // - Check for attached shaders to handle the case of a Program linking the currently 1011 // attached shaders. 1012 // - Check for linked shaders to handle the case of a PPO linking separable programs before 1013 // drawing. 1014 if (linkingVariables.isShaderStageUsedBitset[shaderType] || 1015 getLinkedShaderStages().test(shaderType)) 1016 { 1017 activeShadersMask[shaderType] = true; 1018 } 1019 } 1020 1021 if (!varyingPacking->collectAndPackUserVaryings(mInfoLog, context->getCaps(), packMode, 1022 activeShadersMask, mergedVaryings, 1023 transformFeedbackVaryingNames, isSeparable)) 1024 { 1025 return false; 1026 } 1027 1028 gatherTransformFeedbackVaryings(mergedVaryings, tfStage, transformFeedbackVaryingNames); 1029 updateTransformFeedbackStrides(); 1030 1031 return true; 1032 } 1033 1034 bool ProgramExecutable::linkValidateTransformFeedback( 1035 const Context *context, 1036 const ProgramMergedVaryings &varyings, 1037 ShaderType stage, 1038 const std::vector<std::string> &transformFeedbackVaryingNames) 1039 { 1040 const Version &version = context->getClientVersion(); 1041 1042 // Validate the tf names regardless of the actual program varyings. 1043 std::set<std::string> uniqueNames; 1044 for (const std::string &tfVaryingName : transformFeedbackVaryingNames) 1045 { 1046 if (version < Version(3, 1) && tfVaryingName.find('[') != std::string::npos) 1047 { 1048 mInfoLog << "Capture of array elements is undefined and not supported."; 1049 return false; 1050 } 1051 if (version >= Version(3, 1)) 1052 { 1053 if (IncludeSameArrayElement(uniqueNames, tfVaryingName)) 1054 { 1055 mInfoLog << "Two transform feedback varyings include the same array element (" 1056 << tfVaryingName << ")."; 1057 return false; 1058 } 1059 } 1060 else 1061 { 1062 if (uniqueNames.count(tfVaryingName) > 0) 1063 { 1064 mInfoLog << "Two transform feedback varyings specify the same output variable (" 1065 << tfVaryingName << ")."; 1066 return false; 1067 } 1068 } 1069 uniqueNames.insert(tfVaryingName); 1070 } 1071 1072 // From OpneGLES spec. 11.1.2.1: A program will fail to link if: 1073 // the count specified by TransformFeedbackVaryings is non-zero, but the 1074 // program object has no vertex, tessellation evaluation, or geometry shader 1075 if (transformFeedbackVaryingNames.size() > 0 && 1076 !gl::ShaderTypeSupportsTransformFeedback(getLinkedTransformFeedbackStage())) 1077 { 1078 mInfoLog << "Linked transform feedback stage " << getLinkedTransformFeedbackStage() 1079 << " does not support transform feedback varying."; 1080 return false; 1081 } 1082 1083 // Validate against program varyings. 1084 size_t totalComponents = 0; 1085 for (const std::string &tfVaryingName : transformFeedbackVaryingNames) 1086 { 1087 std::vector<unsigned int> subscripts; 1088 std::string baseName = ParseResourceName(tfVaryingName, &subscripts); 1089 1090 const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName); 1091 if (var == nullptr) 1092 { 1093 mInfoLog << "Transform feedback varying " << tfVaryingName 1094 << " does not exist in the vertex shader."; 1095 return false; 1096 } 1097 1098 // Validate the matching variable. 1099 if (var->isStruct()) 1100 { 1101 mInfoLog << "Struct cannot be captured directly (" << baseName << ")."; 1102 return false; 1103 } 1104 1105 size_t elementCount = 0; 1106 size_t componentCount = 0; 1107 1108 if (var->isArray()) 1109 { 1110 if (version < Version(3, 1)) 1111 { 1112 mInfoLog << "Capture of arrays is undefined and not supported."; 1113 return false; 1114 } 1115 1116 // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays. 1117 ASSERT(!var->isArrayOfArrays()); 1118 1119 if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize()) 1120 { 1121 mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'."; 1122 return false; 1123 } 1124 elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1); 1125 } 1126 else 1127 { 1128 if (!subscripts.empty()) 1129 { 1130 mInfoLog << "Varying '" << baseName 1131 << "' is not an array to be captured by element."; 1132 return false; 1133 } 1134 elementCount = 1; 1135 } 1136 1137 const Caps &caps = context->getCaps(); 1138 1139 // TODO(jmadill): Investigate implementation limits on D3D11 1140 componentCount = VariableComponentCount(var->type) * elementCount; 1141 if (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && 1142 componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents)) 1143 { 1144 mInfoLog << "Transform feedback varying " << tfVaryingName << " components (" 1145 << componentCount << ") exceed the maximum separate components (" 1146 << caps.maxTransformFeedbackSeparateComponents << ")."; 1147 return false; 1148 } 1149 1150 totalComponents += componentCount; 1151 if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && 1152 totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents)) 1153 { 1154 mInfoLog << "Transform feedback varying total components (" << totalComponents 1155 << ") exceed the maximum interleaved components (" 1156 << caps.maxTransformFeedbackInterleavedComponents << ")."; 1157 return false; 1158 } 1159 } 1160 return true; 1161 } 1162 1163 void ProgramExecutable::gatherTransformFeedbackVaryings( 1164 const ProgramMergedVaryings &varyings, 1165 ShaderType stage, 1166 const std::vector<std::string> &transformFeedbackVaryingNames) 1167 { 1168 // Gather the linked varyings that are used for transform feedback, they should all exist. 1169 mLinkedTransformFeedbackVaryings.clear(); 1170 for (const std::string &tfVaryingName : transformFeedbackVaryingNames) 1171 { 1172 std::vector<unsigned int> subscripts; 1173 std::string baseName = ParseResourceName(tfVaryingName, &subscripts); 1174 size_t subscript = GL_INVALID_INDEX; 1175 if (!subscripts.empty()) 1176 { 1177 subscript = subscripts.back(); 1178 } 1179 for (const ProgramVaryingRef &ref : varyings) 1180 { 1181 if (ref.frontShaderStage != stage) 1182 { 1183 continue; 1184 } 1185 1186 const sh::ShaderVariable *varying = ref.get(stage); 1187 if (baseName == varying->name) 1188 { 1189 mLinkedTransformFeedbackVaryings.emplace_back(*varying, 1190 static_cast<GLuint>(subscript)); 1191 break; 1192 } 1193 else if (varying->isStruct()) 1194 { 1195 GLuint fieldIndex = 0; 1196 const auto *field = varying->findField(tfVaryingName, &fieldIndex); 1197 if (field != nullptr) 1198 { 1199 mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying); 1200 break; 1201 } 1202 } 1203 } 1204 } 1205 } 1206 1207 void ProgramExecutable::updateTransformFeedbackStrides() 1208 { 1209 if (mLinkedTransformFeedbackVaryings.empty()) 1210 { 1211 return; 1212 } 1213 1214 if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS) 1215 { 1216 mTransformFeedbackStrides.resize(1); 1217 size_t totalSize = 0; 1218 for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings) 1219 { 1220 totalSize += varying.size() * VariableExternalSize(varying.type); 1221 } 1222 mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize); 1223 } 1224 else 1225 { 1226 mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size()); 1227 for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++) 1228 { 1229 TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i]; 1230 mTransformFeedbackStrides[i] = 1231 static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type)); 1232 } 1233 } 1234 } 1235 1236 bool ProgramExecutable::validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const 1237 { 1238 // if any two active samplers in a program are of different types, but refer to the same 1239 // texture image unit, and this is the current program, then ValidateProgram will fail, and 1240 // DrawArrays and DrawElements will issue the INVALID_OPERATION error. 1241 for (size_t textureUnit : mActiveSamplersMask) 1242 { 1243 if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum) 1244 { 1245 if (infoLog) 1246 { 1247 (*infoLog) << "Samplers of conflicting types refer to the same texture " 1248 "image unit (" 1249 << textureUnit << ")."; 1250 } 1251 1252 mCachedValidateSamplersResult = false; 1253 return false; 1254 } 1255 1256 if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum) 1257 { 1258 if (infoLog) 1259 { 1260 (*infoLog) << "Samplers of conflicting formats refer to the same texture " 1261 "image unit (" 1262 << textureUnit << ")."; 1263 } 1264 1265 mCachedValidateSamplersResult = false; 1266 return false; 1267 } 1268 } 1269 1270 mCachedValidateSamplersResult = true; 1271 return true; 1272 } 1273 1274 bool ProgramExecutable::linkValidateOutputVariables( 1275 const Caps &caps, 1276 const Extensions &extensions, 1277 const Version &version, 1278 GLuint combinedImageUniformsCount, 1279 GLuint combinedShaderStorageBlocksCount, 1280 const std::vector<sh::ShaderVariable> &outputVariables, 1281 int fragmentShaderVersion, 1282 const ProgramAliasedBindings &fragmentOutputLocations, 1283 const ProgramAliasedBindings &fragmentOutputIndices) 1284 { 1285 ASSERT(mOutputVariableTypes.empty()); 1286 ASSERT(mActiveOutputVariablesMask.none()); 1287 ASSERT(mDrawBufferTypeMask.none()); 1288 ASSERT(!mYUVOutput); 1289 1290 // Gather output variable types 1291 for (const sh::ShaderVariable &outputVariable : outputVariables) 1292 { 1293 if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" && 1294 outputVariable.name != "gl_FragData") 1295 { 1296 continue; 1297 } 1298 1299 unsigned int baseLocation = 1300 (outputVariable.location == -1 ? 0u 1301 : static_cast<unsigned int>(outputVariable.location)); 1302 1303 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of 1304 // structures, so we may use getBasicTypeElementCount(). 1305 unsigned int elementCount = outputVariable.getBasicTypeElementCount(); 1306 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++) 1307 { 1308 const unsigned int location = baseLocation + elementIndex; 1309 if (location >= mOutputVariableTypes.size()) 1310 { 1311 mOutputVariableTypes.resize(location + 1, GL_NONE); 1312 } 1313 ASSERT(location < mActiveOutputVariablesMask.size()); 1314 mActiveOutputVariablesMask.set(location); 1315 mOutputVariableTypes[location] = VariableComponentType(outputVariable.type); 1316 ComponentType componentType = GLenumToComponentType(mOutputVariableTypes[location]); 1317 SetComponentTypeMask(componentType, location, &mDrawBufferTypeMask); 1318 } 1319 1320 if (outputVariable.yuv) 1321 { 1322 ASSERT(outputVariables.size() == 1); 1323 mYUVOutput = true; 1324 } 1325 } 1326 1327 if (version >= ES_3_1) 1328 { 1329 // [OpenGL ES 3.1] Chapter 8.22 Page 203: 1330 // A link error will be generated if the sum of the number of active image uniforms used in 1331 // all shaders, the number of active shader storage blocks, and the number of active 1332 // fragment shader outputs exceeds the implementation-dependent value of 1333 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES. 1334 if (combinedImageUniformsCount + combinedShaderStorageBlocksCount + 1335 mActiveOutputVariablesMask.count() > 1336 static_cast<GLuint>(caps.maxCombinedShaderOutputResources)) 1337 { 1338 mInfoLog 1339 << "The sum of the number of active image uniforms, active shader storage blocks " 1340 "and active fragment shader outputs exceeds " 1341 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES (" 1342 << caps.maxCombinedShaderOutputResources << ")"; 1343 return false; 1344 } 1345 } 1346 1347 mOutputVariables = outputVariables; 1348 1349 if (fragmentShaderVersion == 100) 1350 { 1351 return true; 1352 } 1353 1354 // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an 1355 // output array in explicit terms. 1356 // 1357 // Assuming fragData is an output array, you can defend the position that: 1358 // P1) you must support binding "fragData" because it's specified 1359 // P2) you must support querying "fragData[x]" because it's specified 1360 // P3) you must support binding "fragData[0]" because it's a frequently used pattern 1361 // 1362 // Then you can make the leap of faith: 1363 // P4) you must support binding "fragData[x]" because you support "fragData[0]" 1364 // P5) you must support binding "fragData[x]" because you support querying "fragData[x]" 1365 // 1366 // The spec brings in the "world of arrays" when it mentions binding the arrays and the 1367 // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you 1368 // must infer the only possible interpretation (?). Note again: this need of interpretation 1369 // might be completely off of what GL spec logic is. 1370 // 1371 // The other complexity is that unless you implement this feature, it's hard to understand what 1372 // should happen when the client invokes the feature. You cannot add an additional error as it 1373 // is not specified. One can ignore it, but obviously it creates the discrepancies... 1374 1375 std::vector<VariableLocation> reservedLocations; 1376 1377 // Process any output API bindings for arrays that don't alias to the first element. 1378 for (const auto &bindingPair : fragmentOutputLocations) 1379 { 1380 const std::string &name = bindingPair.first; 1381 const ProgramBinding &binding = bindingPair.second; 1382 1383 size_t nameLengthWithoutArrayIndex; 1384 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex); 1385 if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX) 1386 { 1387 continue; 1388 } 1389 for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size(); 1390 outputVariableIndex++) 1391 { 1392 const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex]; 1393 // Check that the binding corresponds to an output array and its array index fits. 1394 if (outputVariable.isBuiltIn() || !outputVariable.isArray() || 1395 !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) || 1396 arrayIndex >= outputVariable.getOutermostArraySize()) 1397 { 1398 continue; 1399 } 1400 1401 // Get the API index that corresponds to this exact binding. 1402 // This index may differ from the index used for the array's base. 1403 std::vector<VariableLocation> &outputLocations = 1404 fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations 1405 : mOutputLocations; 1406 unsigned int location = binding.location; 1407 VariableLocation locationInfo(arrayIndex, outputVariableIndex); 1408 if (location >= outputLocations.size()) 1409 { 1410 outputLocations.resize(location + 1); 1411 } 1412 if (outputLocations[location].used()) 1413 { 1414 mInfoLog << "Location of variable " << outputVariable.name 1415 << " conflicts with another variable."; 1416 return false; 1417 } 1418 outputLocations[location] = locationInfo; 1419 1420 // Note the array binding location so that it can be skipped later. 1421 reservedLocations.push_back(locationInfo); 1422 } 1423 } 1424 1425 // Reserve locations for output variables whose location is fixed in the shader or through the 1426 // API. Otherwise, the remaining unallocated outputs will be processed later. 1427 for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size(); 1428 outputVariableIndex++) 1429 { 1430 const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex]; 1431 1432 // Don't store outputs for gl_FragDepth, gl_FragColor, etc. 1433 if (outputVariable.isBuiltIn()) 1434 continue; 1435 1436 int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable); 1437 if (fixedLocation == -1) 1438 { 1439 // Here we're only reserving locations for variables whose location is fixed. 1440 continue; 1441 } 1442 unsigned int baseLocation = static_cast<unsigned int>(fixedLocation); 1443 1444 std::vector<VariableLocation> &outputLocations = 1445 IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable) 1446 ? mSecondaryOutputLocations 1447 : mOutputLocations; 1448 1449 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of 1450 // structures, so we may use getBasicTypeElementCount(). 1451 unsigned int elementCount = outputVariable.getBasicTypeElementCount(); 1452 if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations, 1453 outputVariableIndex)) 1454 { 1455 mInfoLog << "Location of variable " << outputVariable.name 1456 << " conflicts with another variable."; 1457 return false; 1458 } 1459 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations, 1460 outputVariableIndex, mOutputVariables[outputVariableIndex]); 1461 } 1462 1463 // Here we assign locations for the output variables that don't yet have them. Note that we're 1464 // not necessarily able to fit the variables optimally, since then we might have to try 1465 // different arrangements of output arrays. Now we just assign the locations in the order that 1466 // we got the output variables. The spec isn't clear on what kind of algorithm is required for 1467 // finding locations for the output variables, so this should be acceptable at least for now. 1468 GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers); 1469 if (!mSecondaryOutputLocations.empty()) 1470 { 1471 // EXT_blend_func_extended: Program outputs will be validated against 1472 // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one. 1473 maxLocation = caps.maxDualSourceDrawBuffers; 1474 } 1475 1476 for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size(); 1477 outputVariableIndex++) 1478 { 1479 const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex]; 1480 1481 // Don't store outputs for gl_FragDepth, gl_FragColor, etc. 1482 if (outputVariable.isBuiltIn()) 1483 continue; 1484 1485 int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable); 1486 std::vector<VariableLocation> &outputLocations = 1487 IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable) 1488 ? mSecondaryOutputLocations 1489 : mOutputLocations; 1490 unsigned int baseLocation = 0; 1491 unsigned int elementCount = outputVariable.getBasicTypeElementCount(); 1492 if (fixedLocation != -1) 1493 { 1494 // Secondary inputs might have caused the max location to drop below what has already 1495 // been explicitly assigned locations. Check for any fixed locations above the max 1496 // that should cause linking to fail. 1497 baseLocation = static_cast<unsigned int>(fixedLocation); 1498 } 1499 else 1500 { 1501 // No fixed location, so try to fit the output in unassigned locations. 1502 // Try baseLocations starting from 0 one at a time and see if the variable fits. 1503 while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, 1504 reservedLocations, outputVariableIndex)) 1505 { 1506 baseLocation++; 1507 } 1508 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations, 1509 outputVariableIndex, mOutputVariables[outputVariableIndex]); 1510 } 1511 1512 // Check for any elements assigned above the max location that are actually used. 1513 if (baseLocation + elementCount > maxLocation && 1514 (baseLocation >= maxLocation || 1515 FindUsedOutputLocation(outputLocations, maxLocation, 1516 baseLocation + elementCount - maxLocation, reservedLocations, 1517 outputVariableIndex))) 1518 { 1519 // EXT_blend_func_extended: Linking can fail: 1520 // "if the explicit binding assignments do not leave enough space for the linker to 1521 // automatically assign a location for a varying out array, which requires multiple 1522 // contiguous locations." 1523 mInfoLog << "Could not fit output variable into available locations: " 1524 << outputVariable.name; 1525 return false; 1526 } 1527 } 1528 1529 return true; 1530 } 1531 1532 bool ProgramExecutable::linkUniforms( 1533 const Context *context, 1534 const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms, 1535 InfoLog &infoLog, 1536 const ProgramAliasedBindings &uniformLocationBindings, 1537 GLuint *combinedImageUniformsCountOut, 1538 std::vector<UnusedUniform> *unusedUniformsOutOrNull, 1539 std::vector<VariableLocation> *uniformLocationsOutOrNull) 1540 { 1541 UniformLinker linker(mLinkedShaderStages, shaderUniforms); 1542 if (!linker.link(context->getCaps(), infoLog, uniformLocationBindings)) 1543 { 1544 return false; 1545 } 1546 1547 linker.getResults(&mUniforms, unusedUniformsOutOrNull, uniformLocationsOutOrNull); 1548 1549 linkSamplerAndImageBindings(combinedImageUniformsCountOut); 1550 1551 if (!linkAtomicCounterBuffers(context, infoLog)) 1552 { 1553 return false; 1554 } 1555 1556 return true; 1557 } 1558 1559 void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniforms) 1560 { 1561 ASSERT(combinedImageUniforms); 1562 1563 // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs, 1564 // atomic counters, images and samplers in that order. 1565 auto highIter = mUniforms.rbegin(); 1566 auto lowIter = highIter; 1567 1568 unsigned int high = static_cast<unsigned int>(mUniforms.size()); 1569 unsigned int low = high; 1570 1571 // Note that uniform block uniforms are not yet appended to this list. 1572 ASSERT(mUniforms.empty() || highIter->isAtomicCounter() || highIter->isImage() || 1573 highIter->isSampler() || highIter->isInDefaultBlock() || highIter->isFragmentInOut); 1574 1575 for (; lowIter != mUniforms.rend() && lowIter->isFragmentInOut; ++lowIter) 1576 { 1577 --low; 1578 } 1579 1580 mFragmentInoutRange = RangeUI(low, high); 1581 1582 highIter = lowIter; 1583 high = low; 1584 1585 for (; lowIter != mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter) 1586 { 1587 --low; 1588 } 1589 1590 mAtomicCounterUniformRange = RangeUI(low, high); 1591 1592 highIter = lowIter; 1593 high = low; 1594 1595 for (; lowIter != mUniforms.rend() && lowIter->isImage(); ++lowIter) 1596 { 1597 --low; 1598 } 1599 1600 mImageUniformRange = RangeUI(low, high); 1601 *combinedImageUniforms = 0u; 1602 // If uniform is a image type, insert it into the mImageBindings array. 1603 for (unsigned int imageIndex : mImageUniformRange) 1604 { 1605 // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands 1606 // cannot load values into a uniform defined as an image. if declare without a 1607 // binding qualifier, any uniform image variable (include all elements of 1608 // unbound image array) should be bound to unit zero. 1609 auto &imageUniform = mUniforms[imageIndex]; 1610 TextureType textureType = ImageTypeToTextureType(imageUniform.type); 1611 const GLuint arraySize = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u; 1612 1613 if (imageUniform.binding == -1) 1614 { 1615 mImageBindings.emplace_back( 1616 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType)); 1617 } 1618 else 1619 { 1620 // The arrays of arrays are flattened to arrays, it needs to record the array offset for 1621 // the correct binding image unit. 1622 mImageBindings.emplace_back( 1623 ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize, 1624 imageUniform.getBasicTypeElementCount(), textureType)); 1625 } 1626 1627 *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize; 1628 } 1629 1630 highIter = lowIter; 1631 high = low; 1632 1633 for (; lowIter != mUniforms.rend() && lowIter->isSampler(); ++lowIter) 1634 { 1635 --low; 1636 } 1637 1638 mSamplerUniformRange = RangeUI(low, high); 1639 1640 // If uniform is a sampler type, insert it into the mSamplerBindings array. 1641 for (unsigned int samplerIndex : mSamplerUniformRange) 1642 { 1643 const auto &samplerUniform = mUniforms[samplerIndex]; 1644 TextureType textureType = SamplerTypeToTextureType(samplerUniform.type); 1645 GLenum samplerType = samplerUniform.typeInfo->type; 1646 unsigned int elementCount = samplerUniform.getBasicTypeElementCount(); 1647 SamplerFormat format = samplerUniform.typeInfo->samplerFormat; 1648 mSamplerBindings.emplace_back(textureType, samplerType, format, elementCount); 1649 } 1650 1651 // Whatever is left constitutes the default uniforms. 1652 mDefaultUniformRange = RangeUI(0, low); 1653 } 1654 1655 bool ProgramExecutable::linkAtomicCounterBuffers(const Context *context, InfoLog &infoLog) 1656 { 1657 for (unsigned int index : mAtomicCounterUniformRange) 1658 { 1659 auto &uniform = mUniforms[index]; 1660 uniform.blockInfo.offset = uniform.offset; 1661 uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0); 1662 uniform.blockInfo.matrixStride = 0; 1663 uniform.blockInfo.isRowMajorMatrix = false; 1664 1665 bool found = false; 1666 for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount(); 1667 ++bufferIndex) 1668 { 1669 auto &buffer = mAtomicCounterBuffers[bufferIndex]; 1670 if (buffer.binding == uniform.binding) 1671 { 1672 buffer.memberIndexes.push_back(index); 1673 uniform.bufferIndex = bufferIndex; 1674 found = true; 1675 buffer.unionReferencesWith(uniform); 1676 break; 1677 } 1678 } 1679 if (!found) 1680 { 1681 AtomicCounterBuffer atomicCounterBuffer; 1682 atomicCounterBuffer.binding = uniform.binding; 1683 atomicCounterBuffer.memberIndexes.push_back(index); 1684 atomicCounterBuffer.unionReferencesWith(uniform); 1685 mAtomicCounterBuffers.push_back(atomicCounterBuffer); 1686 uniform.bufferIndex = static_cast<int>(getActiveAtomicCounterBufferCount() - 1); 1687 } 1688 } 1689 1690 // Count each atomic counter buffer to validate against 1691 // per-stage and combined gl_Max*AtomicCounterBuffers. 1692 GLint combinedShaderACBCount = 0; 1693 gl::ShaderMap<GLint> perShaderACBCount = {}; 1694 for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount(); 1695 ++bufferIndex) 1696 { 1697 AtomicCounterBuffer &acb = mAtomicCounterBuffers[bufferIndex]; 1698 const ShaderBitSet shaderStages = acb.activeShaders(); 1699 for (gl::ShaderType shaderType : shaderStages) 1700 { 1701 ++perShaderACBCount[shaderType]; 1702 } 1703 ++combinedShaderACBCount; 1704 } 1705 const Caps &caps = context->getCaps(); 1706 if (combinedShaderACBCount > caps.maxCombinedAtomicCounterBuffers) 1707 { 1708 infoLog << " combined AtomicCounterBuffers count exceeds limit"; 1709 return false; 1710 } 1711 for (gl::ShaderType stage : gl::AllShaderTypes()) 1712 { 1713 if (perShaderACBCount[stage] > caps.maxShaderAtomicCounterBuffers[stage]) 1714 { 1715 infoLog << GetShaderTypeString(stage) 1716 << " shader AtomicCounterBuffers count exceeds limit"; 1717 return false; 1718 } 1719 } 1720 return true; 1721 } 1722 1723 void ProgramExecutable::copyInputsFromProgram(const ProgramState &programState) 1724 { 1725 mProgramInputs = programState.getProgramInputs(); 1726 } 1727 1728 void ProgramExecutable::copyShaderBuffersFromProgram(const ProgramState &programState, 1729 ShaderType shaderType) 1730 { 1731 AppendActiveBlocks(shaderType, programState.getUniformBlocks(), mUniformBlocks); 1732 AppendActiveBlocks(shaderType, programState.getShaderStorageBlocks(), mShaderStorageBlocks); 1733 AppendActiveBlocks(shaderType, programState.getAtomicCounterBuffers(), mAtomicCounterBuffers); 1734 } 1735 1736 void ProgramExecutable::clearSamplerBindings() 1737 { 1738 mSamplerBindings.clear(); 1739 } 1740 1741 void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramState &programState) 1742 { 1743 const std::vector<SamplerBinding> &bindings = programState.getSamplerBindings(); 1744 mSamplerBindings.insert(mSamplerBindings.end(), bindings.begin(), bindings.end()); 1745 } 1746 1747 void ProgramExecutable::copyImageBindingsFromProgram(const ProgramState &programState) 1748 { 1749 const std::vector<ImageBinding> &bindings = programState.getImageBindings(); 1750 mImageBindings.insert(mImageBindings.end(), bindings.begin(), bindings.end()); 1751 } 1752 1753 void ProgramExecutable::copyOutputsFromProgram(const ProgramState &programState) 1754 { 1755 mOutputVariables = programState.getOutputVariables(); 1756 mOutputLocations = programState.getOutputLocations(); 1757 mSecondaryOutputLocations = programState.getSecondaryOutputLocations(); 1758 } 1759 1760 void ProgramExecutable::copyUniformsFromProgramMap(const ShaderMap<Program *> &programs) 1761 { 1762 // Merge default uniforms. 1763 auto getDefaultRange = [](const ProgramState &state) { return state.getDefaultUniformRange(); }; 1764 mDefaultUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getDefaultRange); 1765 1766 // Merge sampler uniforms. 1767 auto getSamplerRange = [](const ProgramState &state) { return state.getSamplerUniformRange(); }; 1768 mSamplerUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getSamplerRange); 1769 1770 // Merge image uniforms. 1771 auto getImageRange = [](const ProgramState &state) { return state.getImageUniformRange(); }; 1772 mImageUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getImageRange); 1773 1774 // Merge atomic counter uniforms. 1775 auto getAtomicRange = [](const ProgramState &state) { 1776 return state.getAtomicCounterUniformRange(); 1777 }; 1778 mAtomicCounterUniformRange = 1779 AddUniforms(programs, mLinkedShaderStages, mUniforms, getAtomicRange); 1780 1781 // Merge fragment in/out uniforms. 1782 auto getInoutRange = [](const ProgramState &state) { return state.getFragmentInoutRange(); }; 1783 mFragmentInoutRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getInoutRange); 1784 } 1785 } // namespace gl