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