• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // ProgramPipeline.cpp: Implements the gl::ProgramPipeline class.
8 // Implements GL program pipeline objects and related functionality.
9 // [OpenGL ES 3.1] section 7.4 page 105.
10 
11 #include "libANGLE/ProgramPipeline.h"
12 
13 #include <algorithm>
14 
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Program.h"
17 #include "libANGLE/angletypes.h"
18 #include "libANGLE/renderer/GLImplFactory.h"
19 #include "libANGLE/renderer/ProgramPipelineImpl.h"
20 
21 namespace gl
22 {
23 
24 enum SubjectIndexes : angle::SubjectIndex
25 {
26     kExecutableSubjectIndex = 0
27 };
28 
ProgramPipelineState()29 ProgramPipelineState::ProgramPipelineState()
30     : mLabel(),
31       mActiveShaderProgram(nullptr),
32       mValid(false),
33       mExecutable(new ProgramExecutable()),
34       mIsLinked(false)
35 {
36     for (const ShaderType shaderType : gl::AllShaderTypes())
37     {
38         mPrograms[shaderType] = nullptr;
39     }
40 }
41 
~ProgramPipelineState()42 ProgramPipelineState::~ProgramPipelineState()
43 {
44     SafeDelete(mExecutable);
45 }
46 
getLabel() const47 const std::string &ProgramPipelineState::getLabel() const
48 {
49     return mLabel;
50 }
51 
activeShaderProgram(Program * shaderProgram)52 void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
53 {
54     mActiveShaderProgram = shaderProgram;
55 }
56 
useProgramStage(const Context * context,const ShaderType shaderType,Program * shaderProgram,angle::ObserverBinding * programObserverBindings)57 void ProgramPipelineState::useProgramStage(const Context *context,
58                                            const ShaderType shaderType,
59                                            Program *shaderProgram,
60                                            angle::ObserverBinding *programObserverBindings)
61 {
62     Program *oldProgram = mPrograms[shaderType];
63     if (oldProgram)
64     {
65         oldProgram->release(context);
66     }
67 
68     // If program refers to a program object with a valid shader attached for the indicated shader
69     // stage, glUseProgramStages installs the executable code for that stage in the indicated
70     // program pipeline object pipeline.
71     if (shaderProgram && (shaderProgram->id().value != 0) &&
72         shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
73     {
74         mPrograms[shaderType] = shaderProgram;
75         shaderProgram->addRef();
76     }
77     else
78     {
79         // If program is zero, or refers to a program object with no valid shader executable for the
80         // given stage, it is as if the pipeline object has no programmable stage configured for the
81         // indicated shader stage.
82         mPrograms[shaderType] = nullptr;
83     }
84 
85     Program *program = mPrograms[shaderType];
86     programObserverBindings->bind(program);
87 }
88 
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram,std::vector<angle::ObserverBinding> * programObserverBindings)89 void ProgramPipelineState::useProgramStages(
90     const Context *context,
91     GLbitfield stages,
92     Program *shaderProgram,
93     std::vector<angle::ObserverBinding> *programObserverBindings)
94 {
95     for (size_t singleShaderBit : angle::BitSet16<16>(static_cast<uint16_t>(stages)))
96     {
97         // Cast back to a bit after the iterator returns an index.
98         ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
99         if (shaderType == ShaderType::InvalidEnum)
100         {
101             break;
102         }
103         useProgramStage(context, shaderType, shaderProgram,
104                         &programObserverBindings->at(static_cast<size_t>(shaderType)));
105     }
106 }
107 
usesShaderProgram(ShaderProgramID programId) const108 bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
109 {
110     for (const Program *program : mPrograms)
111     {
112         if (program && (program->id() == programId))
113         {
114             return true;
115         }
116     }
117 
118     return false;
119 }
120 
updateExecutableTextures()121 void ProgramPipelineState::updateExecutableTextures()
122 {
123     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
124     {
125         const Program *program = getShaderProgram(shaderType);
126         ASSERT(program);
127         mExecutable->setActiveTextureMask(program->getExecutable().getActiveSamplersMask());
128         mExecutable->setActiveImagesMask(program->getExecutable().getActiveImagesMask());
129         // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
130         mExecutable->updateActiveSamplers(program->getState());
131     }
132 }
133 
getSpecConstUsageBits() const134 rx::SpecConstUsageBits ProgramPipelineState::getSpecConstUsageBits() const
135 {
136     rx::SpecConstUsageBits specConstUsageBits;
137     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
138     {
139         const Program *program = getShaderProgram(shaderType);
140         ASSERT(program);
141         specConstUsageBits |= program->getState().getSpecConstUsageBits();
142     }
143     return specConstUsageBits;
144 }
145 
ProgramPipeline(rx::GLImplFactory * factory,ProgramPipelineID handle)146 ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
147     : RefCountObject(factory->generateSerial(), handle),
148       mProgramPipelineImpl(factory->createProgramPipeline(mState)),
149       mExecutableObserverBinding(this, kExecutableSubjectIndex)
150 {
151     ASSERT(mProgramPipelineImpl);
152 
153     for (const ShaderType shaderType : gl::AllShaderTypes())
154     {
155         mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
156     }
157     mExecutableObserverBinding.bind(mState.mExecutable);
158 }
159 
~ProgramPipeline()160 ProgramPipeline::~ProgramPipeline()
161 {
162     mProgramPipelineImpl.release();
163 }
164 
onDestroy(const Context * context)165 void ProgramPipeline::onDestroy(const Context *context)
166 {
167     for (Program *program : mState.mPrograms)
168     {
169         if (program)
170         {
171             ASSERT(program->getRefCount());
172             program->release(context);
173         }
174     }
175 
176     getImplementation()->destroy(context);
177 }
178 
setLabel(const Context * context,const std::string & label)179 void ProgramPipeline::setLabel(const Context *context, const std::string &label)
180 {
181     mState.mLabel = label;
182 }
183 
getLabel() const184 const std::string &ProgramPipeline::getLabel() const
185 {
186     return mState.mLabel;
187 }
188 
getImplementation() const189 rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
190 {
191     return mProgramPipelineImpl.get();
192 }
193 
activeShaderProgram(Program * shaderProgram)194 void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
195 {
196     mState.activeShaderProgram(shaderProgram);
197 }
198 
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)199 void ProgramPipeline::useProgramStages(const Context *context,
200                                        GLbitfield stages,
201                                        Program *shaderProgram)
202 {
203     mState.useProgramStages(context, stages, shaderProgram, &mProgramObserverBindings);
204     updateLinkedShaderStages();
205     updateExecutable();
206 
207     mState.mIsLinked = false;
208 }
209 
updateLinkedShaderStages()210 void ProgramPipeline::updateLinkedShaderStages()
211 {
212     mState.mExecutable->resetLinkedShaderStages();
213 
214     for (const ShaderType shaderType : gl::AllShaderTypes())
215     {
216         Program *program = mState.mPrograms[shaderType];
217         if (program)
218         {
219             mState.mExecutable->setLinkedShaderStages(shaderType);
220         }
221     }
222 
223     mState.mExecutable->updateCanDrawWith();
224 }
225 
updateExecutableAttributes()226 void ProgramPipeline::updateExecutableAttributes()
227 {
228     Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
229 
230     if (!vertexProgram)
231     {
232         return;
233     }
234 
235     const ProgramExecutable &vertexExecutable      = vertexProgram->getExecutable();
236     mState.mExecutable->mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
237     mState.mExecutable->mMaxActiveAttribLocation   = vertexExecutable.mMaxActiveAttribLocation;
238     mState.mExecutable->mAttributesTypeMask        = vertexExecutable.mAttributesTypeMask;
239     mState.mExecutable->mAttributesMask            = vertexExecutable.mAttributesMask;
240 }
241 
updateTransformFeedbackMembers()242 void ProgramPipeline::updateTransformFeedbackMembers()
243 {
244     ShaderType lastVertexProcessingStage =
245         gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
246     if (lastVertexProcessingStage == ShaderType::InvalidEnum)
247     {
248         return;
249     }
250 
251     Program *shaderProgram = getShaderProgram(lastVertexProcessingStage);
252     ASSERT(shaderProgram);
253 
254     const ProgramExecutable &lastPreFragmentExecutable = shaderProgram->getExecutable();
255     mState.mExecutable->mTransformFeedbackStrides =
256         lastPreFragmentExecutable.mTransformFeedbackStrides;
257     mState.mExecutable->mLinkedTransformFeedbackVaryings =
258         lastPreFragmentExecutable.mLinkedTransformFeedbackVaryings;
259 }
260 
updateShaderStorageBlocks()261 void ProgramPipeline::updateShaderStorageBlocks()
262 {
263     mState.mExecutable->mComputeShaderStorageBlocks.clear();
264     mState.mExecutable->mGraphicsShaderStorageBlocks.clear();
265 
266     // Only copy the storage blocks from each Program in the PPO once, since each Program could
267     // contain multiple shader stages.
268     ShaderBitSet handledStages;
269 
270     for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
271     {
272         const Program *shaderProgram = getShaderProgram(shaderType);
273         if (shaderProgram && !handledStages.test(shaderType))
274         {
275             // Only add each Program's blocks once.
276             handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
277 
278             for (const InterfaceBlock &block :
279                  shaderProgram->getExecutable().getShaderStorageBlocks())
280             {
281                 mState.mExecutable->mGraphicsShaderStorageBlocks.emplace_back(block);
282             }
283         }
284     }
285 
286     const Program *computeProgram = getShaderProgram(ShaderType::Compute);
287     if (computeProgram)
288     {
289         for (const InterfaceBlock &block : computeProgram->getExecutable().getShaderStorageBlocks())
290         {
291             mState.mExecutable->mComputeShaderStorageBlocks.emplace_back(block);
292         }
293     }
294 }
295 
updateImageBindings()296 void ProgramPipeline::updateImageBindings()
297 {
298     mState.mExecutable->mComputeImageBindings.clear();
299     mState.mExecutable->mGraphicsImageBindings.clear();
300     mState.mExecutable->mActiveImageShaderBits.fill({});
301 
302     // Only copy the storage blocks from each Program in the PPO once, since each Program could
303     // contain multiple shader stages.
304     ShaderBitSet handledStages;
305 
306     for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
307     {
308         const Program *shaderProgram = getShaderProgram(shaderType);
309         if (shaderProgram && !handledStages.test(shaderType))
310         {
311             // Only add each Program's blocks once.
312             handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
313 
314             for (const ImageBinding &imageBinding : shaderProgram->getState().getImageBindings())
315             {
316                 mState.mExecutable->mGraphicsImageBindings.emplace_back(imageBinding);
317             }
318 
319             mState.mExecutable->updateActiveImages(shaderProgram->getExecutable());
320         }
321     }
322 
323     const Program *computeProgram = getShaderProgram(ShaderType::Compute);
324     if (computeProgram)
325     {
326         for (const ImageBinding &imageBinding : computeProgram->getState().getImageBindings())
327         {
328             mState.mExecutable->mComputeImageBindings.emplace_back(imageBinding);
329         }
330 
331         mState.mExecutable->setIsCompute(true);
332         mState.mExecutable->updateActiveImages(computeProgram->getExecutable());
333         mState.mExecutable->setIsCompute(false);
334     }
335 }
336 
updateExecutableGeometryProperties()337 void ProgramPipeline::updateExecutableGeometryProperties()
338 {
339     Program *geometryProgram = getShaderProgram(gl::ShaderType::Geometry);
340 
341     if (!geometryProgram)
342     {
343         return;
344     }
345 
346     const ProgramExecutable &geometryExecutable = geometryProgram->getExecutable();
347     mState.mExecutable->mGeometryShaderInputPrimitiveType =
348         geometryExecutable.mGeometryShaderInputPrimitiveType;
349     mState.mExecutable->mGeometryShaderOutputPrimitiveType =
350         geometryExecutable.mGeometryShaderOutputPrimitiveType;
351     mState.mExecutable->mGeometryShaderInvocations = geometryExecutable.mGeometryShaderInvocations;
352     mState.mExecutable->mGeometryShaderMaxVertices = geometryExecutable.mGeometryShaderMaxVertices;
353 }
354 
updateExecutableTessellationProperties()355 void ProgramPipeline::updateExecutableTessellationProperties()
356 {
357     Program *tessControlProgram = getShaderProgram(gl::ShaderType::TessControl);
358     Program *tessEvalProgram    = getShaderProgram(gl::ShaderType::TessEvaluation);
359 
360     if (tessControlProgram)
361     {
362         const ProgramExecutable &tessControlExecutable = tessControlProgram->getExecutable();
363         mState.mExecutable->mTessControlShaderVertices =
364             tessControlExecutable.mTessControlShaderVertices;
365     }
366 
367     if (tessEvalProgram)
368     {
369         const ProgramExecutable &tessEvalExecutable = tessEvalProgram->getExecutable();
370         mState.mExecutable->mTessGenMode            = tessEvalExecutable.mTessGenMode;
371         mState.mExecutable->mTessGenSpacing         = tessEvalExecutable.mTessGenSpacing;
372         mState.mExecutable->mTessGenVertexOrder     = tessEvalExecutable.mTessGenVertexOrder;
373         mState.mExecutable->mTessGenPointMode       = tessEvalExecutable.mTessGenPointMode;
374     }
375 }
376 
updateFragmentInoutRange()377 void ProgramPipeline::updateFragmentInoutRange()
378 {
379     Program *fragmentProgram = getShaderProgram(gl::ShaderType::Fragment);
380 
381     if (!fragmentProgram)
382     {
383         return;
384     }
385 
386     const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
387     mState.mExecutable->mFragmentInoutRange     = fragmentExecutable.mFragmentInoutRange;
388 }
389 
updateLinkedVaryings()390 void ProgramPipeline::updateLinkedVaryings()
391 {
392     // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
393     for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
394     {
395         const Program *shaderProgram = getShaderProgram(shaderType);
396         if (shaderProgram && shaderProgram->isLinked())
397         {
398             const ProgramExecutable &executable = shaderProgram->getExecutable();
399             mState.mExecutable->mLinkedOutputVaryings[shaderType] =
400                 executable.getLinkedOutputVaryings(shaderType);
401             mState.mExecutable->mLinkedInputVaryings[shaderType] =
402                 executable.getLinkedInputVaryings(shaderType);
403         }
404     }
405 
406     const Program *computeProgram = getShaderProgram(ShaderType::Compute);
407     if (computeProgram && computeProgram->isLinked())
408     {
409         const ProgramExecutable &executable = computeProgram->getExecutable();
410         mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
411             executable.getLinkedOutputVaryings(ShaderType::Compute);
412         mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
413             executable.getLinkedInputVaryings(ShaderType::Compute);
414     }
415 }
416 
updateHasBooleans()417 void ProgramPipeline::updateHasBooleans()
418 {
419     // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
420     for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
421     {
422         const Program *shaderProgram = getShaderProgram(shaderType);
423         if (shaderProgram)
424         {
425             const ProgramExecutable &executable = shaderProgram->getExecutable();
426 
427             if (executable.hasUniformBuffers())
428             {
429                 mState.mExecutable->mPipelineHasGraphicsUniformBuffers = true;
430             }
431             if (executable.hasGraphicsStorageBuffers())
432             {
433                 mState.mExecutable->mPipelineHasGraphicsStorageBuffers = true;
434             }
435             if (executable.hasAtomicCounterBuffers())
436             {
437                 mState.mExecutable->mPipelineHasGraphicsAtomicCounterBuffers = true;
438             }
439             if (executable.hasDefaultUniforms())
440             {
441                 mState.mExecutable->mPipelineHasGraphicsDefaultUniforms = true;
442             }
443             if (executable.hasTextures())
444             {
445                 mState.mExecutable->mPipelineHasGraphicsTextures = true;
446             }
447             if (executable.hasGraphicsImages())
448             {
449                 mState.mExecutable->mPipelineHasGraphicsImages = true;
450             }
451         }
452     }
453 
454     const Program *computeProgram = getShaderProgram(ShaderType::Compute);
455     if (computeProgram)
456     {
457         const ProgramExecutable &executable = computeProgram->getExecutable();
458 
459         if (executable.hasUniformBuffers())
460         {
461             mState.mExecutable->mPipelineHasComputeUniformBuffers = true;
462         }
463         if (executable.hasComputeStorageBuffers())
464         {
465             mState.mExecutable->mPipelineHasComputeStorageBuffers = true;
466         }
467         if (executable.hasAtomicCounterBuffers())
468         {
469             mState.mExecutable->mPipelineHasComputeAtomicCounterBuffers = true;
470         }
471         if (executable.hasDefaultUniforms())
472         {
473             mState.mExecutable->mPipelineHasComputeDefaultUniforms = true;
474         }
475         if (executable.hasTextures())
476         {
477             mState.mExecutable->mPipelineHasComputeTextures = true;
478         }
479         if (executable.hasComputeImages())
480         {
481             mState.mExecutable->mPipelineHasComputeImages = true;
482         }
483     }
484 }
485 
updateExecutable()486 void ProgramPipeline::updateExecutable()
487 {
488     mState.mExecutable->reset();
489 
490     // Vertex Shader ProgramExecutable properties
491     updateExecutableAttributes();
492     updateTransformFeedbackMembers();
493     updateShaderStorageBlocks();
494     updateImageBindings();
495 
496     // Geometry Shader ProgramExecutable properties
497     updateExecutableGeometryProperties();
498 
499     // Tessellation Shaders ProgramExecutable properties
500     updateExecutableTessellationProperties();
501 
502     // Fragment Shader ProgramExecutable properties
503     updateFragmentInoutRange();
504 
505     // All Shader ProgramExecutable properties
506     mState.updateExecutableTextures();
507     updateLinkedVaryings();
508 
509     // Must be last, since it queries things updated by earlier functions
510     updateHasBooleans();
511 }
512 
513 // The attached shaders are checked for linking errors by matching up their variables.
514 // Uniform, input and output variables get collected.
515 // The code gets compiled into binaries.
link(const Context * context)516 angle::Result ProgramPipeline::link(const Context *context)
517 {
518     if (mState.mIsLinked)
519     {
520         return angle::Result::Continue;
521     }
522 
523     ProgramMergedVaryings mergedVaryings;
524     ProgramVaryingPacking varyingPacking;
525 
526     if (!getExecutable().isCompute())
527     {
528         InfoLog &infoLog = mState.mExecutable->getInfoLog();
529         infoLog.reset();
530 
531         if (!linkVaryings(infoLog))
532         {
533             return angle::Result::Stop;
534         }
535 
536         if (!LinkValidateProgramGlobalNames(infoLog, *this))
537         {
538             return angle::Result::Stop;
539         }
540 
541         mergedVaryings = GetMergedVaryingsFromShaders(*this, getExecutable());
542         // If separable program objects are in use, the set of attributes captured is taken
543         // from the program object active on the last vertex processing stage.
544         ShaderType lastVertexProcessingStage =
545             gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
546         if (lastVertexProcessingStage == ShaderType::InvalidEnum)
547         {
548             return angle::Result::Stop;
549         }
550 
551         Program *tfProgram = getShaderProgram(lastVertexProcessingStage);
552         ASSERT(tfProgram);
553 
554         if (!tfProgram)
555         {
556             tfProgram = mState.mPrograms[ShaderType::Vertex];
557         }
558 
559         const std::vector<std::string> &transformFeedbackVaryingNames =
560             tfProgram->getState().getTransformFeedbackVaryingNames();
561 
562         if (!mState.mExecutable->linkMergedVaryings(context, *this, mergedVaryings,
563                                                     transformFeedbackVaryingNames, false,
564                                                     &varyingPacking))
565         {
566             return angle::Result::Stop;
567         }
568     }
569 
570     ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
571 
572     mState.mIsLinked = true;
573 
574     return angle::Result::Continue;
575 }
576 
linkVaryings(InfoLog & infoLog) const577 bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
578 {
579     ShaderType previousShaderType = ShaderType::InvalidEnum;
580     for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
581     {
582         Program *program = getShaderProgram(shaderType);
583         ASSERT(program);
584         ProgramExecutable &executable = program->getExecutable();
585 
586         if (previousShaderType != ShaderType::InvalidEnum)
587         {
588             Program *previousProgram = getShaderProgram(previousShaderType);
589             ASSERT(previousProgram);
590             const ProgramExecutable &previousExecutable = previousProgram->getExecutable();
591 
592             if (!LinkValidateShaderInterfaceMatching(
593                     previousExecutable.getLinkedOutputVaryings(previousShaderType),
594                     executable.getLinkedInputVaryings(shaderType), previousShaderType, shaderType,
595                     previousExecutable.getLinkedShaderVersion(previousShaderType),
596                     executable.getLinkedShaderVersion(shaderType), true, infoLog))
597             {
598                 return false;
599             }
600         }
601         previousShaderType = shaderType;
602     }
603 
604     // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
605     // Need to move logic of validating builtin varyings inside the for-loop above.
606     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
607     // can be redeclared in Geometry or Tessellation shaders as well.
608     Program *vertexProgram   = mState.mPrograms[ShaderType::Vertex];
609     Program *fragmentProgram = mState.mPrograms[ShaderType::Fragment];
610     if (!vertexProgram || !fragmentProgram)
611     {
612         return false;
613     }
614     ProgramExecutable &vertexExecutable   = vertexProgram->getExecutable();
615     ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
616     return LinkValidateBuiltInVaryings(
617         vertexExecutable.getLinkedOutputVaryings(ShaderType::Vertex),
618         fragmentExecutable.getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
619         ShaderType::Fragment, vertexExecutable.getLinkedShaderVersion(ShaderType::Vertex),
620         fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment), infoLog);
621 }
622 
validate(const gl::Context * context)623 void ProgramPipeline::validate(const gl::Context *context)
624 {
625     const Caps &caps = context->getCaps();
626     mState.mValid    = true;
627     InfoLog &infoLog = mState.mExecutable->getInfoLog();
628     infoLog.reset();
629 
630     for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
631     {
632         Program *shaderProgram = mState.mPrograms[shaderType];
633         if (shaderProgram)
634         {
635             shaderProgram->resolveLink(context);
636             shaderProgram->validate(caps);
637             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
638             if (shaderInfoString.length())
639             {
640                 mState.mValid = false;
641                 infoLog << shaderInfoString << "\n";
642                 return;
643             }
644             if (!shaderProgram->isSeparable())
645             {
646                 mState.mValid = false;
647                 infoLog << GetShaderTypeString(shaderType) << " is not marked separable."
648                         << "\n";
649                 return;
650             }
651         }
652     }
653 
654     if (!linkVaryings(infoLog))
655     {
656         mState.mValid = false;
657 
658         for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
659         {
660             Program *shaderProgram = mState.mPrograms[shaderType];
661             ASSERT(shaderProgram);
662             shaderProgram->validate(caps);
663             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
664             if (shaderInfoString.length())
665             {
666                 infoLog << shaderInfoString << "\n";
667             }
668         }
669     }
670 }
671 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)672 void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
673 {
674     switch (message)
675     {
676         case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
677             mState.mIsLinked = false;
678             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
679             mState.updateExecutableTextures();
680             break;
681         case angle::SubjectMessage::ProgramRelinked:
682             mState.mIsLinked = false;
683             updateExecutable();
684             break;
685         case angle::SubjectMessage::SamplerUniformsUpdated:
686             getExecutable().resetCachedValidateSamplersResult();
687             break;
688         default:
689             UNREACHABLE();
690             break;
691     }
692 }
693 
getAttachedShader(ShaderType shaderType) const694 Shader *ProgramPipeline::getAttachedShader(ShaderType shaderType) const
695 {
696     const Program *program = mState.mPrograms[shaderType];
697     return program ? program->getAttachedShader(shaderType) : nullptr;
698 }
699 }  // namespace gl
700