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