1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // ProgramPipeline.cpp: Implements the gl::ProgramPipeline class.
8 // Implements GL program pipeline objects and related functionality.
9 // [OpenGL ES 3.1] section 7.4 page 105.
10
11 #include "libANGLE/ProgramPipeline.h"
12
13 #include <algorithm>
14
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Program.h"
17 #include "libANGLE/angletypes.h"
18 #include "libANGLE/renderer/GLImplFactory.h"
19 #include "libANGLE/renderer/ProgramPipelineImpl.h"
20
21 namespace gl
22 {
23
24 enum SubjectIndexes : angle::SubjectIndex
25 {
26 kExecutableSubjectIndex = 0
27 };
28
ProgramPipelineState()29 ProgramPipelineState::ProgramPipelineState()
30 : mLabel(),
31 mActiveShaderProgram(nullptr),
32 mValid(false),
33 mExecutable(new ProgramExecutable()),
34 mIsLinked(false)
35 {
36 for (const ShaderType shaderType : gl::AllShaderTypes())
37 {
38 mPrograms[shaderType] = nullptr;
39 }
40 }
41
~ProgramPipelineState()42 ProgramPipelineState::~ProgramPipelineState()
43 {
44 SafeDelete(mExecutable);
45 }
46
getLabel() const47 const std::string &ProgramPipelineState::getLabel() const
48 {
49 return mLabel;
50 }
51
activeShaderProgram(Program * shaderProgram)52 void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
53 {
54 mActiveShaderProgram = shaderProgram;
55 }
56
useProgramStage(const Context * context,const ShaderType shaderType,Program * shaderProgram,angle::ObserverBinding * programObserverBindings)57 void ProgramPipelineState::useProgramStage(const Context *context,
58 const ShaderType shaderType,
59 Program *shaderProgram,
60 angle::ObserverBinding *programObserverBindings)
61 {
62 Program *oldProgram = mPrograms[shaderType];
63 if (oldProgram)
64 {
65 oldProgram->release(context);
66 }
67
68 // If program refers to a program object with a valid shader attached for the indicated shader
69 // stage, glUseProgramStages installs the executable code for that stage in the indicated
70 // program pipeline object pipeline.
71 if (shaderProgram && (shaderProgram->id().value != 0) &&
72 shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
73 {
74 mPrograms[shaderType] = shaderProgram;
75 shaderProgram->addRef();
76 }
77 else
78 {
79 // If program is zero, or refers to a program object with no valid shader executable for the
80 // given stage, it is as if the pipeline object has no programmable stage configured for the
81 // indicated shader stage.
82 mPrograms[shaderType] = nullptr;
83 }
84
85 Program *program = mPrograms[shaderType];
86 programObserverBindings->bind(program);
87 }
88
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram,std::vector<angle::ObserverBinding> * programObserverBindings)89 void ProgramPipelineState::useProgramStages(
90 const Context *context,
91 GLbitfield stages,
92 Program *shaderProgram,
93 std::vector<angle::ObserverBinding> *programObserverBindings)
94 {
95 for (size_t singleShaderBit : angle::BitSet16<16>(static_cast<uint16_t>(stages)))
96 {
97 // Cast back to a bit after the iterator returns an index.
98 ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
99 if (shaderType == ShaderType::InvalidEnum)
100 {
101 break;
102 }
103 useProgramStage(context, shaderType, shaderProgram,
104 &programObserverBindings->at(static_cast<size_t>(shaderType)));
105 }
106 }
107
usesShaderProgram(ShaderProgramID programId) const108 bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
109 {
110 for (const Program *program : mPrograms)
111 {
112 if (program && (program->id() == programId))
113 {
114 return true;
115 }
116 }
117
118 return false;
119 }
120
updateExecutableTextures()121 void ProgramPipelineState::updateExecutableTextures()
122 {
123 for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
124 {
125 const Program *program = getShaderProgram(shaderType);
126 ASSERT(program);
127 mExecutable->setActiveTextureMask(program->getExecutable().getActiveSamplersMask());
128 mExecutable->setActiveImagesMask(program->getExecutable().getActiveImagesMask());
129 // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
130 mExecutable->updateActiveSamplers(program->getState());
131 }
132 }
133
getSpecConstUsageBits() const134 rx::SpecConstUsageBits ProgramPipelineState::getSpecConstUsageBits() const
135 {
136 rx::SpecConstUsageBits specConstUsageBits;
137 for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
138 {
139 const Program *program = getShaderProgram(shaderType);
140 ASSERT(program);
141 specConstUsageBits |= program->getState().getSpecConstUsageBits();
142 }
143 return specConstUsageBits;
144 }
145
ProgramPipeline(rx::GLImplFactory * factory,ProgramPipelineID handle)146 ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
147 : RefCountObject(factory->generateSerial(), handle),
148 mProgramPipelineImpl(factory->createProgramPipeline(mState)),
149 mExecutableObserverBinding(this, kExecutableSubjectIndex)
150 {
151 ASSERT(mProgramPipelineImpl);
152
153 for (const ShaderType shaderType : gl::AllShaderTypes())
154 {
155 mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
156 }
157 mExecutableObserverBinding.bind(mState.mExecutable);
158 }
159
~ProgramPipeline()160 ProgramPipeline::~ProgramPipeline()
161 {
162 mProgramPipelineImpl.release();
163 }
164
onDestroy(const Context * context)165 void ProgramPipeline::onDestroy(const Context *context)
166 {
167 for (Program *program : mState.mPrograms)
168 {
169 if (program)
170 {
171 ASSERT(program->getRefCount());
172 program->release(context);
173 }
174 }
175
176 getImplementation()->destroy(context);
177 }
178
setLabel(const Context * context,const std::string & label)179 void ProgramPipeline::setLabel(const Context *context, const std::string &label)
180 {
181 mState.mLabel = label;
182 }
183
getLabel() const184 const std::string &ProgramPipeline::getLabel() const
185 {
186 return mState.mLabel;
187 }
188
getImplementation() const189 rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
190 {
191 return mProgramPipelineImpl.get();
192 }
193
activeShaderProgram(Program * shaderProgram)194 void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
195 {
196 mState.activeShaderProgram(shaderProgram);
197 }
198
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)199 void ProgramPipeline::useProgramStages(const Context *context,
200 GLbitfield stages,
201 Program *shaderProgram)
202 {
203 mState.useProgramStages(context, stages, shaderProgram, &mProgramObserverBindings);
204 updateLinkedShaderStages();
205 updateExecutable();
206
207 mState.mIsLinked = false;
208 }
209
updateLinkedShaderStages()210 void ProgramPipeline::updateLinkedShaderStages()
211 {
212 mState.mExecutable->resetLinkedShaderStages();
213
214 for (const ShaderType shaderType : gl::AllShaderTypes())
215 {
216 Program *program = mState.mPrograms[shaderType];
217 if (program)
218 {
219 mState.mExecutable->setLinkedShaderStages(shaderType);
220 }
221 }
222
223 mState.mExecutable->updateCanDrawWith();
224 }
225
updateExecutableAttributes()226 void ProgramPipeline::updateExecutableAttributes()
227 {
228 Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
229
230 if (!vertexProgram)
231 {
232 return;
233 }
234
235 const ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
236 mState.mExecutable->mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
237 mState.mExecutable->mMaxActiveAttribLocation = vertexExecutable.mMaxActiveAttribLocation;
238 mState.mExecutable->mAttributesTypeMask = vertexExecutable.mAttributesTypeMask;
239 mState.mExecutable->mAttributesMask = vertexExecutable.mAttributesMask;
240 }
241
updateTransformFeedbackMembers()242 void ProgramPipeline::updateTransformFeedbackMembers()
243 {
244 ShaderType lastVertexProcessingStage =
245 gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
246 if (lastVertexProcessingStage == ShaderType::InvalidEnum)
247 {
248 return;
249 }
250
251 Program *shaderProgram = getShaderProgram(lastVertexProcessingStage);
252 ASSERT(shaderProgram);
253
254 const ProgramExecutable &lastPreFragmentExecutable = shaderProgram->getExecutable();
255 mState.mExecutable->mTransformFeedbackStrides =
256 lastPreFragmentExecutable.mTransformFeedbackStrides;
257 mState.mExecutable->mLinkedTransformFeedbackVaryings =
258 lastPreFragmentExecutable.mLinkedTransformFeedbackVaryings;
259 }
260
updateShaderStorageBlocks()261 void ProgramPipeline::updateShaderStorageBlocks()
262 {
263 mState.mExecutable->mComputeShaderStorageBlocks.clear();
264 mState.mExecutable->mGraphicsShaderStorageBlocks.clear();
265
266 // Only copy the storage blocks from each Program in the PPO once, since each Program could
267 // contain multiple shader stages.
268 ShaderBitSet handledStages;
269
270 for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
271 {
272 const Program *shaderProgram = getShaderProgram(shaderType);
273 if (shaderProgram && !handledStages.test(shaderType))
274 {
275 // Only add each Program's blocks once.
276 handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
277
278 for (const InterfaceBlock &block :
279 shaderProgram->getExecutable().getShaderStorageBlocks())
280 {
281 mState.mExecutable->mGraphicsShaderStorageBlocks.emplace_back(block);
282 }
283 }
284 }
285
286 const Program *computeProgram = getShaderProgram(ShaderType::Compute);
287 if (computeProgram)
288 {
289 for (const InterfaceBlock &block : computeProgram->getExecutable().getShaderStorageBlocks())
290 {
291 mState.mExecutable->mComputeShaderStorageBlocks.emplace_back(block);
292 }
293 }
294 }
295
updateImageBindings()296 void ProgramPipeline::updateImageBindings()
297 {
298 mState.mExecutable->mComputeImageBindings.clear();
299 mState.mExecutable->mGraphicsImageBindings.clear();
300 mState.mExecutable->mActiveImageShaderBits.fill({});
301
302 // Only copy the storage blocks from each Program in the PPO once, since each Program could
303 // contain multiple shader stages.
304 ShaderBitSet handledStages;
305
306 for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
307 {
308 const Program *shaderProgram = getShaderProgram(shaderType);
309 if (shaderProgram && !handledStages.test(shaderType))
310 {
311 // Only add each Program's blocks once.
312 handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
313
314 for (const ImageBinding &imageBinding : shaderProgram->getState().getImageBindings())
315 {
316 mState.mExecutable->mGraphicsImageBindings.emplace_back(imageBinding);
317 }
318
319 mState.mExecutable->updateActiveImages(shaderProgram->getExecutable());
320 }
321 }
322
323 const Program *computeProgram = getShaderProgram(ShaderType::Compute);
324 if (computeProgram)
325 {
326 for (const ImageBinding &imageBinding : computeProgram->getState().getImageBindings())
327 {
328 mState.mExecutable->mComputeImageBindings.emplace_back(imageBinding);
329 }
330
331 mState.mExecutable->setIsCompute(true);
332 mState.mExecutable->updateActiveImages(computeProgram->getExecutable());
333 mState.mExecutable->setIsCompute(false);
334 }
335 }
336
updateExecutableGeometryProperties()337 void ProgramPipeline::updateExecutableGeometryProperties()
338 {
339 Program *geometryProgram = getShaderProgram(gl::ShaderType::Geometry);
340
341 if (!geometryProgram)
342 {
343 return;
344 }
345
346 const ProgramExecutable &geometryExecutable = geometryProgram->getExecutable();
347 mState.mExecutable->mGeometryShaderInputPrimitiveType =
348 geometryExecutable.mGeometryShaderInputPrimitiveType;
349 mState.mExecutable->mGeometryShaderOutputPrimitiveType =
350 geometryExecutable.mGeometryShaderOutputPrimitiveType;
351 mState.mExecutable->mGeometryShaderInvocations = geometryExecutable.mGeometryShaderInvocations;
352 mState.mExecutable->mGeometryShaderMaxVertices = geometryExecutable.mGeometryShaderMaxVertices;
353 }
354
updateExecutableTessellationProperties()355 void ProgramPipeline::updateExecutableTessellationProperties()
356 {
357 Program *tessControlProgram = getShaderProgram(gl::ShaderType::TessControl);
358 Program *tessEvalProgram = getShaderProgram(gl::ShaderType::TessEvaluation);
359
360 if (tessControlProgram)
361 {
362 const ProgramExecutable &tessControlExecutable = tessControlProgram->getExecutable();
363 mState.mExecutable->mTessControlShaderVertices =
364 tessControlExecutable.mTessControlShaderVertices;
365 }
366
367 if (tessEvalProgram)
368 {
369 const ProgramExecutable &tessEvalExecutable = tessEvalProgram->getExecutable();
370 mState.mExecutable->mTessGenMode = tessEvalExecutable.mTessGenMode;
371 mState.mExecutable->mTessGenSpacing = tessEvalExecutable.mTessGenSpacing;
372 mState.mExecutable->mTessGenVertexOrder = tessEvalExecutable.mTessGenVertexOrder;
373 mState.mExecutable->mTessGenPointMode = tessEvalExecutable.mTessGenPointMode;
374 }
375 }
376
updateFragmentInoutRange()377 void ProgramPipeline::updateFragmentInoutRange()
378 {
379 Program *fragmentProgram = getShaderProgram(gl::ShaderType::Fragment);
380
381 if (!fragmentProgram)
382 {
383 return;
384 }
385
386 const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
387 mState.mExecutable->mFragmentInoutRange = fragmentExecutable.mFragmentInoutRange;
388 }
389
updateLinkedVaryings()390 void ProgramPipeline::updateLinkedVaryings()
391 {
392 // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
393 for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
394 {
395 const Program *shaderProgram = getShaderProgram(shaderType);
396 if (shaderProgram && shaderProgram->isLinked())
397 {
398 const ProgramExecutable &executable = shaderProgram->getExecutable();
399 mState.mExecutable->mLinkedOutputVaryings[shaderType] =
400 executable.getLinkedOutputVaryings(shaderType);
401 mState.mExecutable->mLinkedInputVaryings[shaderType] =
402 executable.getLinkedInputVaryings(shaderType);
403 }
404 }
405
406 const Program *computeProgram = getShaderProgram(ShaderType::Compute);
407 if (computeProgram && computeProgram->isLinked())
408 {
409 const ProgramExecutable &executable = computeProgram->getExecutable();
410 mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
411 executable.getLinkedOutputVaryings(ShaderType::Compute);
412 mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
413 executable.getLinkedInputVaryings(ShaderType::Compute);
414 }
415 }
416
updateHasBooleans()417 void ProgramPipeline::updateHasBooleans()
418 {
419 // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
420 for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
421 {
422 const Program *shaderProgram = getShaderProgram(shaderType);
423 if (shaderProgram)
424 {
425 const ProgramExecutable &executable = shaderProgram->getExecutable();
426
427 if (executable.hasUniformBuffers())
428 {
429 mState.mExecutable->mPipelineHasGraphicsUniformBuffers = true;
430 }
431 if (executable.hasGraphicsStorageBuffers())
432 {
433 mState.mExecutable->mPipelineHasGraphicsStorageBuffers = true;
434 }
435 if (executable.hasAtomicCounterBuffers())
436 {
437 mState.mExecutable->mPipelineHasGraphicsAtomicCounterBuffers = true;
438 }
439 if (executable.hasDefaultUniforms())
440 {
441 mState.mExecutable->mPipelineHasGraphicsDefaultUniforms = true;
442 }
443 if (executable.hasTextures())
444 {
445 mState.mExecutable->mPipelineHasGraphicsTextures = true;
446 }
447 if (executable.hasGraphicsImages())
448 {
449 mState.mExecutable->mPipelineHasGraphicsImages = true;
450 }
451 }
452 }
453
454 const Program *computeProgram = getShaderProgram(ShaderType::Compute);
455 if (computeProgram)
456 {
457 const ProgramExecutable &executable = computeProgram->getExecutable();
458
459 if (executable.hasUniformBuffers())
460 {
461 mState.mExecutable->mPipelineHasComputeUniformBuffers = true;
462 }
463 if (executable.hasComputeStorageBuffers())
464 {
465 mState.mExecutable->mPipelineHasComputeStorageBuffers = true;
466 }
467 if (executable.hasAtomicCounterBuffers())
468 {
469 mState.mExecutable->mPipelineHasComputeAtomicCounterBuffers = true;
470 }
471 if (executable.hasDefaultUniforms())
472 {
473 mState.mExecutable->mPipelineHasComputeDefaultUniforms = true;
474 }
475 if (executable.hasTextures())
476 {
477 mState.mExecutable->mPipelineHasComputeTextures = true;
478 }
479 if (executable.hasComputeImages())
480 {
481 mState.mExecutable->mPipelineHasComputeImages = true;
482 }
483 }
484 }
485
updateExecutable()486 void ProgramPipeline::updateExecutable()
487 {
488 mState.mExecutable->reset();
489
490 // Vertex Shader ProgramExecutable properties
491 updateExecutableAttributes();
492 updateTransformFeedbackMembers();
493 updateShaderStorageBlocks();
494 updateImageBindings();
495
496 // Geometry Shader ProgramExecutable properties
497 updateExecutableGeometryProperties();
498
499 // Tessellation Shaders ProgramExecutable properties
500 updateExecutableTessellationProperties();
501
502 // Fragment Shader ProgramExecutable properties
503 updateFragmentInoutRange();
504
505 // All Shader ProgramExecutable properties
506 mState.updateExecutableTextures();
507 updateLinkedVaryings();
508
509 // Must be last, since it queries things updated by earlier functions
510 updateHasBooleans();
511 }
512
513 // The attached shaders are checked for linking errors by matching up their variables.
514 // Uniform, input and output variables get collected.
515 // The code gets compiled into binaries.
link(const Context * context)516 angle::Result ProgramPipeline::link(const Context *context)
517 {
518 if (mState.mIsLinked)
519 {
520 return angle::Result::Continue;
521 }
522
523 ProgramMergedVaryings mergedVaryings;
524 ProgramVaryingPacking varyingPacking;
525
526 if (!getExecutable().isCompute())
527 {
528 InfoLog &infoLog = mState.mExecutable->getInfoLog();
529 infoLog.reset();
530
531 if (!linkVaryings(infoLog))
532 {
533 return angle::Result::Stop;
534 }
535
536 if (!LinkValidateProgramGlobalNames(infoLog, *this))
537 {
538 return angle::Result::Stop;
539 }
540
541 mergedVaryings = GetMergedVaryingsFromShaders(*this, getExecutable());
542 // If separable program objects are in use, the set of attributes captured is taken
543 // from the program object active on the last vertex processing stage.
544 ShaderType lastVertexProcessingStage =
545 gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
546 if (lastVertexProcessingStage == ShaderType::InvalidEnum)
547 {
548 return angle::Result::Stop;
549 }
550
551 Program *tfProgram = getShaderProgram(lastVertexProcessingStage);
552 ASSERT(tfProgram);
553
554 if (!tfProgram)
555 {
556 tfProgram = mState.mPrograms[ShaderType::Vertex];
557 }
558
559 const std::vector<std::string> &transformFeedbackVaryingNames =
560 tfProgram->getState().getTransformFeedbackVaryingNames();
561
562 if (!mState.mExecutable->linkMergedVaryings(context, *this, mergedVaryings,
563 transformFeedbackVaryingNames, false,
564 &varyingPacking))
565 {
566 return angle::Result::Stop;
567 }
568 }
569
570 ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
571
572 mState.mIsLinked = true;
573
574 return angle::Result::Continue;
575 }
576
linkVaryings(InfoLog & infoLog) const577 bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
578 {
579 ShaderType previousShaderType = ShaderType::InvalidEnum;
580 for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
581 {
582 Program *program = getShaderProgram(shaderType);
583 ASSERT(program);
584 ProgramExecutable &executable = program->getExecutable();
585
586 if (previousShaderType != ShaderType::InvalidEnum)
587 {
588 Program *previousProgram = getShaderProgram(previousShaderType);
589 ASSERT(previousProgram);
590 const ProgramExecutable &previousExecutable = previousProgram->getExecutable();
591
592 if (!LinkValidateShaderInterfaceMatching(
593 previousExecutable.getLinkedOutputVaryings(previousShaderType),
594 executable.getLinkedInputVaryings(shaderType), previousShaderType, shaderType,
595 previousExecutable.getLinkedShaderVersion(previousShaderType),
596 executable.getLinkedShaderVersion(shaderType), true, infoLog))
597 {
598 return false;
599 }
600 }
601 previousShaderType = shaderType;
602 }
603
604 // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
605 // Need to move logic of validating builtin varyings inside the for-loop above.
606 // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
607 // can be redeclared in Geometry or Tessellation shaders as well.
608 Program *vertexProgram = mState.mPrograms[ShaderType::Vertex];
609 Program *fragmentProgram = mState.mPrograms[ShaderType::Fragment];
610 if (!vertexProgram || !fragmentProgram)
611 {
612 return false;
613 }
614 ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
615 ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
616 return LinkValidateBuiltInVaryings(
617 vertexExecutable.getLinkedOutputVaryings(ShaderType::Vertex),
618 fragmentExecutable.getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
619 ShaderType::Fragment, vertexExecutable.getLinkedShaderVersion(ShaderType::Vertex),
620 fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment), infoLog);
621 }
622
validate(const gl::Context * context)623 void ProgramPipeline::validate(const gl::Context *context)
624 {
625 const Caps &caps = context->getCaps();
626 mState.mValid = true;
627 InfoLog &infoLog = mState.mExecutable->getInfoLog();
628 infoLog.reset();
629
630 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
631 {
632 Program *shaderProgram = mState.mPrograms[shaderType];
633 if (shaderProgram)
634 {
635 shaderProgram->resolveLink(context);
636 shaderProgram->validate(caps);
637 std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
638 if (shaderInfoString.length())
639 {
640 mState.mValid = false;
641 infoLog << shaderInfoString << "\n";
642 return;
643 }
644 if (!shaderProgram->isSeparable())
645 {
646 mState.mValid = false;
647 infoLog << GetShaderTypeString(shaderType) << " is not marked separable."
648 << "\n";
649 return;
650 }
651 }
652 }
653
654 if (!linkVaryings(infoLog))
655 {
656 mState.mValid = false;
657
658 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
659 {
660 Program *shaderProgram = mState.mPrograms[shaderType];
661 ASSERT(shaderProgram);
662 shaderProgram->validate(caps);
663 std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
664 if (shaderInfoString.length())
665 {
666 infoLog << shaderInfoString << "\n";
667 }
668 }
669 }
670 }
671
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)672 void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
673 {
674 switch (message)
675 {
676 case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
677 mState.mIsLinked = false;
678 mState.mExecutable->mActiveSamplerRefCounts.fill(0);
679 mState.updateExecutableTextures();
680 break;
681 case angle::SubjectMessage::ProgramRelinked:
682 mState.mIsLinked = false;
683 updateExecutable();
684 break;
685 case angle::SubjectMessage::SamplerUniformsUpdated:
686 getExecutable().resetCachedValidateSamplersResult();
687 break;
688 default:
689 UNREACHABLE();
690 break;
691 }
692 }
693
getAttachedShader(ShaderType shaderType) const694 Shader *ProgramPipeline::getAttachedShader(ShaderType shaderType) const
695 {
696 const Program *program = mState.mPrograms[shaderType];
697 return program ? program->getAttachedShader(shaderType) : nullptr;
698 }
699 } // namespace gl
700