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/ErrorStrings.h"
17 #include "libANGLE/Program.h"
18 #include "libANGLE/angletypes.h"
19 #include "libANGLE/renderer/GLImplFactory.h"
20 #include "libANGLE/renderer/ProgramPipelineImpl.h"
21
22 namespace gl
23 {
24
ProgramPipelineState()25 ProgramPipelineState::ProgramPipelineState()
26 : mLabel(),
27 mIsCompute(false),
28 mActiveShaderProgram(nullptr),
29 mValid(false),
30 mHasBeenBound(false),
31 mExecutable(new ProgramExecutable())
32 {
33 mExecutable->setProgramPipelineState(this);
34
35 for (const ShaderType shaderType : gl::AllShaderTypes())
36 {
37 mPrograms[shaderType] = nullptr;
38 }
39 }
40
~ProgramPipelineState()41 ProgramPipelineState::~ProgramPipelineState()
42 {
43 SafeDelete(mExecutable);
44 }
45
getLabel() const46 const std::string &ProgramPipelineState::getLabel() const
47 {
48 return mLabel;
49 }
50
activeShaderProgram(Program * shaderProgram)51 void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
52 {
53 mActiveShaderProgram = shaderProgram;
54 }
55
useProgramStage(const Context * context,const ShaderType shaderType,Program * shaderProgram)56 void ProgramPipelineState::useProgramStage(const Context *context,
57 const ShaderType shaderType,
58 Program *shaderProgram)
59 {
60 Program *oldProgram = mPrograms[shaderType];
61 if (oldProgram)
62 {
63 oldProgram->release(context);
64 }
65
66 // If program refers to a program object with a valid shader attached for the indicated shader
67 // stage, glUseProgramStages installs the executable code for that stage in the indicated
68 // program pipeline object pipeline.
69 if (shaderProgram && (shaderProgram->id().value != 0) &&
70 shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
71 {
72 mPrograms[shaderType] = shaderProgram;
73 shaderProgram->addRef();
74 }
75 else
76 {
77 // If program is zero, or refers to a program object with no valid shader executable for the
78 // given stage, it is as if the pipeline object has no programmable stage configured for the
79 // indicated shader stage.
80 mPrograms[shaderType] = nullptr;
81 }
82 }
83
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)84 void ProgramPipelineState::useProgramStages(const Context *context,
85 GLbitfield stages,
86 Program *shaderProgram)
87 {
88 if (stages == GL_ALL_SHADER_BITS)
89 {
90 for (const ShaderType shaderType : gl::AllShaderTypes())
91 {
92 useProgramStage(context, shaderType, shaderProgram);
93 }
94 }
95 else
96 {
97 if (stages & GL_VERTEX_SHADER_BIT)
98 {
99 useProgramStage(context, ShaderType::Vertex, shaderProgram);
100 }
101
102 if (stages & GL_FRAGMENT_SHADER_BIT)
103 {
104 useProgramStage(context, ShaderType::Fragment, shaderProgram);
105 }
106
107 if (stages & GL_COMPUTE_SHADER_BIT)
108 {
109 useProgramStage(context, ShaderType::Compute, shaderProgram);
110 }
111 }
112 }
113
usesShaderProgram(ShaderProgramID programId) const114 bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
115 {
116 for (const Program *program : mPrograms)
117 {
118 if (program && (program->id() == programId))
119 {
120 return true;
121 }
122 }
123
124 return false;
125 }
126
hasDefaultUniforms() const127 bool ProgramPipelineState::hasDefaultUniforms() const
128 {
129 for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
130 {
131 const Program *shaderProgram = getShaderProgram(shaderType);
132 if (shaderProgram && shaderProgram->getState().hasDefaultUniforms())
133 {
134 return true;
135 }
136 }
137
138 return false;
139 }
140
hasTextures() const141 bool ProgramPipelineState::hasTextures() const
142 {
143 for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
144 {
145 const Program *shaderProgram = getShaderProgram(shaderType);
146 if (shaderProgram && shaderProgram->getState().hasTextures())
147 {
148 return true;
149 }
150 }
151
152 return false;
153 }
154
hasImages() const155 bool ProgramPipelineState::hasImages() const
156 {
157 for (const gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
158 {
159 const Program *shaderProgram = getShaderProgram(shaderType);
160 if (shaderProgram && shaderProgram->getState().hasImages())
161 {
162 return true;
163 }
164 }
165
166 return false;
167 }
168
ProgramPipeline(rx::GLImplFactory * factory,ProgramPipelineID handle)169 ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
170 : RefCountObject(factory->generateSerial(), handle),
171 mProgramPipelineImpl(factory->createProgramPipeline(mState))
172 {
173 ASSERT(mProgramPipelineImpl);
174 }
175
~ProgramPipeline()176 ProgramPipeline::~ProgramPipeline()
177 {
178 mProgramPipelineImpl.release();
179 }
180
onDestroy(const Context * context)181 void ProgramPipeline::onDestroy(const Context *context)
182 {
183 for (Program *program : mState.mPrograms)
184 {
185 if (program)
186 {
187 ASSERT(program->getRefCount());
188 program->release(context);
189 }
190 }
191
192 getImplementation()->destroy(context);
193 }
194
setLabel(const Context * context,const std::string & label)195 void ProgramPipeline::setLabel(const Context *context, const std::string &label)
196 {
197 mState.mLabel = label;
198 }
199
getLabel() const200 const std::string &ProgramPipeline::getLabel() const
201 {
202 return mState.mLabel;
203 }
204
getImplementation() const205 rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
206 {
207 return mProgramPipelineImpl.get();
208 }
209
activeShaderProgram(Program * shaderProgram)210 void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
211 {
212 mState.activeShaderProgram(shaderProgram);
213 }
214
useProgramStages(const Context * context,GLbitfield stages,Program * shaderProgram)215 void ProgramPipeline::useProgramStages(const Context *context,
216 GLbitfield stages,
217 Program *shaderProgram)
218 {
219 mState.useProgramStages(context, stages, shaderProgram);
220 updateLinkedShaderStages();
221 updateExecutable();
222
223 mDirtyBits.set(DIRTY_BIT_PROGRAM_STAGE);
224 }
225
updateLinkedShaderStages()226 void ProgramPipeline::updateLinkedShaderStages()
227 {
228 mState.mExecutable->resetLinkedShaderStages();
229
230 for (const ShaderType shaderType : gl::AllShaderTypes())
231 {
232 Program *program = mState.mPrograms[shaderType];
233 if (program)
234 {
235 mState.mExecutable->setLinkedShaderStages(shaderType);
236 }
237 }
238
239 mState.mExecutable->updateCanDrawWith();
240 }
241
updateExecutableAttributes()242 void ProgramPipeline::updateExecutableAttributes()
243 {
244 Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
245
246 if (!vertexProgram)
247 {
248 return;
249 }
250
251 const ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
252 mState.mExecutable->mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
253 mState.mExecutable->mMaxActiveAttribLocation = vertexExecutable.mMaxActiveAttribLocation;
254 mState.mExecutable->mAttributesTypeMask = vertexExecutable.mAttributesTypeMask;
255 mState.mExecutable->mAttributesMask = vertexExecutable.mAttributesMask;
256 }
257
updateTransformFeedbackMembers()258 void ProgramPipeline::updateTransformFeedbackMembers()
259 {
260 Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
261
262 if (!vertexProgram)
263 {
264 return;
265 }
266
267 const ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
268 mState.mExecutable->mTransformFeedbackStrides = vertexExecutable.mTransformFeedbackStrides;
269 mState.mExecutable->mLinkedTransformFeedbackVaryings =
270 vertexExecutable.mLinkedTransformFeedbackVaryings;
271 }
272
updateExecutableTextures()273 void ProgramPipeline::updateExecutableTextures()
274 {
275 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
276 {
277 const Program *program = getShaderProgram(shaderType);
278 if (program)
279 {
280 mState.mExecutable->mActiveSamplersMask |=
281 program->getExecutable().getActiveSamplersMask();
282 mState.mExecutable->mActiveImagesMask |= program->getExecutable().getActiveImagesMask();
283 // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
284 mState.mExecutable->updateActiveSamplers(program->getState());
285 }
286 }
287 }
288
updateHasBuffers()289 void ProgramPipeline::updateHasBuffers()
290 {
291 // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
292 for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
293 {
294 const Program *shaderProgram = getShaderProgram(shaderType);
295 if (shaderProgram)
296 {
297 const ProgramExecutable &executable = shaderProgram->getExecutable();
298
299 if (executable.hasUniformBuffers())
300 {
301 mState.mExecutable->mPipelineHasGraphicsUniformBuffers = true;
302 }
303 if (executable.hasStorageBuffers())
304 {
305 mState.mExecutable->mPipelineHasGraphicsStorageBuffers = true;
306 }
307 if (executable.hasAtomicCounterBuffers())
308 {
309 mState.mExecutable->mPipelineHasGraphicsAtomicCounterBuffers = true;
310 }
311 }
312 }
313
314 const Program *computeProgram = getShaderProgram(ShaderType::Compute);
315 if (computeProgram)
316 {
317 const ProgramExecutable &executable = computeProgram->getExecutable();
318
319 if (executable.hasUniformBuffers())
320 {
321 mState.mExecutable->mPipelineHasComputeUniformBuffers = true;
322 }
323 if (executable.hasStorageBuffers())
324 {
325 mState.mExecutable->mPipelineHasComputeStorageBuffers = true;
326 }
327 if (executable.hasAtomicCounterBuffers())
328 {
329 mState.mExecutable->mPipelineHasComputeAtomicCounterBuffers = true;
330 }
331 }
332 }
333
updateExecutable()334 void ProgramPipeline::updateExecutable()
335 {
336 mState.mExecutable->reset();
337
338 // Vertex Shader ProgramExecutable properties
339 updateExecutableAttributes();
340 updateTransformFeedbackMembers();
341
342 // All Shader ProgramExecutable properties
343 updateExecutableTextures();
344 updateHasBuffers();
345 }
346
getMergedVaryings() const347 ProgramMergedVaryings ProgramPipeline::getMergedVaryings() const
348 {
349 ASSERT(!mState.mExecutable->isCompute());
350
351 // Varyings are matched between pairs of consecutive stages, by location if assigned or
352 // by name otherwise. Note that it's possible for one stage to specify location and the other
353 // not: https://cvs.khronos.org/bugzilla/show_bug.cgi?id=16261
354
355 // Map stages to the previous active stage in the rendering pipeline. When looking at input
356 // varyings of a stage, this is used to find the stage whose output varyings are being linked
357 // with them.
358 ShaderMap<ShaderType> previousActiveStage;
359
360 // Note that kAllGraphicsShaderTypes is sorted according to the rendering pipeline.
361 ShaderType lastActiveStage = ShaderType::InvalidEnum;
362 for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
363 {
364 previousActiveStage[shaderType] = lastActiveStage;
365
366 const Program *program = getShaderProgram(shaderType);
367 ASSERT(program);
368 lastActiveStage = shaderType;
369 }
370
371 // First, go through output varyings and create two maps (one by name, one by location) for
372 // faster lookup when matching input varyings.
373
374 ShaderMap<std::map<std::string, size_t>> outputVaryingNameToIndexShaderMap;
375 ShaderMap<std::map<int, size_t>> outputVaryingLocationToIndexShaderMap;
376
377 ProgramMergedVaryings merged;
378
379 // Gather output varyings.
380 for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
381 {
382 const Program *program = getShaderProgram(shaderType);
383 ASSERT(program);
384 Shader *shader = program->getState().getAttachedShader(shaderType);
385 ASSERT(shader);
386
387 for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
388 {
389 merged.push_back({});
390 ProgramVaryingRef *ref = &merged.back();
391
392 ref->frontShader = &varying;
393 ref->frontShaderStage = shaderType;
394
395 // Always map by name. Even if location is provided in this stage, it may not be in the
396 // paired stage.
397 outputVaryingNameToIndexShaderMap[shaderType][varying.name] = merged.size() - 1;
398
399 // If location is provided, also keep it in a map by location.
400 if (varying.location != -1)
401 {
402 outputVaryingLocationToIndexShaderMap[shaderType][varying.location] =
403 merged.size() - 1;
404 }
405 }
406 }
407
408 // Gather input varyings, and match them with output varyings of the previous stage.
409 for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
410 {
411 const Program *program = getShaderProgram(shaderType);
412 ASSERT(program);
413 Shader *shader = program->getState().getAttachedShader(shaderType);
414 ASSERT(shader);
415 ShaderType previousStage = previousActiveStage[shaderType];
416
417 for (const sh::ShaderVariable &varying : shader->getInputVaryings())
418 {
419 size_t mergedIndex = merged.size();
420 if (previousStage != ShaderType::InvalidEnum)
421 {
422 // If location is provided, see if we can match by location.
423 if (varying.location != -1)
424 {
425 std::map<int, size_t> outputVaryingLocationToIndex =
426 outputVaryingLocationToIndexShaderMap[previousStage];
427 auto byLocationIter = outputVaryingLocationToIndex.find(varying.location);
428 if (byLocationIter != outputVaryingLocationToIndex.end())
429 {
430 mergedIndex = byLocationIter->second;
431 }
432 }
433
434 // If not found, try to match by name.
435 if (mergedIndex == merged.size())
436 {
437 std::map<std::string, size_t> outputVaryingNameToIndex =
438 outputVaryingNameToIndexShaderMap[previousStage];
439 auto byNameIter = outputVaryingNameToIndex.find(varying.name);
440 if (byNameIter != outputVaryingNameToIndex.end())
441 {
442 mergedIndex = byNameIter->second;
443 }
444 }
445 }
446
447 // If no previous stage, or not matched by location or name, create a new entry for it.
448 if (mergedIndex == merged.size())
449 {
450 merged.push_back({});
451 mergedIndex = merged.size() - 1;
452 }
453
454 ProgramVaryingRef *ref = &merged[mergedIndex];
455
456 ref->backShader = &varying;
457 ref->backShaderStage = shaderType;
458 }
459 }
460
461 return merged;
462 }
463
464 // The attached shaders are checked for linking errors by matching up their variables.
465 // Uniform, input and output variables get collected.
466 // The code gets compiled into binaries.
link(const Context * context)467 angle::Result ProgramPipeline::link(const Context *context)
468 {
469 if (!getExecutable().isCompute())
470 {
471 InfoLog &infoLog = mState.mExecutable->getInfoLog();
472 infoLog.reset();
473 const State &state = context->getState();
474
475 // Map the varyings to the register file
476 gl::PackMode packMode = PackMode::ANGLE_RELAXED;
477 if (state.getLimitations().noFlexibleVaryingPacking)
478 {
479 // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
480 packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
481 }
482 else if (state.getExtensions().webglCompatibility)
483 {
484 // In WebGL, we use a slightly different handling for packing variables.
485 packMode = PackMode::WEBGL_STRICT;
486 }
487
488 if (!linkVaryings(infoLog))
489 {
490 return angle::Result::Stop;
491 }
492
493 if (!mState.mExecutable->linkValidateGlobalNames(infoLog))
494 {
495 return angle::Result::Stop;
496 }
497
498 GLuint maxVaryingVectors =
499 static_cast<GLuint>(context->getState().getCaps().maxVaryingVectors);
500 VaryingPacking varyingPacking(maxVaryingVectors, packMode);
501
502 const ProgramMergedVaryings &mergedVaryings = getMergedVaryings();
503 for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
504 {
505 Program *program = mState.mPrograms[shaderType];
506 ASSERT(program);
507 program->getExecutable().getResources().varyingPacking.reset();
508 ANGLE_TRY(
509 program->linkMergedVaryings(context, program->getExecutable(), mergedVaryings));
510 }
511 }
512
513 ANGLE_TRY(getImplementation()->link(context));
514
515 return angle::Result::Continue;
516 }
517
linkVaryings(InfoLog & infoLog) const518 bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
519 {
520 ShaderType previousShaderType = ShaderType::InvalidEnum;
521 for (ShaderType shaderType : getExecutable().getLinkedShaderStages())
522 {
523 Program *program = getShaderProgram(shaderType);
524 ASSERT(program);
525 ProgramExecutable &executable = program->getExecutable();
526
527 if (previousShaderType != ShaderType::InvalidEnum)
528 {
529 Program *previousProgram = getShaderProgram(previousShaderType);
530 ASSERT(previousProgram);
531 ProgramExecutable &previousExecutable = previousProgram->getExecutable();
532
533 if (!Program::linkValidateShaderInterfaceMatching(
534 previousExecutable.getLinkedOutputVaryings(previousShaderType),
535 executable.getLinkedInputVaryings(shaderType), previousShaderType, shaderType,
536 previousExecutable.getLinkedShaderVersion(previousShaderType),
537 executable.getLinkedShaderVersion(shaderType), true, infoLog))
538 {
539 return false;
540 }
541 }
542 previousShaderType = shaderType;
543 }
544
545 Program *vertexProgram = mState.mPrograms[ShaderType::Vertex];
546 Program *fragmentProgram = mState.mPrograms[ShaderType::Fragment];
547 if (!vertexProgram || !fragmentProgram)
548 {
549 return false;
550 }
551 ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
552 ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
553 return Program::linkValidateBuiltInVaryings(
554 vertexExecutable.getLinkedOutputVaryings(ShaderType::Vertex),
555 fragmentExecutable.getLinkedInputVaryings(ShaderType::Fragment),
556 vertexExecutable.getLinkedShaderVersion(ShaderType::Vertex), infoLog);
557 }
558
validate(const gl::Context * context)559 void ProgramPipeline::validate(const gl::Context *context)
560 {
561 const Caps &caps = context->getCaps();
562 mState.mValid = true;
563 InfoLog &infoLog = mState.mExecutable->getInfoLog();
564 infoLog.reset();
565
566 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
567 {
568 Program *shaderProgram = mState.mPrograms[shaderType];
569 if (shaderProgram)
570 {
571 shaderProgram->resolveLink(context);
572 shaderProgram->validate(caps);
573 std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
574 if (shaderInfoString.length())
575 {
576 mState.mValid = false;
577 infoLog << shaderInfoString << "\n";
578 return;
579 }
580 if (!shaderProgram->isSeparable())
581 {
582 mState.mValid = false;
583 infoLog << GetShaderTypeString(shaderType) << " is not marked separable."
584 << "\n";
585 return;
586 }
587 }
588 }
589
590 if (!linkVaryings(infoLog))
591 {
592 mState.mValid = false;
593
594 for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
595 {
596 Program *shaderProgram = mState.mPrograms[shaderType];
597 ASSERT(shaderProgram);
598 shaderProgram->validate(caps);
599 std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
600 if (shaderInfoString.length())
601 {
602 infoLog << shaderInfoString << "\n";
603 }
604 }
605 }
606 }
607
validateSamplers(InfoLog * infoLog,const Caps & caps)608 bool ProgramPipeline::validateSamplers(InfoLog *infoLog, const Caps &caps)
609 {
610 for (const ShaderType shaderType : gl::AllShaderTypes())
611 {
612 Program *shaderProgram = mState.mPrograms[shaderType];
613 if (shaderProgram && !shaderProgram->validateSamplers(infoLog, caps))
614 {
615 return false;
616 }
617 }
618
619 return true;
620 }
621
syncState(const Context * context)622 angle::Result ProgramPipeline::syncState(const Context *context)
623 {
624 if (mDirtyBits.any())
625 {
626 mDirtyBits.reset();
627
628 // If there's a Program bound, we still want to link the PPO so we don't
629 // lose the dirty bit, but, we don't want to signal any errors if it fails
630 // since the failure would be unrelated to drawing with the Program.
631 bool goodResult = link(context) == angle::Result::Continue;
632 if (!context->getState().getProgram())
633 {
634 ANGLE_CHECK(const_cast<Context *>(context), goodResult, "Program pipeline link failed",
635 GL_INVALID_OPERATION);
636 }
637 }
638
639 return angle::Result::Continue;
640 }
641
642 } // namespace gl
643