• 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/ContextImpl.h"
19 #include "libANGLE/renderer/ProgramPipelineImpl.h"
20 
21 namespace gl
22 {
23 
ProgramPipelineState(rx::GLImplFactory * factory)24 ProgramPipelineState::ProgramPipelineState(rx::GLImplFactory *factory)
25     : mLabel(),
26       mActiveShaderProgram(nullptr),
27       mValid(false),
28       mExecutable(makeNewExecutable(factory, {})),
29       mIsLinked(false)
30 {
31     for (const ShaderType shaderType : AllShaderTypes())
32     {
33         mPrograms[shaderType] = nullptr;
34     }
35 }
36 
~ProgramPipelineState()37 ProgramPipelineState::~ProgramPipelineState() {}
38 
getLabel() const39 const std::string &ProgramPipelineState::getLabel() const
40 {
41     return mLabel;
42 }
43 
activeShaderProgram(Program * shaderProgram)44 void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
45 {
46     mActiveShaderProgram = shaderProgram;
47 }
48 
makeNewExecutable(rx::GLImplFactory * factory,ShaderMap<SharedProgramExecutable> && ppoProgramExecutables)49 SharedProgramExecutable ProgramPipelineState::makeNewExecutable(
50     rx::GLImplFactory *factory,
51     ShaderMap<SharedProgramExecutable> &&ppoProgramExecutables)
52 {
53     SharedProgramExecutable newExecutable = std::make_shared<ProgramExecutable>(factory, &mInfoLog);
54     newExecutable->mIsPPO                 = true;
55     newExecutable->mPPOProgramExecutables = std::move(ppoProgramExecutables);
56     return newExecutable;
57 }
58 
useProgramStage(const Context * context,const ShaderType shaderType,Program * shaderProgram,angle::ObserverBinding * programObserverBinding,angle::ObserverBinding * programExecutableObserverBinding)59 void ProgramPipelineState::useProgramStage(const Context *context,
60                                            const ShaderType shaderType,
61                                            Program *shaderProgram,
62                                            angle::ObserverBinding *programObserverBinding,
63                                            angle::ObserverBinding *programExecutableObserverBinding)
64 {
65     Program *oldProgram = mPrograms[shaderType];
66     if (oldProgram)
67     {
68         oldProgram->release(context);
69     }
70 
71     // If program refers to a program object with a valid shader attached for the indicated shader
72     // stage, glUseProgramStages installs the executable code for that stage in the indicated
73     // program pipeline object pipeline.
74     if (shaderProgram && (shaderProgram->id().value != 0) &&
75         shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
76     {
77         mPrograms[shaderType] = shaderProgram;
78         // Install the program executable, if not already
79         if (shaderProgram->getSharedExecutable().get() !=
80             mExecutable->mPPOProgramExecutables[shaderType].get())
81         {
82             InstallExecutable(context, shaderProgram->getSharedExecutable(),
83                               &mExecutable->mPPOProgramExecutables[shaderType]);
84         }
85         shaderProgram->addRef();
86     }
87     else
88     {
89         // If program is zero, or refers to a program object with no valid shader executable for the
90         // given stage, it is as if the pipeline object has no programmable stage configured for the
91         // indicated shader stage.
92         mPrograms[shaderType] = nullptr;
93         UninstallExecutable(context, &mExecutable->mPPOProgramExecutables[shaderType]);
94     }
95 
96     programObserverBinding->bind(mPrograms[shaderType]);
97     programExecutableObserverBinding->bind(mExecutable->mPPOProgramExecutables[shaderType].get());
98 }
99 
useProgramStages(const Context * context,const ShaderBitSet & shaderTypes,Program * shaderProgram,std::vector<angle::ObserverBinding> * programObserverBindings,std::vector<angle::ObserverBinding> * programExecutableObserverBindings)100 void ProgramPipelineState::useProgramStages(
101     const Context *context,
102     const ShaderBitSet &shaderTypes,
103     Program *shaderProgram,
104     std::vector<angle::ObserverBinding> *programObserverBindings,
105     std::vector<angle::ObserverBinding> *programExecutableObserverBindings)
106 {
107     for (ShaderType shaderType : shaderTypes)
108     {
109         useProgramStage(context, shaderType, shaderProgram,
110                         &programObserverBindings->at(static_cast<size_t>(shaderType)),
111                         &programExecutableObserverBindings->at(static_cast<size_t>(shaderType)));
112     }
113 }
114 
usesShaderProgram(ShaderProgramID programId) const115 bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
116 {
117     for (const Program *program : mPrograms)
118     {
119         if (program && (program->id() == programId))
120         {
121             return true;
122         }
123     }
124 
125     return false;
126 }
127 
updateExecutableTextures()128 void ProgramPipelineState::updateExecutableTextures()
129 {
130     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
131     {
132         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
133         ASSERT(programExecutable);
134         mExecutable->setActiveTextureMask(mExecutable->getActiveSamplersMask() |
135                                           programExecutable->getActiveSamplersMask());
136         mExecutable->setActiveImagesMask(mExecutable->getActiveImagesMask() |
137                                          programExecutable->getActiveImagesMask());
138         // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
139         mExecutable->updateActiveSamplers(*programExecutable);
140     }
141 }
142 
updateExecutableSpecConstUsageBits()143 void ProgramPipelineState::updateExecutableSpecConstUsageBits()
144 {
145     rx::SpecConstUsageBits specConstUsageBits;
146     for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
147     {
148         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
149         ASSERT(programExecutable);
150         specConstUsageBits |= programExecutable->getSpecConstUsageBits();
151     }
152     mExecutable->mPod.specConstUsageBits = specConstUsageBits;
153 }
154 
ProgramPipeline(rx::GLImplFactory * factory,ProgramPipelineID handle)155 ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
156     : RefCountObject(factory->generateSerial(), handle),
157       mProgramPipelineImpl(factory->createProgramPipeline(mState)),
158       mState(factory)
159 {
160     ASSERT(mProgramPipelineImpl);
161 
162     for (const ShaderType shaderType : AllShaderTypes())
163     {
164         mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
165         mProgramExecutableObserverBindings.emplace_back(
166             this, static_cast<angle::SubjectIndex>(shaderType));
167     }
168 }
169 
~ProgramPipeline()170 ProgramPipeline::~ProgramPipeline()
171 {
172     mProgramPipelineImpl.reset(nullptr);
173 }
174 
onDestroy(const Context * context)175 void ProgramPipeline::onDestroy(const Context *context)
176 {
177     for (Program *program : mState.mPrograms)
178     {
179         if (program)
180         {
181             ASSERT(program->getRefCount());
182             program->release(context);
183         }
184     }
185 
186     getImplementation()->destroy(context);
187     UninstallExecutable(context, &mState.mExecutable);
188 
189     mState.destroyDiscardedExecutables(context);
190 }
191 
destroyDiscardedExecutables(const Context * context)192 void ProgramPipelineState::destroyDiscardedExecutables(const Context *context)
193 {
194     for (SharedProgramExecutable &executable : mProgramExecutablesToDiscard)
195     {
196         UninstallExecutable(context, &executable);
197     }
198     mProgramExecutablesToDiscard.clear();
199 }
200 
setLabel(const Context * context,const std::string & label)201 angle::Result ProgramPipeline::setLabel(const Context *context, const std::string &label)
202 {
203     mState.mLabel = label;
204 
205     if (mProgramPipelineImpl)
206     {
207         return mProgramPipelineImpl->onLabelUpdate(context);
208     }
209     return angle::Result::Continue;
210 }
211 
getLabel() const212 const std::string &ProgramPipeline::getLabel() const
213 {
214     return mState.mLabel;
215 }
216 
getImplementation() const217 rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
218 {
219     return mProgramPipelineImpl.get();
220 }
221 
activeShaderProgram(Program * shaderProgram)222 void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
223 {
224     mState.activeShaderProgram(shaderProgram);
225 }
226 
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)227 angle::Result ProgramPipeline::useProgramStages(const Context *context,
228                                                 GLbitfield stages,
229                                                 Program *shaderProgram)
230 {
231     ShaderBitSet shaderTypes;
232     if (stages != GL_ALL_SHADER_BITS)
233     {
234         ASSERT(stages < 256u);
235         for (size_t singleShaderBit : angle::BitSet<8>(stages))
236         {
237             // Cast back to a bit after the iterator returns an index.
238             ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
239             ASSERT(shaderType != ShaderType::InvalidEnum);
240             shaderTypes.set(shaderType);
241         }
242     }
243     else
244     {
245         shaderTypes.set();
246     }
247     ASSERT(shaderTypes.any());
248 
249     bool needToUpdatePipelineState = false;
250     for (ShaderType shaderType : shaderTypes)
251     {
252         if (mState.getShaderProgram(shaderType) != shaderProgram ||
253             (shaderProgram &&
254              getShaderProgramExecutable(shaderType) != shaderProgram->getSharedExecutable()))
255         {
256             needToUpdatePipelineState = true;
257             break;
258         }
259     }
260 
261     if (!needToUpdatePipelineState)
262     {
263         return angle::Result::Continue;
264     }
265 
266     mState.useProgramStages(context, shaderTypes, shaderProgram, &mProgramObserverBindings,
267                             &mProgramExecutableObserverBindings);
268 
269     mState.mIsLinked = false;
270     onStateChange(angle::SubjectMessage::ProgramUnlinked);
271 
272     return angle::Result::Continue;
273 }
274 
updateLinkedShaderStages()275 void ProgramPipeline::updateLinkedShaderStages()
276 {
277     mState.mExecutable->resetLinkedShaderStages();
278 
279     for (const ShaderType shaderType : AllShaderTypes())
280     {
281         if (getShaderProgramExecutable(shaderType))
282         {
283             mState.mExecutable->setLinkedShaderStages(shaderType);
284         }
285     }
286 
287     mState.mExecutable->updateCanDrawWith();
288 }
289 
updateExecutableAttributes()290 void ProgramPipeline::updateExecutableAttributes()
291 {
292     const SharedProgramExecutable &vertexExecutable =
293         getShaderProgramExecutable(ShaderType::Vertex);
294 
295     if (!vertexExecutable)
296     {
297         return;
298     }
299 
300     mState.mExecutable->mPod.activeAttribLocationsMask =
301         vertexExecutable->mPod.activeAttribLocationsMask;
302     mState.mExecutable->mPod.maxActiveAttribLocation =
303         vertexExecutable->mPod.maxActiveAttribLocation;
304     mState.mExecutable->mPod.attributesTypeMask = vertexExecutable->mPod.attributesTypeMask;
305     mState.mExecutable->mPod.attributesMask     = vertexExecutable->mPod.attributesMask;
306     mState.mExecutable->mProgramInputs          = vertexExecutable->mProgramInputs;
307 
308     mState.mExecutable->mPod.numViews             = vertexExecutable->mPod.numViews;
309     mState.mExecutable->mPod.drawIDLocation       = vertexExecutable->mPod.drawIDLocation;
310     mState.mExecutable->mPod.baseVertexLocation   = vertexExecutable->mPod.baseVertexLocation;
311     mState.mExecutable->mPod.baseInstanceLocation = vertexExecutable->mPod.baseInstanceLocation;
312 }
313 
updateTransformFeedbackMembers()314 void ProgramPipeline::updateTransformFeedbackMembers()
315 {
316     ShaderType lastVertexProcessingStage =
317         GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
318     if (lastVertexProcessingStage == ShaderType::InvalidEnum)
319     {
320         return;
321     }
322 
323     const SharedProgramExecutable &lastPreFragmentExecutable =
324         getShaderProgramExecutable(lastVertexProcessingStage);
325     ASSERT(lastPreFragmentExecutable);
326 
327     mState.mExecutable->mTransformFeedbackStrides =
328         lastPreFragmentExecutable->mTransformFeedbackStrides;
329     mState.mExecutable->mLinkedTransformFeedbackVaryings =
330         lastPreFragmentExecutable->mLinkedTransformFeedbackVaryings;
331 }
332 
updateShaderStorageBlocks()333 void ProgramPipeline::updateShaderStorageBlocks()
334 {
335     mState.mExecutable->mShaderStorageBlocks.clear();
336 
337     // Only copy the storage blocks from each Program in the PPO once, since each Program could
338     // contain multiple shader stages.
339     ShaderBitSet handledStages;
340 
341     for (const ShaderType shaderType : AllShaderTypes())
342     {
343         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
344         if (programExecutable && !handledStages.test(shaderType))
345         {
346             // Only add each Program's blocks once.
347             handledStages |= programExecutable->getLinkedShaderStages();
348 
349             for (const InterfaceBlock &block : programExecutable->getShaderStorageBlocks())
350             {
351                 mState.mExecutable->mShaderStorageBlocks.emplace_back(block);
352             }
353         }
354     }
355 }
356 
updateImageBindings()357 void ProgramPipeline::updateImageBindings()
358 {
359     mState.mExecutable->mImageBindings.clear();
360     mState.mExecutable->mActiveImageShaderBits.fill({});
361 
362     // Only copy the storage blocks from each Program in the PPO once, since each Program could
363     // contain multiple shader stages.
364     ShaderBitSet handledStages;
365 
366     for (const ShaderType shaderType : AllShaderTypes())
367     {
368         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
369         if (programExecutable && !handledStages.test(shaderType))
370         {
371             // Only add each Program's blocks once.
372             handledStages |= programExecutable->getLinkedShaderStages();
373 
374             for (const ImageBinding &imageBinding : *programExecutable->getImageBindings())
375             {
376                 mState.mExecutable->mImageBindings.emplace_back(imageBinding);
377             }
378 
379             mState.mExecutable->updateActiveImages(*programExecutable);
380         }
381     }
382 }
383 
updateExecutableGeometryProperties()384 void ProgramPipeline::updateExecutableGeometryProperties()
385 {
386     const SharedProgramExecutable &geometryExecutable =
387         getShaderProgramExecutable(ShaderType::Geometry);
388 
389     if (!geometryExecutable)
390     {
391         return;
392     }
393 
394     mState.mExecutable->mPod.geometryShaderInputPrimitiveType =
395         geometryExecutable->mPod.geometryShaderInputPrimitiveType;
396     mState.mExecutable->mPod.geometryShaderOutputPrimitiveType =
397         geometryExecutable->mPod.geometryShaderOutputPrimitiveType;
398     mState.mExecutable->mPod.geometryShaderInvocations =
399         geometryExecutable->mPod.geometryShaderInvocations;
400     mState.mExecutable->mPod.geometryShaderMaxVertices =
401         geometryExecutable->mPod.geometryShaderMaxVertices;
402 }
403 
updateExecutableTessellationProperties()404 void ProgramPipeline::updateExecutableTessellationProperties()
405 {
406     const SharedProgramExecutable &tessControlExecutable =
407         getShaderProgramExecutable(ShaderType::TessControl);
408     const SharedProgramExecutable &tessEvalExecutable =
409         getShaderProgramExecutable(ShaderType::TessEvaluation);
410 
411     if (tessControlExecutable)
412     {
413         mState.mExecutable->mPod.tessControlShaderVertices =
414             tessControlExecutable->mPod.tessControlShaderVertices;
415     }
416 
417     if (tessEvalExecutable)
418     {
419         mState.mExecutable->mPod.tessGenMode        = tessEvalExecutable->mPod.tessGenMode;
420         mState.mExecutable->mPod.tessGenSpacing     = tessEvalExecutable->mPod.tessGenSpacing;
421         mState.mExecutable->mPod.tessGenVertexOrder = tessEvalExecutable->mPod.tessGenVertexOrder;
422         mState.mExecutable->mPod.tessGenPointMode   = tessEvalExecutable->mPod.tessGenPointMode;
423     }
424 }
425 
updateFragmentInoutRangeAndEnablesPerSampleShading()426 void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
427 {
428     const SharedProgramExecutable &fragmentExecutable =
429         getShaderProgramExecutable(ShaderType::Fragment);
430 
431     if (!fragmentExecutable)
432     {
433         return;
434     }
435 
436     mState.mExecutable->mPod.fragmentInoutIndices = fragmentExecutable->mPod.fragmentInoutIndices;
437     mState.mExecutable->mPod.hasDiscard           = fragmentExecutable->mPod.hasDiscard;
438     mState.mExecutable->mPod.enablesPerSampleShading =
439         fragmentExecutable->mPod.enablesPerSampleShading;
440 }
441 
updateLinkedVaryings()442 void ProgramPipeline::updateLinkedVaryings()
443 {
444     // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
445     for (const ShaderType shaderType : kAllGraphicsShaderTypes)
446     {
447         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
448         if (programExecutable)
449         {
450             mState.mExecutable->mLinkedOutputVaryings[shaderType] =
451                 programExecutable->getLinkedOutputVaryings(shaderType);
452             mState.mExecutable->mLinkedInputVaryings[shaderType] =
453                 programExecutable->getLinkedInputVaryings(shaderType);
454         }
455     }
456 
457     const SharedProgramExecutable &computeExecutable =
458         getShaderProgramExecutable(ShaderType::Compute);
459     if (computeExecutable)
460     {
461         mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
462             computeExecutable->getLinkedOutputVaryings(ShaderType::Compute);
463         mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
464             computeExecutable->getLinkedInputVaryings(ShaderType::Compute);
465     }
466 }
467 
updateExecutable()468 void ProgramPipeline::updateExecutable()
469 {
470     // Vertex Shader ProgramExecutable properties
471     updateExecutableAttributes();
472     updateTransformFeedbackMembers();
473     updateShaderStorageBlocks();
474     updateImageBindings();
475 
476     // Geometry Shader ProgramExecutable properties
477     updateExecutableGeometryProperties();
478 
479     // Tessellation Shaders ProgramExecutable properties
480     updateExecutableTessellationProperties();
481 
482     // Fragment Shader ProgramExecutable properties
483     updateFragmentInoutRangeAndEnablesPerSampleShading();
484 
485     // All Shader ProgramExecutable properties
486     mState.updateExecutableTextures();
487     mState.updateExecutableSpecConstUsageBits();
488     updateLinkedVaryings();
489 }
490 
resolveAttachedPrograms(const Context * context)491 void ProgramPipeline::resolveAttachedPrograms(const Context *context)
492 {
493     // Wait for attached programs to finish linking
494     for (Program *program : mState.mPrograms)
495     {
496         if (program != nullptr)
497         {
498             program->resolveLink(context);
499         }
500     }
501 }
502 
503 // The attached shaders are checked for linking errors by matching up their variables.
504 // Uniform, input and output variables get collected.
505 // The code gets compiled into binaries.
link(const Context * context)506 angle::Result ProgramPipeline::link(const Context *context)
507 {
508     mState.destroyDiscardedExecutables(context);
509 
510     // Make a new executable to hold the result of the link.
511     SharedProgramExecutable newExecutable = mState.makeNewExecutable(
512         context->getImplementation(), std::move(mState.mExecutable->mPPOProgramExecutables));
513 
514     InstallExecutable(context, newExecutable, &mState.mExecutable);
515     onStateChange(angle::SubjectMessage::ProgramUnlinked);
516 
517     updateLinkedShaderStages();
518 
519     ASSERT(!mState.mIsLinked);
520 
521     ProgramMergedVaryings mergedVaryings;
522     ProgramVaryingPacking varyingPacking;
523     LinkingVariables linkingVariables;
524 
525     mState.mInfoLog.reset();
526 
527     linkingVariables.initForProgramPipeline(mState);
528 
529     const Caps &caps               = context->getCaps();
530     const Limitations &limitations = context->getLimitations();
531     const Version &clientVersion   = context->getClientVersion();
532     const bool isWebGL             = context->isWebGL();
533 
534     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
535         mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
536     {
537         return angle::Result::Stop;
538     }
539 
540     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
541     {
542         if (!linkVaryings())
543         {
544             return angle::Result::Stop;
545         }
546 
547         if (!LinkValidateProgramGlobalNames(mState.mInfoLog, getExecutable(), linkingVariables))
548         {
549             return angle::Result::Stop;
550         }
551 
552         const SharedProgramExecutable &fragmentExecutable =
553             getShaderProgramExecutable(ShaderType::Fragment);
554         if (fragmentExecutable)
555         {
556             // We should also be validating SSBO and image uniform counts.
557             const GLuint combinedImageUniforms       = 0;
558             const GLuint combinedShaderStorageBlocks = 0;
559             ASSERT(mState.mExecutable->mOutputVariables.empty());
560             mState.mExecutable->mOutputVariables = fragmentExecutable->getOutputVariables();
561             if (!mState.mExecutable->linkValidateOutputVariables(
562                     caps, clientVersion, combinedImageUniforms, combinedShaderStorageBlocks,
563                     fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment),
564                     ProgramAliasedBindings(), ProgramAliasedBindings()))
565             {
566                 return angle::Result::Continue;
567             }
568         }
569         mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
570         // If separable program objects are in use, the set of attributes captured is taken
571         // from the program object active on the last vertex processing stage.
572         ShaderType lastVertexProcessingStage =
573             GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
574         if (lastVertexProcessingStage == ShaderType::InvalidEnum)
575         {
576             //  If there is no active program for the vertex or fragment shader stages, the results
577             //  of vertex and fragment shader execution will respectively be undefined. However,
578             //  this is not an error.
579             return angle::Result::Continue;
580         }
581 
582         const SharedProgramExecutable *tfExecutable =
583             &getShaderProgramExecutable(lastVertexProcessingStage);
584         ASSERT(*tfExecutable);
585 
586         if (!*tfExecutable)
587         {
588             tfExecutable = &getShaderProgramExecutable(ShaderType::Vertex);
589         }
590 
591         mState.mExecutable->mTransformFeedbackVaryingNames =
592             (*tfExecutable)->mTransformFeedbackVaryingNames;
593 
594         if (!mState.mExecutable->linkMergedVaryings(caps, limitations, clientVersion, isWebGL,
595                                                     mergedVaryings, linkingVariables,
596                                                     &varyingPacking))
597         {
598             return angle::Result::Stop;
599         }
600     }
601 
602     // Merge uniforms.
603     mState.mExecutable->copyUniformsFromProgramMap(mState.mExecutable->mPPOProgramExecutables);
604 
605     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
606     {
607         const SharedProgramExecutable &executable = getShaderProgramExecutable(ShaderType::Vertex);
608         mState.mExecutable->copyInputsFromProgram(*executable);
609     }
610 
611     // Merge shader buffers (UBOs, SSBOs, and atomic counter buffers) into the executable.
612     // Also copy over image and sampler bindings.
613     for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
614     {
615         const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
616         mState.mExecutable->copyUniformBuffersFromProgram(*executable, shaderType,
617                                                           &mState.mUniformBlockMap[shaderType]);
618         mState.mExecutable->copyStorageBuffersFromProgram(*executable, shaderType);
619         mState.mExecutable->copySamplerBindingsFromProgram(*executable);
620         mState.mExecutable->copyImageBindingsFromProgram(*executable);
621     }
622 
623     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Fragment))
624     {
625         const SharedProgramExecutable &executable =
626             getShaderProgramExecutable(ShaderType::Fragment);
627         mState.mExecutable->copyOutputsFromProgram(*executable);
628     }
629 
630     mState.mExecutable->mActiveSamplerRefCounts.fill(0);
631     updateExecutable();
632 
633     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex) ||
634         mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
635     {
636         ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
637     }
638 
639     mState.mIsLinked = true;
640     onStateChange(angle::SubjectMessage::ProgramRelinked);
641 
642     return angle::Result::Continue;
643 }
644 
getInfoLogLength() const645 int ProgramPipeline::getInfoLogLength() const
646 {
647     return static_cast<int>(mState.mInfoLog.getLength());
648 }
649 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const650 void ProgramPipeline::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
651 {
652     return mState.mInfoLog.getLog(bufSize, length, infoLog);
653 }
654 
linkVaryings()655 bool ProgramPipeline::linkVaryings()
656 {
657     ShaderType previousShaderType = ShaderType::InvalidEnum;
658     for (ShaderType shaderType : kAllGraphicsShaderTypes)
659     {
660         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
661         if (!programExecutable)
662         {
663             continue;
664         }
665 
666         if (previousShaderType != ShaderType::InvalidEnum)
667         {
668             const SharedProgramExecutable &previousExecutable =
669                 getShaderProgramExecutable(previousShaderType);
670             ASSERT(previousExecutable);
671 
672             if (!LinkValidateShaderInterfaceMatching(
673                     previousExecutable->getLinkedOutputVaryings(previousShaderType),
674                     programExecutable->getLinkedInputVaryings(shaderType), previousShaderType,
675                     shaderType, previousExecutable->getLinkedShaderVersion(previousShaderType),
676                     programExecutable->getLinkedShaderVersion(shaderType), true, mState.mInfoLog))
677             {
678                 return false;
679             }
680         }
681         previousShaderType = shaderType;
682     }
683 
684     // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
685     // Need to move logic of validating builtin varyings inside the for-loop above.
686     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
687     // can be redeclared in Geometry or Tessellation shaders as well.
688     const SharedProgramExecutable &vertexExecutable =
689         getShaderProgramExecutable(ShaderType::Vertex);
690     const SharedProgramExecutable &fragmentExecutable =
691         getShaderProgramExecutable(ShaderType::Fragment);
692     if (!vertexExecutable || !fragmentExecutable)
693     {
694         return true;
695     }
696     return LinkValidateBuiltInVaryings(
697         vertexExecutable->getLinkedOutputVaryings(ShaderType::Vertex),
698         fragmentExecutable->getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
699         ShaderType::Fragment, vertexExecutable->getLinkedShaderVersion(ShaderType::Vertex),
700         fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment), mState.mInfoLog);
701 }
702 
validate(const Context * context)703 void ProgramPipeline::validate(const Context *context)
704 {
705     updateLinkedShaderStages();
706 
707     const Caps &caps = context->getCaps();
708     mState.mValid    = true;
709     mState.mInfoLog.reset();
710 
711     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
712         mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
713     {
714         mState.mValid = false;
715         mState.mInfoLog << "Program pipeline must have both a Tessellation Control and Evaluation "
716                            "shader or neither\n";
717         return;
718     }
719 
720     for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
721     {
722         Program *shaderProgram = mState.mPrograms[shaderType];
723         if (shaderProgram)
724         {
725             shaderProgram->resolveLink(context);
726             shaderProgram->validate(caps);
727             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
728             if (shaderInfoString.length())
729             {
730                 mState.mValid = false;
731                 mState.mInfoLog << shaderInfoString << "\n";
732                 return;
733             }
734             if (!shaderProgram->isSeparable())
735             {
736                 mState.mValid = false;
737                 mState.mInfoLog << GetShaderTypeString(shaderType) << " is not marked separable."
738                                 << "\n";
739                 return;
740             }
741         }
742     }
743 
744     intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context);
745     if (programPipelineError)
746     {
747         mState.mValid            = false;
748         const char *errorMessage = reinterpret_cast<const char *>(programPipelineError);
749         mState.mInfoLog << errorMessage << "\n";
750         return;
751     }
752 
753     if (!linkVaryings())
754     {
755         mState.mValid = false;
756 
757         for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
758         {
759             Program *shaderProgram = mState.mPrograms[shaderType];
760             ASSERT(shaderProgram);
761             shaderProgram->validate(caps);
762             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
763             if (shaderInfoString.length())
764             {
765                 mState.mInfoLog << shaderInfoString << "\n";
766             }
767         }
768     }
769 }
770 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)771 void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
772 {
773     switch (message)
774     {
775         case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
776             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
777             mState.updateExecutableTextures();
778             break;
779 
780         case angle::SubjectMessage::ProgramUnlinked:
781             // A used program is being relinked.  Ensure next usage of the PPO resolve the program
782             // link and relinks the PPO.
783             mState.mIsLinked = false;
784             onStateChange(angle::SubjectMessage::ProgramUnlinked);
785             break;
786 
787         case angle::SubjectMessage::ProgramRelinked:
788         {
789             ShaderType shaderType = static_cast<ShaderType>(index);
790             ASSERT(mState.mPrograms[shaderType] != nullptr);
791             ASSERT(mState.mExecutable->mPPOProgramExecutables[shaderType]);
792 
793             mState.mIsLinked = false;
794             mState.mProgramExecutablesToDiscard.emplace_back(
795                 std::move(mState.mExecutable->mPPOProgramExecutables[shaderType]));
796             mState.mExecutable->mPPOProgramExecutables[shaderType] =
797                 mState.mPrograms[shaderType]->getSharedExecutable();
798 
799             break;
800         }
801         case angle::SubjectMessage::SamplerUniformsUpdated:
802             mState.mExecutable->clearSamplerBindings();
803             for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
804             {
805                 const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
806                 mState.mExecutable->copySamplerBindingsFromProgram(*executable);
807             }
808             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
809             mState.updateExecutableTextures();
810             break;
811         default:
812             if (angle::IsProgramUniformBlockBindingUpdatedMessage(message))
813             {
814                 if (mState.mIsLinked)
815                 {
816                     ShaderType shaderType = static_cast<ShaderType>(index);
817                     const SharedProgramExecutable &executable =
818                         getShaderProgramExecutable(shaderType);
819                     const GLuint blockIndex =
820                         angle::ProgramUniformBlockBindingUpdatedMessageToIndex(message);
821                     if (executable->getUniformBlocks()[blockIndex].isActive(shaderType))
822                     {
823                         const uint32_t blockIndexInPPO =
824                             mState.mUniformBlockMap[shaderType][blockIndex];
825                         ASSERT(blockIndexInPPO < mState.mExecutable->mUniformBlocks.size());
826 
827                         // Set the block buffer binding in the PPO to the same binding as the
828                         // program's.
829                         mState.mExecutable->remapUniformBlockBinding(
830                             {blockIndexInPPO}, executable->getUniformBlockBinding(blockIndex));
831 
832                         // Notify the contexts that the block binding has changed.
833                         onStateChange(angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(
834                             blockIndexInPPO));
835                     }
836                 }
837                 break;
838             }
839             UNREACHABLE();
840             break;
841     }
842 }
843 }  // namespace gl
844