xref: /aosp_15_r20/external/angle/src/libANGLE/ProgramPipeline.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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     mState.mExecutable->mPod.hasDepthInputAttachment =
441         fragmentExecutable->mPod.hasDepthInputAttachment;
442     mState.mExecutable->mPod.hasStencilInputAttachment =
443         fragmentExecutable->mPod.hasStencilInputAttachment;
444 }
445 
updateLinkedVaryings()446 void ProgramPipeline::updateLinkedVaryings()
447 {
448     // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
449     for (const ShaderType shaderType : kAllGraphicsShaderTypes)
450     {
451         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
452         if (programExecutable)
453         {
454             mState.mExecutable->mLinkedOutputVaryings[shaderType] =
455                 programExecutable->getLinkedOutputVaryings(shaderType);
456             mState.mExecutable->mLinkedInputVaryings[shaderType] =
457                 programExecutable->getLinkedInputVaryings(shaderType);
458         }
459     }
460 
461     const SharedProgramExecutable &computeExecutable =
462         getShaderProgramExecutable(ShaderType::Compute);
463     if (computeExecutable)
464     {
465         mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
466             computeExecutable->getLinkedOutputVaryings(ShaderType::Compute);
467         mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
468             computeExecutable->getLinkedInputVaryings(ShaderType::Compute);
469     }
470 }
471 
updateExecutable()472 void ProgramPipeline::updateExecutable()
473 {
474     // Vertex Shader ProgramExecutable properties
475     updateExecutableAttributes();
476     updateTransformFeedbackMembers();
477     updateShaderStorageBlocks();
478     updateImageBindings();
479 
480     // Geometry Shader ProgramExecutable properties
481     updateExecutableGeometryProperties();
482 
483     // Tessellation Shaders ProgramExecutable properties
484     updateExecutableTessellationProperties();
485 
486     // Fragment Shader ProgramExecutable properties
487     updateFragmentInoutRangeAndEnablesPerSampleShading();
488 
489     // All Shader ProgramExecutable properties
490     mState.updateExecutableTextures();
491     mState.updateExecutableSpecConstUsageBits();
492     updateLinkedVaryings();
493 }
494 
resolveAttachedPrograms(const Context * context)495 void ProgramPipeline::resolveAttachedPrograms(const Context *context)
496 {
497     // Wait for attached programs to finish linking
498     for (Program *program : mState.mPrograms)
499     {
500         if (program != nullptr)
501         {
502             program->resolveLink(context);
503         }
504     }
505 }
506 
507 // The attached shaders are checked for linking errors by matching up their variables.
508 // Uniform, input and output variables get collected.
509 // The code gets compiled into binaries.
link(const Context * context)510 angle::Result ProgramPipeline::link(const Context *context)
511 {
512     mState.destroyDiscardedExecutables(context);
513 
514     // Make a new executable to hold the result of the link.
515     SharedProgramExecutable newExecutable = mState.makeNewExecutable(
516         context->getImplementation(), std::move(mState.mExecutable->mPPOProgramExecutables));
517 
518     InstallExecutable(context, newExecutable, &mState.mExecutable);
519     onStateChange(angle::SubjectMessage::ProgramUnlinked);
520 
521     updateLinkedShaderStages();
522 
523     ASSERT(!mState.mIsLinked);
524 
525     ProgramMergedVaryings mergedVaryings;
526     ProgramVaryingPacking varyingPacking;
527     LinkingVariables linkingVariables;
528 
529     mState.mInfoLog.reset();
530 
531     linkingVariables.initForProgramPipeline(mState);
532 
533     const Caps &caps               = context->getCaps();
534     const Limitations &limitations = context->getLimitations();
535     const Version &clientVersion   = context->getClientVersion();
536     const bool isWebGL             = context->isWebGL();
537 
538     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
539         mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
540     {
541         return angle::Result::Stop;
542     }
543 
544     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
545     {
546         if (!linkVaryings())
547         {
548             return angle::Result::Stop;
549         }
550 
551         if (!LinkValidateProgramGlobalNames(mState.mInfoLog, getExecutable(), linkingVariables))
552         {
553             return angle::Result::Stop;
554         }
555 
556         const SharedProgramExecutable &fragmentExecutable =
557             getShaderProgramExecutable(ShaderType::Fragment);
558         if (fragmentExecutable)
559         {
560             // We should also be validating SSBO and image uniform counts.
561             const GLuint combinedImageUniforms       = 0;
562             const GLuint combinedShaderStorageBlocks = 0;
563             ASSERT(mState.mExecutable->mOutputVariables.empty());
564             mState.mExecutable->mOutputVariables = fragmentExecutable->getOutputVariables();
565             if (!mState.mExecutable->linkValidateOutputVariables(
566                     caps, clientVersion, combinedImageUniforms, combinedShaderStorageBlocks,
567                     fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment),
568                     ProgramAliasedBindings(), ProgramAliasedBindings()))
569             {
570                 return angle::Result::Continue;
571             }
572         }
573         mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
574         // If separable program objects are in use, the set of attributes captured is taken
575         // from the program object active on the last vertex processing stage.
576         ShaderType lastVertexProcessingStage =
577             GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
578         if (lastVertexProcessingStage == ShaderType::InvalidEnum)
579         {
580             //  If there is no active program for the vertex or fragment shader stages, the results
581             //  of vertex and fragment shader execution will respectively be undefined. However,
582             //  this is not an error.
583             return angle::Result::Continue;
584         }
585 
586         const SharedProgramExecutable *tfExecutable =
587             &getShaderProgramExecutable(lastVertexProcessingStage);
588         ASSERT(*tfExecutable);
589 
590         if (!*tfExecutable)
591         {
592             tfExecutable = &getShaderProgramExecutable(ShaderType::Vertex);
593         }
594 
595         mState.mExecutable->mTransformFeedbackVaryingNames =
596             (*tfExecutable)->mTransformFeedbackVaryingNames;
597 
598         if (!mState.mExecutable->linkMergedVaryings(caps, limitations, clientVersion, isWebGL,
599                                                     mergedVaryings, linkingVariables,
600                                                     &varyingPacking))
601         {
602             return angle::Result::Stop;
603         }
604     }
605 
606     // Merge uniforms.
607     mState.mExecutable->copyUniformsFromProgramMap(mState.mExecutable->mPPOProgramExecutables);
608 
609     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex))
610     {
611         const SharedProgramExecutable &executable = getShaderProgramExecutable(ShaderType::Vertex);
612         mState.mExecutable->copyInputsFromProgram(*executable);
613     }
614 
615     // Merge shader buffers (UBOs, SSBOs, and atomic counter buffers) into the executable.
616     // Also copy over image and sampler bindings.
617     for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
618     {
619         const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
620         mState.mExecutable->copyUniformBuffersFromProgram(*executable, shaderType,
621                                                           &mState.mUniformBlockMap[shaderType]);
622         mState.mExecutable->copyStorageBuffersFromProgram(*executable, shaderType);
623         mState.mExecutable->copySamplerBindingsFromProgram(*executable);
624         mState.mExecutable->copyImageBindingsFromProgram(*executable);
625     }
626 
627     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Fragment))
628     {
629         const SharedProgramExecutable &executable =
630             getShaderProgramExecutable(ShaderType::Fragment);
631         mState.mExecutable->copyOutputsFromProgram(*executable);
632     }
633 
634     mState.mExecutable->mActiveSamplerRefCounts.fill(0);
635     updateExecutable();
636 
637     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Vertex) ||
638         mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
639     {
640         ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
641     }
642 
643     mState.mIsLinked = true;
644     onStateChange(angle::SubjectMessage::ProgramRelinked);
645 
646     return angle::Result::Continue;
647 }
648 
getInfoLogLength() const649 int ProgramPipeline::getInfoLogLength() const
650 {
651     return static_cast<int>(mState.mInfoLog.getLength());
652 }
653 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const654 void ProgramPipeline::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
655 {
656     return mState.mInfoLog.getLog(bufSize, length, infoLog);
657 }
658 
linkVaryings()659 bool ProgramPipeline::linkVaryings()
660 {
661     ShaderType previousShaderType = ShaderType::InvalidEnum;
662     for (ShaderType shaderType : kAllGraphicsShaderTypes)
663     {
664         const SharedProgramExecutable &programExecutable = getShaderProgramExecutable(shaderType);
665         if (!programExecutable)
666         {
667             continue;
668         }
669 
670         if (previousShaderType != ShaderType::InvalidEnum)
671         {
672             const SharedProgramExecutable &previousExecutable =
673                 getShaderProgramExecutable(previousShaderType);
674             ASSERT(previousExecutable);
675 
676             if (!LinkValidateShaderInterfaceMatching(
677                     previousExecutable->getLinkedOutputVaryings(previousShaderType),
678                     programExecutable->getLinkedInputVaryings(shaderType), previousShaderType,
679                     shaderType, previousExecutable->getLinkedShaderVersion(previousShaderType),
680                     programExecutable->getLinkedShaderVersion(shaderType), true, mState.mInfoLog))
681             {
682                 return false;
683             }
684         }
685         previousShaderType = shaderType;
686     }
687 
688     // TODO: http://anglebug.com/42262233 and http://anglebug.com/42262234
689     // Need to move logic of validating builtin varyings inside the for-loop above.
690     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
691     // can be redeclared in Geometry or Tessellation shaders as well.
692     const SharedProgramExecutable &vertexExecutable =
693         getShaderProgramExecutable(ShaderType::Vertex);
694     const SharedProgramExecutable &fragmentExecutable =
695         getShaderProgramExecutable(ShaderType::Fragment);
696     if (!vertexExecutable || !fragmentExecutable)
697     {
698         return true;
699     }
700     return LinkValidateBuiltInVaryings(
701         vertexExecutable->getLinkedOutputVaryings(ShaderType::Vertex),
702         fragmentExecutable->getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
703         ShaderType::Fragment, vertexExecutable->getLinkedShaderVersion(ShaderType::Vertex),
704         fragmentExecutable->getLinkedShaderVersion(ShaderType::Fragment), mState.mInfoLog);
705 }
706 
validate(const Context * context)707 void ProgramPipeline::validate(const Context *context)
708 {
709     updateLinkedShaderStages();
710 
711     const Caps &caps = context->getCaps();
712     mState.mValid    = true;
713     mState.mInfoLog.reset();
714 
715     if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) !=
716         mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
717     {
718         mState.mValid = false;
719         mState.mInfoLog << "Program pipeline must have both a Tessellation Control and Evaluation "
720                            "shader or neither\n";
721         return;
722     }
723 
724     for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
725     {
726         Program *shaderProgram = mState.mPrograms[shaderType];
727         if (shaderProgram)
728         {
729             shaderProgram->resolveLink(context);
730             shaderProgram->validate(caps);
731             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
732             if (shaderInfoString.length())
733             {
734                 mState.mValid = false;
735                 mState.mInfoLog << shaderInfoString << "\n";
736                 return;
737             }
738             if (!shaderProgram->isSeparable())
739             {
740                 mState.mValid = false;
741                 mState.mInfoLog << GetShaderTypeString(shaderType) << " is not marked separable."
742                                 << "\n";
743                 return;
744             }
745         }
746     }
747 
748     intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context);
749     if (programPipelineError)
750     {
751         mState.mValid            = false;
752         const char *errorMessage = reinterpret_cast<const char *>(programPipelineError);
753         mState.mInfoLog << errorMessage << "\n";
754         return;
755     }
756 
757     if (!linkVaryings())
758     {
759         mState.mValid = false;
760 
761         for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
762         {
763             Program *shaderProgram = mState.mPrograms[shaderType];
764             ASSERT(shaderProgram);
765             shaderProgram->validate(caps);
766             std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
767             if (shaderInfoString.length())
768             {
769                 mState.mInfoLog << shaderInfoString << "\n";
770             }
771         }
772     }
773 }
774 
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)775 void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
776 {
777     switch (message)
778     {
779         case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
780             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
781             mState.updateExecutableTextures();
782             break;
783 
784         case angle::SubjectMessage::ProgramUnlinked:
785             // A used program is being relinked.  Ensure next usage of the PPO resolve the program
786             // link and relinks the PPO.
787             mState.mIsLinked = false;
788             onStateChange(angle::SubjectMessage::ProgramUnlinked);
789             break;
790 
791         case angle::SubjectMessage::ProgramRelinked:
792         {
793             ShaderType shaderType = static_cast<ShaderType>(index);
794             ASSERT(mState.mPrograms[shaderType] != nullptr);
795             ASSERT(mState.mExecutable->mPPOProgramExecutables[shaderType]);
796 
797             mState.mIsLinked = false;
798             mState.mProgramExecutablesToDiscard.emplace_back(
799                 std::move(mState.mExecutable->mPPOProgramExecutables[shaderType]));
800             mState.mExecutable->mPPOProgramExecutables[shaderType] =
801                 mState.mPrograms[shaderType]->getSharedExecutable();
802 
803             break;
804         }
805         case angle::SubjectMessage::SamplerUniformsUpdated:
806             mState.mExecutable->clearSamplerBindings();
807             for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
808             {
809                 const SharedProgramExecutable &executable = getShaderProgramExecutable(shaderType);
810                 mState.mExecutable->copySamplerBindingsFromProgram(*executable);
811             }
812             mState.mExecutable->mActiveSamplerRefCounts.fill(0);
813             mState.updateExecutableTextures();
814             break;
815         default:
816             if (angle::IsProgramUniformBlockBindingUpdatedMessage(message))
817             {
818                 if (mState.mIsLinked)
819                 {
820                     ShaderType shaderType = static_cast<ShaderType>(index);
821                     const SharedProgramExecutable &executable =
822                         getShaderProgramExecutable(shaderType);
823                     const GLuint blockIndex =
824                         angle::ProgramUniformBlockBindingUpdatedMessageToIndex(message);
825                     if (executable->getUniformBlocks()[blockIndex].isActive(shaderType))
826                     {
827                         const uint32_t blockIndexInPPO =
828                             mState.mUniformBlockMap[shaderType][blockIndex];
829                         ASSERT(blockIndexInPPO < mState.mExecutable->mUniformBlocks.size());
830 
831                         // Set the block buffer binding in the PPO to the same binding as the
832                         // program's.
833                         mState.mExecutable->remapUniformBlockBinding(
834                             {blockIndexInPPO}, executable->getUniformBlockBinding(blockIndex));
835 
836                         // Notify the contexts that the block binding has changed.
837                         onStateChange(angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(
838                             blockIndexInPPO));
839                     }
840                 }
841                 break;
842             }
843             UNREACHABLE();
844             break;
845     }
846 }
847 }  // namespace gl
848