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,const gl::ShaderBitSet & shaderTypes,Program * shaderProgram,std::vector<angle::ObserverBinding> * programObserverBindings)89 void ProgramPipelineState::useProgramStages(
90 const Context *context,
91 const gl::ShaderBitSet &shaderTypes,
92 Program *shaderProgram,
93 std::vector<angle::ObserverBinding> *programObserverBindings)
94 {
95 for (ShaderType shaderType : shaderTypes)
96 {
97 useProgramStage(context, shaderType, shaderProgram,
98 &programObserverBindings->at(static_cast<size_t>(shaderType)));
99 }
100 }
101
usesShaderProgram(ShaderProgramID programId) const102 bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
103 {
104 for (const Program *program : mPrograms)
105 {
106 if (program && (program->id() == programId))
107 {
108 return true;
109 }
110 }
111
112 return false;
113 }
114
updateExecutableTextures()115 void ProgramPipelineState::updateExecutableTextures()
116 {
117 for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
118 {
119 const Program *program = getShaderProgram(shaderType);
120 ASSERT(program);
121 mExecutable->setActiveTextureMask(mExecutable->getActiveSamplersMask() |
122 program->getExecutable().getActiveSamplersMask());
123 mExecutable->setActiveImagesMask(mExecutable->getActiveImagesMask() |
124 program->getExecutable().getActiveImagesMask());
125 // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
126 mExecutable->updateActiveSamplers(program->getState());
127 }
128 }
129
getSpecConstUsageBits() const130 rx::SpecConstUsageBits ProgramPipelineState::getSpecConstUsageBits() const
131 {
132 rx::SpecConstUsageBits specConstUsageBits;
133 for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
134 {
135 const Program *program = getShaderProgram(shaderType);
136 ASSERT(program);
137 specConstUsageBits |= program->getState().getSpecConstUsageBits();
138 }
139 return specConstUsageBits;
140 }
141
ProgramPipeline(rx::GLImplFactory * factory,ProgramPipelineID handle)142 ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
143 : RefCountObject(factory->generateSerial(), handle),
144 mProgramPipelineImpl(factory->createProgramPipeline(mState)),
145 mExecutableObserverBinding(this, kExecutableSubjectIndex)
146 {
147 ASSERT(mProgramPipelineImpl);
148
149 for (const ShaderType shaderType : gl::AllShaderTypes())
150 {
151 mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
152 }
153 mExecutableObserverBinding.bind(mState.mExecutable);
154 }
155
~ProgramPipeline()156 ProgramPipeline::~ProgramPipeline()
157 {
158 mProgramPipelineImpl.reset(nullptr);
159 }
160
onDestroy(const Context * context)161 void ProgramPipeline::onDestroy(const Context *context)
162 {
163 for (Program *program : mState.mPrograms)
164 {
165 if (program)
166 {
167 ASSERT(program->getRefCount());
168 program->release(context);
169 }
170 }
171
172 getImplementation()->destroy(context);
173 }
174
setLabel(const Context * context,const std::string & label)175 angle::Result ProgramPipeline::setLabel(const Context *context, const std::string &label)
176 {
177 mState.mLabel = label;
178
179 if (mProgramPipelineImpl)
180 {
181 return mProgramPipelineImpl->onLabelUpdate(context);
182 }
183 return angle::Result::Continue;
184 }
185
getLabel() const186 const std::string &ProgramPipeline::getLabel() const
187 {
188 return mState.mLabel;
189 }
190
getImplementation() const191 rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
192 {
193 return mProgramPipelineImpl.get();
194 }
195
activeShaderProgram(Program * shaderProgram)196 void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
197 {
198 mState.activeShaderProgram(shaderProgram);
199 }
200
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)201 angle::Result ProgramPipeline::useProgramStages(const Context *context,
202 GLbitfield stages,
203 Program *shaderProgram)
204 {
205 bool needToUpdatePipelineState = false;
206 gl::ShaderBitSet shaderTypes;
207 if (stages != GL_ALL_SHADER_BITS)
208 {
209 ASSERT(stages < 256u);
210 for (size_t singleShaderBit : angle::BitSet<8>(stages))
211 {
212 // Cast back to a bit after the iterator returns an index.
213 ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
214 ASSERT(shaderType != ShaderType::InvalidEnum);
215 shaderTypes.set(shaderType);
216 }
217 }
218 else
219 {
220 shaderTypes.set();
221 }
222 ASSERT(shaderTypes.any());
223
224 for (ShaderType shaderType : shaderTypes)
225 {
226 if (mState.getShaderProgram(shaderType) != shaderProgram ||
227 (shaderProgram && shaderProgram->hasAnyDirtyBit()))
228 {
229 needToUpdatePipelineState = true;
230 break;
231 }
232 }
233
234 if (!needToUpdatePipelineState)
235 {
236 return angle::Result::Continue;
237 }
238
239 mState.useProgramStages(context, shaderTypes, shaderProgram, &mProgramObserverBindings);
240 updateLinkedShaderStages();
241
242 mState.mIsLinked = false;
243 onStateChange(angle::SubjectMessage::SubjectChanged);
244
245 return angle::Result::Continue;
246 }
247
updateLinkedShaderStages()248 void ProgramPipeline::updateLinkedShaderStages()
249 {
250 mState.mExecutable->resetLinkedShaderStages();
251
252 for (const ShaderType shaderType : gl::AllShaderTypes())
253 {
254 Program *program = mState.mPrograms[shaderType];
255 if (program)
256 {
257 mState.mExecutable->setLinkedShaderStages(shaderType);
258 }
259 }
260
261 mState.mExecutable->updateCanDrawWith();
262 }
263
updateExecutableAttributes()264 void ProgramPipeline::updateExecutableAttributes()
265 {
266 Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
267
268 if (!vertexProgram)
269 {
270 return;
271 }
272
273 const ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
274 mState.mExecutable->mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
275 mState.mExecutable->mMaxActiveAttribLocation = vertexExecutable.mMaxActiveAttribLocation;
276 mState.mExecutable->mAttributesTypeMask = vertexExecutable.mAttributesTypeMask;
277 mState.mExecutable->mAttributesMask = vertexExecutable.mAttributesMask;
278 mState.mExecutable->mProgramInputs = vertexExecutable.mProgramInputs;
279 }
280
updateTransformFeedbackMembers()281 void ProgramPipeline::updateTransformFeedbackMembers()
282 {
283 ShaderType lastVertexProcessingStage =
284 gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
285 if (lastVertexProcessingStage == ShaderType::InvalidEnum)
286 {
287 return;
288 }
289
290 Program *shaderProgram = getShaderProgram(lastVertexProcessingStage);
291 ASSERT(shaderProgram);
292
293 const ProgramExecutable &lastPreFragmentExecutable = shaderProgram->getExecutable();
294 mState.mExecutable->mTransformFeedbackStrides =
295 lastPreFragmentExecutable.mTransformFeedbackStrides;
296 mState.mExecutable->mLinkedTransformFeedbackVaryings =
297 lastPreFragmentExecutable.mLinkedTransformFeedbackVaryings;
298 }
299
updateShaderStorageBlocks()300 void ProgramPipeline::updateShaderStorageBlocks()
301 {
302 mState.mExecutable->mShaderStorageBlocks.clear();
303
304 // Only copy the storage blocks from each Program in the PPO once, since each Program could
305 // contain multiple shader stages.
306 ShaderBitSet handledStages;
307
308 for (const gl::ShaderType shaderType : gl::AllShaderTypes())
309 {
310 const Program *shaderProgram = getShaderProgram(shaderType);
311 if (shaderProgram && !handledStages.test(shaderType))
312 {
313 // Only add each Program's blocks once.
314 handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
315
316 for (const InterfaceBlock &block :
317 shaderProgram->getExecutable().getShaderStorageBlocks())
318 {
319 mState.mExecutable->mShaderStorageBlocks.emplace_back(block);
320 }
321 }
322 }
323 }
324
updateImageBindings()325 void ProgramPipeline::updateImageBindings()
326 {
327 mState.mExecutable->mImageBindings.clear();
328 mState.mExecutable->mActiveImageShaderBits.fill({});
329
330 // Only copy the storage blocks from each Program in the PPO once, since each Program could
331 // contain multiple shader stages.
332 ShaderBitSet handledStages;
333
334 for (const gl::ShaderType shaderType : gl::AllShaderTypes())
335 {
336 const Program *shaderProgram = getShaderProgram(shaderType);
337 if (shaderProgram && !handledStages.test(shaderType))
338 {
339 // Only add each Program's blocks once.
340 handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
341
342 for (const ImageBinding &imageBinding : shaderProgram->getState().getImageBindings())
343 {
344 mState.mExecutable->mImageBindings.emplace_back(imageBinding);
345 }
346
347 mState.mExecutable->updateActiveImages(shaderProgram->getExecutable());
348 }
349 }
350 }
351
updateExecutableGeometryProperties()352 void ProgramPipeline::updateExecutableGeometryProperties()
353 {
354 Program *geometryProgram = getShaderProgram(gl::ShaderType::Geometry);
355
356 if (!geometryProgram)
357 {
358 return;
359 }
360
361 const ProgramExecutable &geometryExecutable = geometryProgram->getExecutable();
362 mState.mExecutable->mGeometryShaderInputPrimitiveType =
363 geometryExecutable.mGeometryShaderInputPrimitiveType;
364 mState.mExecutable->mGeometryShaderOutputPrimitiveType =
365 geometryExecutable.mGeometryShaderOutputPrimitiveType;
366 mState.mExecutable->mGeometryShaderInvocations = geometryExecutable.mGeometryShaderInvocations;
367 mState.mExecutable->mGeometryShaderMaxVertices = geometryExecutable.mGeometryShaderMaxVertices;
368 }
369
updateExecutableTessellationProperties()370 void ProgramPipeline::updateExecutableTessellationProperties()
371 {
372 Program *tessControlProgram = getShaderProgram(gl::ShaderType::TessControl);
373 Program *tessEvalProgram = getShaderProgram(gl::ShaderType::TessEvaluation);
374
375 if (tessControlProgram)
376 {
377 const ProgramExecutable &tessControlExecutable = tessControlProgram->getExecutable();
378 mState.mExecutable->mTessControlShaderVertices =
379 tessControlExecutable.mTessControlShaderVertices;
380 }
381
382 if (tessEvalProgram)
383 {
384 const ProgramExecutable &tessEvalExecutable = tessEvalProgram->getExecutable();
385 mState.mExecutable->mTessGenMode = tessEvalExecutable.mTessGenMode;
386 mState.mExecutable->mTessGenSpacing = tessEvalExecutable.mTessGenSpacing;
387 mState.mExecutable->mTessGenVertexOrder = tessEvalExecutable.mTessGenVertexOrder;
388 mState.mExecutable->mTessGenPointMode = tessEvalExecutable.mTessGenPointMode;
389 }
390 }
391
updateFragmentInoutRangeAndEnablesPerSampleShading()392 void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
393 {
394 Program *fragmentProgram = getShaderProgram(gl::ShaderType::Fragment);
395
396 if (!fragmentProgram)
397 {
398 return;
399 }
400
401 const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
402 mState.mExecutable->mFragmentInoutRange = fragmentExecutable.mFragmentInoutRange;
403 mState.mExecutable->mHasDiscard = fragmentExecutable.mHasDiscard;
404 mState.mExecutable->mEnablesPerSampleShading = fragmentExecutable.mEnablesPerSampleShading;
405 }
406
updateLinkedVaryings()407 void ProgramPipeline::updateLinkedVaryings()
408 {
409 // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
410 for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
411 {
412 const Program *shaderProgram = getShaderProgram(shaderType);
413 if (shaderProgram && shaderProgram->isLinked())
414 {
415 const ProgramExecutable &executable = shaderProgram->getExecutable();
416 mState.mExecutable->mLinkedOutputVaryings[shaderType] =
417 executable.getLinkedOutputVaryings(shaderType);
418 mState.mExecutable->mLinkedInputVaryings[shaderType] =
419 executable.getLinkedInputVaryings(shaderType);
420 }
421 }
422
423 const Program *computeProgram = getShaderProgram(ShaderType::Compute);
424 if (computeProgram && computeProgram->isLinked())
425 {
426 const ProgramExecutable &executable = computeProgram->getExecutable();
427 mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
428 executable.getLinkedOutputVaryings(ShaderType::Compute);
429 mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
430 executable.getLinkedInputVaryings(ShaderType::Compute);
431 }
432 }
433
updateExecutable()434 void ProgramPipeline::updateExecutable()
435 {
436 // Vertex Shader ProgramExecutable properties
437 updateExecutableAttributes();
438 updateTransformFeedbackMembers();
439 updateShaderStorageBlocks();
440 updateImageBindings();
441
442 // Geometry Shader ProgramExecutable properties
443 updateExecutableGeometryProperties();
444
445 // Tessellation Shaders ProgramExecutable properties
446 updateExecutableTessellationProperties();
447
448 // Fragment Shader ProgramExecutable properties
449 updateFragmentInoutRangeAndEnablesPerSampleShading();
450
451 // All Shader ProgramExecutable properties
452 mState.updateExecutableTextures();
453 updateLinkedVaryings();
454 }
455
456 // The attached shaders are checked for linking errors by matching up their variables.
457 // Uniform, input and output variables get collected.
458 // The code gets compiled into binaries.
link(const Context * context)459 angle::Result ProgramPipeline::link(const Context *context)
460 {
461 ASSERT(!mState.mIsLinked);
462
463 ProgramMergedVaryings mergedVaryings;
464 ProgramVaryingPacking varyingPacking;
465 LinkingVariables linkingVariables(mState);
466
467 mState.mExecutable->reset(true);
468
469 InfoLog &infoLog = mState.mExecutable->getInfoLog();
470 infoLog.reset();
471
472 if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex))
473 {
474 if (!linkVaryings(infoLog))
475 {
476 return angle::Result::Stop;
477 }
478
479 if (!LinkValidateProgramGlobalNames(infoLog, getExecutable(), linkingVariables))
480 {
481 return angle::Result::Stop;
482 }
483
484 Program *fragmentShaderProgram = getShaderProgram(ShaderType::Fragment);
485 if (fragmentShaderProgram)
486 {
487 // We should also be validating SSBO and image uniform counts.
488 const GLuint combinedImageUniforms = 0;
489 const GLuint combinedShaderStorageBlocks = 0;
490 const ProgramExecutable &fragmentExecutable = fragmentShaderProgram->getExecutable();
491 if (!mState.mExecutable->linkValidateOutputVariables(
492 context->getCaps(), context->getExtensions(), context->getClientVersion(),
493 combinedImageUniforms, combinedShaderStorageBlocks,
494 fragmentExecutable.getOutputVariables(),
495 fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment),
496 ProgramAliasedBindings(), ProgramAliasedBindings()))
497 {
498 return angle::Result::Continue;
499 }
500 }
501 mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
502 // If separable program objects are in use, the set of attributes captured is taken
503 // from the program object active on the last vertex processing stage.
504 ShaderType lastVertexProcessingStage =
505 gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
506 if (lastVertexProcessingStage == ShaderType::InvalidEnum)
507 {
508 // If there is no active program for the vertex or fragment shader stages, the results
509 // of vertex and fragment shader execution will respectively be undefined. However,
510 // this is not an error.
511 return angle::Result::Continue;
512 }
513
514 Program *tfProgram = getShaderProgram(lastVertexProcessingStage);
515 ASSERT(tfProgram);
516
517 if (!tfProgram)
518 {
519 tfProgram = mState.mPrograms[ShaderType::Vertex];
520 }
521
522 const std::vector<std::string> &transformFeedbackVaryingNames =
523 tfProgram->getState().getTransformFeedbackVaryingNames();
524
525 if (!mState.mExecutable->linkMergedVaryings(context, mergedVaryings,
526 transformFeedbackVaryingNames, linkingVariables,
527 false, &varyingPacking))
528 {
529 return angle::Result::Stop;
530 }
531 }
532
533 // Merge uniforms.
534 mState.mExecutable->copyUniformsFromProgramMap(mState.mPrograms);
535
536 if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex))
537 {
538 const ProgramState &programState = mState.mPrograms[gl::ShaderType::Vertex]->getState();
539 mState.mExecutable->copyInputsFromProgram(programState);
540 }
541
542 // Merge shader buffers (UBOs, SSBOs, and atomic counter buffers) into the executable.
543 // Also copy over image and sampler bindings.
544 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
545 {
546 const ProgramState &programState = mState.mPrograms[shaderType]->getState();
547 mState.mExecutable->copyShaderBuffersFromProgram(programState, shaderType);
548 mState.mExecutable->copySamplerBindingsFromProgram(programState);
549 mState.mExecutable->copyImageBindingsFromProgram(programState);
550 }
551
552 if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Fragment))
553 {
554 const ProgramState &programState = mState.mPrograms[gl::ShaderType::Fragment]->getState();
555 mState.mExecutable->copyOutputsFromProgram(programState);
556 }
557
558 if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex) ||
559 mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute))
560 {
561 ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
562 }
563
564 mState.mExecutable->mActiveSamplerRefCounts.fill(0);
565 updateExecutable();
566
567 mState.mIsLinked = true;
568 onStateChange(angle::SubjectMessage::SubjectChanged);
569
570 return angle::Result::Continue;
571 }
572
linkVaryings(InfoLog & infoLog) const573 bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
574 {
575 ShaderType previousShaderType = ShaderType::InvalidEnum;
576 for (ShaderType shaderType : kAllGraphicsShaderTypes)
577 {
578 Program *program = getShaderProgram(shaderType);
579 if (!program)
580 {
581 continue;
582 }
583 ProgramExecutable &executable = program->getExecutable();
584
585 if (previousShaderType != ShaderType::InvalidEnum)
586 {
587 Program *previousProgram = getShaderProgram(previousShaderType);
588 ASSERT(previousProgram);
589 const ProgramExecutable &previousExecutable = previousProgram->getExecutable();
590
591 if (!LinkValidateShaderInterfaceMatching(
592 previousExecutable.getLinkedOutputVaryings(previousShaderType),
593 executable.getLinkedInputVaryings(shaderType), previousShaderType, shaderType,
594 previousExecutable.getLinkedShaderVersion(previousShaderType),
595 executable.getLinkedShaderVersion(shaderType), true, infoLog))
596 {
597 return false;
598 }
599 }
600 previousShaderType = shaderType;
601 }
602
603 // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
604 // Need to move logic of validating builtin varyings inside the for-loop above.
605 // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
606 // can be redeclared in Geometry or Tessellation shaders as well.
607 Program *vertexProgram = mState.mPrograms[ShaderType::Vertex];
608 Program *fragmentProgram = mState.mPrograms[ShaderType::Fragment];
609 if (!vertexProgram || !fragmentProgram)
610 {
611 return true;
612 }
613 ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
614 ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
615 return LinkValidateBuiltInVaryings(
616 vertexExecutable.getLinkedOutputVaryings(ShaderType::Vertex),
617 fragmentExecutable.getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
618 ShaderType::Fragment, vertexExecutable.getLinkedShaderVersion(ShaderType::Vertex),
619 fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment), infoLog);
620 }
621
validate(const gl::Context * context)622 void ProgramPipeline::validate(const gl::Context *context)
623 {
624 const Caps &caps = context->getCaps();
625 mState.mValid = true;
626 InfoLog &infoLog = mState.mExecutable->getInfoLog();
627 infoLog.reset();
628
629 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
630 {
631 Program *shaderProgram = mState.mPrograms[shaderType];
632 if (shaderProgram)
633 {
634 shaderProgram->resolveLink(context);
635 shaderProgram->validate(caps);
636 std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
637 if (shaderInfoString.length())
638 {
639 mState.mValid = false;
640 infoLog << shaderInfoString << "\n";
641 return;
642 }
643 if (!shaderProgram->isSeparable())
644 {
645 mState.mValid = false;
646 infoLog << GetShaderTypeString(shaderType) << " is not marked separable."
647 << "\n";
648 return;
649 }
650 }
651 }
652
653 intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context);
654 if (programPipelineError)
655 {
656 mState.mValid = false;
657 const char *errorMessage = reinterpret_cast<const char *>(programPipelineError);
658 infoLog << errorMessage << "\n";
659 return;
660 }
661
662 if (!linkVaryings(infoLog))
663 {
664 mState.mValid = false;
665
666 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
667 {
668 Program *shaderProgram = mState.mPrograms[shaderType];
669 ASSERT(shaderProgram);
670 shaderProgram->validate(caps);
671 std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
672 if (shaderInfoString.length())
673 {
674 infoLog << shaderInfoString << "\n";
675 }
676 }
677 }
678 }
679
syncState(const Context * context)680 angle::Result ProgramPipeline::syncState(const Context *context)
681 {
682 Program::DirtyBits dirtyBits;
683 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
684 {
685 Program *shaderProgram = mState.mPrograms[shaderType];
686 if (shaderProgram)
687 {
688 dirtyBits |= shaderProgram->mDirtyBits;
689 }
690 }
691 if (dirtyBits.any())
692 {
693 ANGLE_TRY(mProgramPipelineImpl->syncState(context, dirtyBits));
694 }
695
696 return angle::Result::Continue;
697 }
698
onUniformBufferStateChange(size_t uniformBufferIndex)699 void ProgramPipeline::onUniformBufferStateChange(size_t uniformBufferIndex)
700 {
701 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
702 {
703 Program *shaderProgram = mState.mPrograms[shaderType];
704 if (shaderProgram)
705 {
706 shaderProgram->onUniformBufferStateChange(uniformBufferIndex);
707 }
708 }
709 }
710
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)711 void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
712 {
713 switch (message)
714 {
715 case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
716 mState.mExecutable->mActiveSamplerRefCounts.fill(0);
717 mState.updateExecutableTextures();
718 break;
719
720 case angle::SubjectMessage::ProgramRelinked:
721 mState.mIsLinked = false;
722 onStateChange(angle::SubjectMessage::ProgramRelinked);
723 break;
724 case angle::SubjectMessage::SamplerUniformsUpdated:
725 mState.mExecutable->clearSamplerBindings();
726 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
727 {
728 const ProgramState &programState = mState.mPrograms[shaderType]->getState();
729 mState.mExecutable->copySamplerBindingsFromProgram(programState);
730 }
731 mState.mExecutable->mActiveSamplerRefCounts.fill(0);
732 mState.updateExecutableTextures();
733 break;
734 case angle::SubjectMessage::ProgramUniformUpdated:
735 mProgramPipelineImpl->onProgramUniformUpdate(static_cast<ShaderType>(index));
736 break;
737 default:
738 UNREACHABLE();
739 break;
740 }
741 }
742 } // namespace gl
743