• 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,const gl::ShaderBitSet & shaderTypes,Program * shaderProgram,std::vector<angle::ObserverBinding> * programObserverBindings)89 void ProgramPipelineState::useProgramStages(
90     const Context *context,
91     const gl::ShaderBitSet &shaderTypes,
92     Program *shaderProgram,
93     std::vector<angle::ObserverBinding> *programObserverBindings)
94 {
95     for (ShaderType shaderType : shaderTypes)
96     {
97         useProgramStage(context, shaderType, shaderProgram,
98                         &programObserverBindings->at(static_cast<size_t>(shaderType)));
99     }
100 }
101 
usesShaderProgram(ShaderProgramID programId) const102 bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
103 {
104     for (const Program *program : mPrograms)
105     {
106         if (program && (program->id() == programId))
107         {
108             return true;
109         }
110     }
111 
112     return false;
113 }
114 
updateExecutableTextures()115 void ProgramPipelineState::updateExecutableTextures()
116 {
117     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
118     {
119         const Program *program = getShaderProgram(shaderType);
120         ASSERT(program);
121         mExecutable->setActiveTextureMask(mExecutable->getActiveSamplersMask() |
122                                           program->getExecutable().getActiveSamplersMask());
123         mExecutable->setActiveImagesMask(mExecutable->getActiveImagesMask() |
124                                          program->getExecutable().getActiveImagesMask());
125         // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
126         mExecutable->updateActiveSamplers(program->getState());
127     }
128 }
129 
getSpecConstUsageBits() const130 rx::SpecConstUsageBits ProgramPipelineState::getSpecConstUsageBits() const
131 {
132     rx::SpecConstUsageBits specConstUsageBits;
133     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
134     {
135         const Program *program = getShaderProgram(shaderType);
136         ASSERT(program);
137         specConstUsageBits |= program->getState().getSpecConstUsageBits();
138     }
139     return specConstUsageBits;
140 }
141 
ProgramPipeline(rx::GLImplFactory * factory,ProgramPipelineID handle)142 ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
143     : RefCountObject(factory->generateSerial(), handle),
144       mProgramPipelineImpl(factory->createProgramPipeline(mState)),
145       mExecutableObserverBinding(this, kExecutableSubjectIndex)
146 {
147     ASSERT(mProgramPipelineImpl);
148 
149     for (const ShaderType shaderType : gl::AllShaderTypes())
150     {
151         mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
152     }
153     mExecutableObserverBinding.bind(mState.mExecutable);
154 }
155 
~ProgramPipeline()156 ProgramPipeline::~ProgramPipeline()
157 {
158     mProgramPipelineImpl.reset(nullptr);
159 }
160 
onDestroy(const Context * context)161 void ProgramPipeline::onDestroy(const Context *context)
162 {
163     for (Program *program : mState.mPrograms)
164     {
165         if (program)
166         {
167             ASSERT(program->getRefCount());
168             program->release(context);
169         }
170     }
171 
172     getImplementation()->destroy(context);
173 }
174 
setLabel(const Context * context,const std::string & label)175 angle::Result ProgramPipeline::setLabel(const Context *context, const std::string &label)
176 {
177     mState.mLabel = label;
178 
179     if (mProgramPipelineImpl)
180     {
181         return mProgramPipelineImpl->onLabelUpdate(context);
182     }
183     return angle::Result::Continue;
184 }
185 
getLabel() const186 const std::string &ProgramPipeline::getLabel() const
187 {
188     return mState.mLabel;
189 }
190 
getImplementation() const191 rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
192 {
193     return mProgramPipelineImpl.get();
194 }
195 
activeShaderProgram(Program * shaderProgram)196 void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
197 {
198     mState.activeShaderProgram(shaderProgram);
199 }
200 
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)201 angle::Result ProgramPipeline::useProgramStages(const Context *context,
202                                                 GLbitfield stages,
203                                                 Program *shaderProgram)
204 {
205     bool needToUpdatePipelineState = false;
206     gl::ShaderBitSet shaderTypes;
207     if (stages != GL_ALL_SHADER_BITS)
208     {
209         ASSERT(stages < 256u);
210         for (size_t singleShaderBit : angle::BitSet<8>(stages))
211         {
212             // Cast back to a bit after the iterator returns an index.
213             ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
214             ASSERT(shaderType != ShaderType::InvalidEnum);
215             shaderTypes.set(shaderType);
216         }
217     }
218     else
219     {
220         shaderTypes.set();
221     }
222     ASSERT(shaderTypes.any());
223 
224     for (ShaderType shaderType : shaderTypes)
225     {
226         if (mState.getShaderProgram(shaderType) != shaderProgram ||
227             (shaderProgram && shaderProgram->hasAnyDirtyBit()))
228         {
229             needToUpdatePipelineState = true;
230             break;
231         }
232     }
233 
234     if (!needToUpdatePipelineState)
235     {
236         return angle::Result::Continue;
237     }
238 
239     mState.useProgramStages(context, shaderTypes, shaderProgram, &mProgramObserverBindings);
240     updateLinkedShaderStages();
241 
242     mState.mIsLinked = false;
243     onStateChange(angle::SubjectMessage::SubjectChanged);
244 
245     return angle::Result::Continue;
246 }
247 
updateLinkedShaderStages()248 void ProgramPipeline::updateLinkedShaderStages()
249 {
250     mState.mExecutable->resetLinkedShaderStages();
251 
252     for (const ShaderType shaderType : gl::AllShaderTypes())
253     {
254         Program *program = mState.mPrograms[shaderType];
255         if (program)
256         {
257             mState.mExecutable->setLinkedShaderStages(shaderType);
258         }
259     }
260 
261     mState.mExecutable->updateCanDrawWith();
262 }
263 
updateExecutableAttributes()264 void ProgramPipeline::updateExecutableAttributes()
265 {
266     Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
267 
268     if (!vertexProgram)
269     {
270         return;
271     }
272 
273     const ProgramExecutable &vertexExecutable      = vertexProgram->getExecutable();
274     mState.mExecutable->mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
275     mState.mExecutable->mMaxActiveAttribLocation   = vertexExecutable.mMaxActiveAttribLocation;
276     mState.mExecutable->mAttributesTypeMask        = vertexExecutable.mAttributesTypeMask;
277     mState.mExecutable->mAttributesMask            = vertexExecutable.mAttributesMask;
278     mState.mExecutable->mProgramInputs             = vertexExecutable.mProgramInputs;
279 }
280 
updateTransformFeedbackMembers()281 void ProgramPipeline::updateTransformFeedbackMembers()
282 {
283     ShaderType lastVertexProcessingStage =
284         gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
285     if (lastVertexProcessingStage == ShaderType::InvalidEnum)
286     {
287         return;
288     }
289 
290     Program *shaderProgram = getShaderProgram(lastVertexProcessingStage);
291     ASSERT(shaderProgram);
292 
293     const ProgramExecutable &lastPreFragmentExecutable = shaderProgram->getExecutable();
294     mState.mExecutable->mTransformFeedbackStrides =
295         lastPreFragmentExecutable.mTransformFeedbackStrides;
296     mState.mExecutable->mLinkedTransformFeedbackVaryings =
297         lastPreFragmentExecutable.mLinkedTransformFeedbackVaryings;
298 }
299 
updateShaderStorageBlocks()300 void ProgramPipeline::updateShaderStorageBlocks()
301 {
302     mState.mExecutable->mShaderStorageBlocks.clear();
303 
304     // Only copy the storage blocks from each Program in the PPO once, since each Program could
305     // contain multiple shader stages.
306     ShaderBitSet handledStages;
307 
308     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
309     {
310         const Program *shaderProgram = getShaderProgram(shaderType);
311         if (shaderProgram && !handledStages.test(shaderType))
312         {
313             // Only add each Program's blocks once.
314             handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
315 
316             for (const InterfaceBlock &block :
317                  shaderProgram->getExecutable().getShaderStorageBlocks())
318             {
319                 mState.mExecutable->mShaderStorageBlocks.emplace_back(block);
320             }
321         }
322     }
323 }
324 
updateImageBindings()325 void ProgramPipeline::updateImageBindings()
326 {
327     mState.mExecutable->mImageBindings.clear();
328     mState.mExecutable->mActiveImageShaderBits.fill({});
329 
330     // Only copy the storage blocks from each Program in the PPO once, since each Program could
331     // contain multiple shader stages.
332     ShaderBitSet handledStages;
333 
334     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
335     {
336         const Program *shaderProgram = getShaderProgram(shaderType);
337         if (shaderProgram && !handledStages.test(shaderType))
338         {
339             // Only add each Program's blocks once.
340             handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
341 
342             for (const ImageBinding &imageBinding : shaderProgram->getState().getImageBindings())
343             {
344                 mState.mExecutable->mImageBindings.emplace_back(imageBinding);
345             }
346 
347             mState.mExecutable->updateActiveImages(shaderProgram->getExecutable());
348         }
349     }
350 }
351 
updateExecutableGeometryProperties()352 void ProgramPipeline::updateExecutableGeometryProperties()
353 {
354     Program *geometryProgram = getShaderProgram(gl::ShaderType::Geometry);
355 
356     if (!geometryProgram)
357     {
358         return;
359     }
360 
361     const ProgramExecutable &geometryExecutable = geometryProgram->getExecutable();
362     mState.mExecutable->mGeometryShaderInputPrimitiveType =
363         geometryExecutable.mGeometryShaderInputPrimitiveType;
364     mState.mExecutable->mGeometryShaderOutputPrimitiveType =
365         geometryExecutable.mGeometryShaderOutputPrimitiveType;
366     mState.mExecutable->mGeometryShaderInvocations = geometryExecutable.mGeometryShaderInvocations;
367     mState.mExecutable->mGeometryShaderMaxVertices = geometryExecutable.mGeometryShaderMaxVertices;
368 }
369 
updateExecutableTessellationProperties()370 void ProgramPipeline::updateExecutableTessellationProperties()
371 {
372     Program *tessControlProgram = getShaderProgram(gl::ShaderType::TessControl);
373     Program *tessEvalProgram    = getShaderProgram(gl::ShaderType::TessEvaluation);
374 
375     if (tessControlProgram)
376     {
377         const ProgramExecutable &tessControlExecutable = tessControlProgram->getExecutable();
378         mState.mExecutable->mTessControlShaderVertices =
379             tessControlExecutable.mTessControlShaderVertices;
380     }
381 
382     if (tessEvalProgram)
383     {
384         const ProgramExecutable &tessEvalExecutable = tessEvalProgram->getExecutable();
385         mState.mExecutable->mTessGenMode            = tessEvalExecutable.mTessGenMode;
386         mState.mExecutable->mTessGenSpacing         = tessEvalExecutable.mTessGenSpacing;
387         mState.mExecutable->mTessGenVertexOrder     = tessEvalExecutable.mTessGenVertexOrder;
388         mState.mExecutable->mTessGenPointMode       = tessEvalExecutable.mTessGenPointMode;
389     }
390 }
391 
updateFragmentInoutRangeAndEnablesPerSampleShading()392 void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
393 {
394     Program *fragmentProgram = getShaderProgram(gl::ShaderType::Fragment);
395 
396     if (!fragmentProgram)
397     {
398         return;
399     }
400 
401     const ProgramExecutable &fragmentExecutable  = fragmentProgram->getExecutable();
402     mState.mExecutable->mFragmentInoutRange      = fragmentExecutable.mFragmentInoutRange;
403     mState.mExecutable->mHasDiscard              = fragmentExecutable.mHasDiscard;
404     mState.mExecutable->mEnablesPerSampleShading = fragmentExecutable.mEnablesPerSampleShading;
405 }
406 
updateLinkedVaryings()407 void ProgramPipeline::updateLinkedVaryings()
408 {
409     // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
410     for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
411     {
412         const Program *shaderProgram = getShaderProgram(shaderType);
413         if (shaderProgram && shaderProgram->isLinked())
414         {
415             const ProgramExecutable &executable = shaderProgram->getExecutable();
416             mState.mExecutable->mLinkedOutputVaryings[shaderType] =
417                 executable.getLinkedOutputVaryings(shaderType);
418             mState.mExecutable->mLinkedInputVaryings[shaderType] =
419                 executable.getLinkedInputVaryings(shaderType);
420         }
421     }
422 
423     const Program *computeProgram = getShaderProgram(ShaderType::Compute);
424     if (computeProgram && computeProgram->isLinked())
425     {
426         const ProgramExecutable &executable = computeProgram->getExecutable();
427         mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
428             executable.getLinkedOutputVaryings(ShaderType::Compute);
429         mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
430             executable.getLinkedInputVaryings(ShaderType::Compute);
431     }
432 }
433 
updateExecutable()434 void ProgramPipeline::updateExecutable()
435 {
436     // Vertex Shader ProgramExecutable properties
437     updateExecutableAttributes();
438     updateTransformFeedbackMembers();
439     updateShaderStorageBlocks();
440     updateImageBindings();
441 
442     // Geometry Shader ProgramExecutable properties
443     updateExecutableGeometryProperties();
444 
445     // Tessellation Shaders ProgramExecutable properties
446     updateExecutableTessellationProperties();
447 
448     // Fragment Shader ProgramExecutable properties
449     updateFragmentInoutRangeAndEnablesPerSampleShading();
450 
451     // All Shader ProgramExecutable properties
452     mState.updateExecutableTextures();
453     updateLinkedVaryings();
454 }
455 
456 // The attached shaders are checked for linking errors by matching up their variables.
457 // Uniform, input and output variables get collected.
458 // The code gets compiled into binaries.
link(const Context * context)459 angle::Result ProgramPipeline::link(const Context *context)
460 {
461     ASSERT(!mState.mIsLinked);
462 
463     ProgramMergedVaryings mergedVaryings;
464     ProgramVaryingPacking varyingPacking;
465     LinkingVariables linkingVariables(mState);
466 
467     mState.mExecutable->reset(true);
468 
469     InfoLog &infoLog = mState.mExecutable->getInfoLog();
470     infoLog.reset();
471 
472     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex))
473     {
474         if (!linkVaryings(infoLog))
475         {
476             return angle::Result::Stop;
477         }
478 
479         if (!LinkValidateProgramGlobalNames(infoLog, getExecutable(), linkingVariables))
480         {
481             return angle::Result::Stop;
482         }
483 
484         Program *fragmentShaderProgram = getShaderProgram(ShaderType::Fragment);
485         if (fragmentShaderProgram)
486         {
487             // We should also be validating SSBO and image uniform counts.
488             const GLuint combinedImageUniforms          = 0;
489             const GLuint combinedShaderStorageBlocks    = 0;
490             const ProgramExecutable &fragmentExecutable = fragmentShaderProgram->getExecutable();
491             if (!mState.mExecutable->linkValidateOutputVariables(
492                     context->getCaps(), context->getExtensions(), context->getClientVersion(),
493                     combinedImageUniforms, combinedShaderStorageBlocks,
494                     fragmentExecutable.getOutputVariables(),
495                     fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment),
496                     ProgramAliasedBindings(), ProgramAliasedBindings()))
497             {
498                 return angle::Result::Continue;
499             }
500         }
501         mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
502         // If separable program objects are in use, the set of attributes captured is taken
503         // from the program object active on the last vertex processing stage.
504         ShaderType lastVertexProcessingStage =
505             gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
506         if (lastVertexProcessingStage == ShaderType::InvalidEnum)
507         {
508             //  If there is no active program for the vertex or fragment shader stages, the results
509             //  of vertex and fragment shader execution will respectively be undefined. However,
510             //  this is not an error.
511             return angle::Result::Continue;
512         }
513 
514         Program *tfProgram = getShaderProgram(lastVertexProcessingStage);
515         ASSERT(tfProgram);
516 
517         if (!tfProgram)
518         {
519             tfProgram = mState.mPrograms[ShaderType::Vertex];
520         }
521 
522         const std::vector<std::string> &transformFeedbackVaryingNames =
523             tfProgram->getState().getTransformFeedbackVaryingNames();
524 
525         if (!mState.mExecutable->linkMergedVaryings(context, mergedVaryings,
526                                                     transformFeedbackVaryingNames, linkingVariables,
527                                                     false, &varyingPacking))
528         {
529             return angle::Result::Stop;
530         }
531     }
532 
533     // Merge uniforms.
534     mState.mExecutable->copyUniformsFromProgramMap(mState.mPrograms);
535 
536     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex))
537     {
538         const ProgramState &programState = mState.mPrograms[gl::ShaderType::Vertex]->getState();
539         mState.mExecutable->copyInputsFromProgram(programState);
540     }
541 
542     // Merge shader buffers (UBOs, SSBOs, and atomic counter buffers) into the executable.
543     // Also copy over image and sampler bindings.
544     for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
545     {
546         const ProgramState &programState = mState.mPrograms[shaderType]->getState();
547         mState.mExecutable->copyShaderBuffersFromProgram(programState, shaderType);
548         mState.mExecutable->copySamplerBindingsFromProgram(programState);
549         mState.mExecutable->copyImageBindingsFromProgram(programState);
550     }
551 
552     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Fragment))
553     {
554         const ProgramState &programState = mState.mPrograms[gl::ShaderType::Fragment]->getState();
555         mState.mExecutable->copyOutputsFromProgram(programState);
556     }
557 
558     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex) ||
559         mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute))
560     {
561         ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
562     }
563 
564     mState.mExecutable->mActiveSamplerRefCounts.fill(0);
565     updateExecutable();
566 
567     mState.mIsLinked = true;
568     onStateChange(angle::SubjectMessage::SubjectChanged);
569 
570     return angle::Result::Continue;
571 }
572 
linkVaryings(InfoLog & infoLog) const573 bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
574 {
575     ShaderType previousShaderType = ShaderType::InvalidEnum;
576     for (ShaderType shaderType : kAllGraphicsShaderTypes)
577     {
578         Program *program = getShaderProgram(shaderType);
579         if (!program)
580         {
581             continue;
582         }
583         ProgramExecutable &executable = program->getExecutable();
584 
585         if (previousShaderType != ShaderType::InvalidEnum)
586         {
587             Program *previousProgram = getShaderProgram(previousShaderType);
588             ASSERT(previousProgram);
589             const ProgramExecutable &previousExecutable = previousProgram->getExecutable();
590 
591             if (!LinkValidateShaderInterfaceMatching(
592                     previousExecutable.getLinkedOutputVaryings(previousShaderType),
593                     executable.getLinkedInputVaryings(shaderType), previousShaderType, shaderType,
594                     previousExecutable.getLinkedShaderVersion(previousShaderType),
595                     executable.getLinkedShaderVersion(shaderType), true, infoLog))
596             {
597                 return false;
598             }
599         }
600         previousShaderType = shaderType;
601     }
602 
603     // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
604     // Need to move logic of validating builtin varyings inside the for-loop above.
605     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
606     // can be redeclared in Geometry or Tessellation shaders as well.
607     Program *vertexProgram   = mState.mPrograms[ShaderType::Vertex];
608     Program *fragmentProgram = mState.mPrograms[ShaderType::Fragment];
609     if (!vertexProgram || !fragmentProgram)
610     {
611         return true;
612     }
613     ProgramExecutable &vertexExecutable   = vertexProgram->getExecutable();
614     ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
615     return LinkValidateBuiltInVaryings(
616         vertexExecutable.getLinkedOutputVaryings(ShaderType::Vertex),
617         fragmentExecutable.getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
618         ShaderType::Fragment, vertexExecutable.getLinkedShaderVersion(ShaderType::Vertex),
619         fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment), infoLog);
620 }
621 
validate(const gl::Context * context)622 void ProgramPipeline::validate(const gl::Context *context)
623 {
624     const Caps &caps = context->getCaps();
625     mState.mValid    = true;
626     InfoLog &infoLog = mState.mExecutable->getInfoLog();
627     infoLog.reset();
628 
629     for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
630     {
631         Program *shaderProgram = mState.mPrograms[shaderType];
632         if (shaderProgram)
633         {
634             shaderProgram->resolveLink(context);
635             shaderProgram->validate(caps);
636             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
637             if (shaderInfoString.length())
638             {
639                 mState.mValid = false;
640                 infoLog << shaderInfoString << "\n";
641                 return;
642             }
643             if (!shaderProgram->isSeparable())
644             {
645                 mState.mValid = false;
646                 infoLog << GetShaderTypeString(shaderType) << " is not marked separable."
647                         << "\n";
648                 return;
649             }
650         }
651     }
652 
653     intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context);
654     if (programPipelineError)
655     {
656         mState.mValid            = false;
657         const char *errorMessage = reinterpret_cast<const char *>(programPipelineError);
658         infoLog << errorMessage << "\n";
659         return;
660     }
661 
662     if (!linkVaryings(infoLog))
663     {
664         mState.mValid = false;
665 
666         for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
667         {
668             Program *shaderProgram = mState.mPrograms[shaderType];
669             ASSERT(shaderProgram);
670             shaderProgram->validate(caps);
671             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
672             if (shaderInfoString.length())
673             {
674                 infoLog << shaderInfoString << "\n";
675             }
676         }
677     }
678 }
679 
syncState(const Context * context)680 angle::Result ProgramPipeline::syncState(const Context *context)
681 {
682     Program::DirtyBits dirtyBits;
683     for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
684     {
685         Program *shaderProgram = mState.mPrograms[shaderType];
686         if (shaderProgram)
687         {
688             dirtyBits |= shaderProgram->mDirtyBits;
689         }
690     }
691     if (dirtyBits.any())
692     {
693         ANGLE_TRY(mProgramPipelineImpl->syncState(context, dirtyBits));
694     }
695 
696     return angle::Result::Continue;
697 }
698 
onUniformBufferStateChange(size_t uniformBufferIndex)699 void ProgramPipeline::onUniformBufferStateChange(size_t uniformBufferIndex)
700 {
701     for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
702     {
703         Program *shaderProgram = mState.mPrograms[shaderType];
704         if (shaderProgram)
705         {
706             shaderProgram->onUniformBufferStateChange(uniformBufferIndex);
707         }
708     }
709 }
710 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)711 void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
712 {
713     switch (message)
714     {
715         case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
716             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
717             mState.updateExecutableTextures();
718             break;
719 
720         case angle::SubjectMessage::ProgramRelinked:
721             mState.mIsLinked = false;
722             onStateChange(angle::SubjectMessage::ProgramRelinked);
723             break;
724         case angle::SubjectMessage::SamplerUniformsUpdated:
725             mState.mExecutable->clearSamplerBindings();
726             for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
727             {
728                 const ProgramState &programState = mState.mPrograms[shaderType]->getState();
729                 mState.mExecutable->copySamplerBindingsFromProgram(programState);
730             }
731             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
732             mState.updateExecutableTextures();
733             break;
734         case angle::SubjectMessage::ProgramUniformUpdated:
735             mProgramPipelineImpl->onProgramUniformUpdate(static_cast<ShaderType>(index));
736             break;
737         default:
738             UNREACHABLE();
739             break;
740     }
741 }
742 }  // namespace gl
743