1 //
2 // Copyright 2002 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 // Program.cpp: Implements the gl::Program class. Implements GL program objects
8 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
10 #include "libANGLE/Program.h"
11
12 #include <algorithm>
13 #include <utility>
14
15 #include "common/angle_version_info.h"
16 #include "common/bitset_utils.h"
17 #include "common/debug.h"
18 #include "common/platform.h"
19 #include "common/platform_helpers.h"
20 #include "common/string_utils.h"
21 #include "common/utilities.h"
22 #include "compiler/translator/blocklayout.h"
23 #include "libANGLE/Context.h"
24 #include "libANGLE/ErrorStrings.h"
25 #include "libANGLE/MemoryProgramCache.h"
26 #include "libANGLE/ProgramLinkedResources.h"
27 #include "libANGLE/ResourceManager.h"
28 #include "libANGLE/Uniform.h"
29 #include "libANGLE/VaryingPacking.h"
30 #include "libANGLE/Version.h"
31 #include "libANGLE/capture/FrameCapture.h"
32 #include "libANGLE/features.h"
33 #include "libANGLE/histogram_macros.h"
34 #include "libANGLE/queryconversions.h"
35 #include "libANGLE/renderer/ContextImpl.h"
36 #include "libANGLE/renderer/GLImplFactory.h"
37 #include "libANGLE/renderer/ProgramImpl.h"
38 #include "libANGLE/trace.h"
39 #include "platform/PlatformMethods.h"
40 #include "platform/autogen/FrontendFeatures_autogen.h"
41
42 namespace gl
43 {
44
45 namespace
46 {
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)47 void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
48 {
49 for (ShaderType shaderType : AllShaderTypes())
50 {
51 const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
52 if (shader)
53 {
54 blockLinker->addShaderBlocks(shaderType, &shader->uniformBlocks);
55 }
56 }
57 }
58
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)59 void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
60 {
61 for (ShaderType shaderType : AllShaderTypes())
62 {
63 const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
64 if (shader)
65 {
66 blockLinker->addShaderBlocks(shaderType, &shader->shaderStorageBlocks);
67 }
68 }
69 }
70
71 // Provides a mechanism to access the result of asynchronous linking.
72 class LinkEvent : angle::NonCopyable
73 {
74 public:
~LinkEvent()75 virtual ~LinkEvent() {}
76
77 // Please be aware that these methods may be called under a gl::Context other
78 // than the one where the LinkEvent was created.
79 //
80 // Waits until the linking is actually done. Returns true if the linking
81 // succeeded, false otherwise.
82 virtual angle::Result wait(const Context *context) = 0;
83 // Peeks whether the linking is still ongoing.
84 virtual bool isLinking() = 0;
85 };
86
87 // Wraps an already done linking.
88 class LinkEventDone final : public LinkEvent
89 {
90 public:
LinkEventDone(angle::Result result)91 LinkEventDone(angle::Result result) : mResult(result) {}
wait(const Context * context)92 angle::Result wait(const Context *context) override { return mResult; }
isLinking()93 bool isLinking() override { return false; }
94
95 private:
96 angle::Result mResult;
97 };
98
ScheduleSubTasks(const std::shared_ptr<angle::WorkerThreadPool> & workerThreadPool,std::vector<std::shared_ptr<rx::LinkSubTask>> & tasks,std::vector<std::shared_ptr<angle::WaitableEvent>> * eventsOut)99 void ScheduleSubTasks(const std::shared_ptr<angle::WorkerThreadPool> &workerThreadPool,
100 std::vector<std::shared_ptr<rx::LinkSubTask>> &tasks,
101 std::vector<std::shared_ptr<angle::WaitableEvent>> *eventsOut)
102 {
103 eventsOut->reserve(tasks.size());
104 for (const std::shared_ptr<rx::LinkSubTask> &subTask : tasks)
105 {
106 eventsOut->push_back(workerThreadPool->postWorkerTask(subTask));
107 }
108 }
109 } // anonymous namespace
110
GetLinkMismatchErrorString(LinkMismatchError linkError)111 const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
112 {
113 switch (linkError)
114 {
115 case LinkMismatchError::TYPE_MISMATCH:
116 return "Type";
117 case LinkMismatchError::ARRAYNESS_MISMATCH:
118 return "Array-ness";
119 case LinkMismatchError::ARRAY_SIZE_MISMATCH:
120 return "Array size";
121 case LinkMismatchError::PRECISION_MISMATCH:
122 return "Precision";
123 case LinkMismatchError::STRUCT_NAME_MISMATCH:
124 return "Structure name";
125 case LinkMismatchError::FIELD_NUMBER_MISMATCH:
126 return "Field number";
127 case LinkMismatchError::FIELD_NAME_MISMATCH:
128 return "Field name";
129
130 case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
131 return "Interpolation type";
132 case LinkMismatchError::INVARIANCE_MISMATCH:
133 return "Invariance";
134
135 case LinkMismatchError::BINDING_MISMATCH:
136 return "Binding layout qualifier";
137 case LinkMismatchError::LOCATION_MISMATCH:
138 return "Location layout qualifier";
139 case LinkMismatchError::OFFSET_MISMATCH:
140 return "Offset layout qualifier";
141 case LinkMismatchError::INSTANCE_NAME_MISMATCH:
142 return "Instance name qualifier";
143 case LinkMismatchError::FORMAT_MISMATCH:
144 return "Format qualifier";
145
146 case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
147 return "Layout qualifier";
148 case LinkMismatchError::MATRIX_PACKING_MISMATCH:
149 return "Matrix Packing";
150
151 case LinkMismatchError::FIELD_LOCATION_MISMATCH:
152 return "Field location";
153 case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
154 return "Field structure name";
155 default:
156 UNREACHABLE();
157 return "";
158 }
159 }
160
161 template <typename T>
UpdateInterfaceVariable(std::vector<T> * block,const sh::ShaderVariable & var)162 void UpdateInterfaceVariable(std::vector<T> *block, const sh::ShaderVariable &var)
163 {
164 if (!var.isStruct())
165 {
166 block->emplace_back(var);
167 block->back().resetEffectiveLocation();
168 }
169
170 for (const sh::ShaderVariable &field : var.fields)
171 {
172 ASSERT(!var.name.empty() || var.isShaderIOBlock);
173
174 // Shader I/O block naming is similar to UBOs and SSBOs:
175 //
176 // in Block
177 // {
178 // type field; // produces "field"
179 // };
180 //
181 // in Block2
182 // {
183 // type field; // produces "Block2.field"
184 // } block2;
185 //
186 const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
187 const std::string prefix = var.name.empty() ? "" : baseName + ".";
188
189 if (!field.isStruct())
190 {
191 sh::ShaderVariable fieldCopy = field;
192 fieldCopy.updateEffectiveLocation(var);
193 fieldCopy.name = prefix + field.name;
194 block->emplace_back(fieldCopy);
195 }
196
197 for (const sh::ShaderVariable &nested : field.fields)
198 {
199 sh::ShaderVariable nestedCopy = nested;
200 nestedCopy.updateEffectiveLocation(field);
201 nestedCopy.name = prefix + field.name + "." + nested.name;
202 block->emplace_back(nestedCopy);
203 }
204 }
205 }
206
207 // Saves the linking context for later use in resolveLink().
208 struct Program::LinkingState
209 {
210 LinkingVariables linkingVariables;
211 ProgramLinkedResources resources;
212 std::unique_ptr<LinkEvent> linkEvent;
213 bool linkingFromBinary;
214 };
215
216 const char *const g_fakepath = "C:\\fakepath";
217
218 // InfoLog implementation.
InfoLog()219 InfoLog::InfoLog() : mLazyStream(nullptr) {}
220
~InfoLog()221 InfoLog::~InfoLog() {}
222
getLength() const223 size_t InfoLog::getLength() const
224 {
225 if (!mLazyStream)
226 {
227 return 0;
228 }
229
230 const std::string &logString = mLazyStream->str();
231 return logString.empty() ? 0 : logString.length() + 1;
232 }
233
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const234 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
235 {
236 size_t index = 0;
237
238 if (bufSize > 0)
239 {
240 const std::string logString(str());
241
242 if (!logString.empty())
243 {
244 index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
245 memcpy(infoLog, logString.c_str(), index);
246 }
247
248 infoLog[index] = '\0';
249 }
250
251 if (length)
252 {
253 *length = static_cast<GLsizei>(index);
254 }
255 }
256
257 // append a sanitized message to the program info log.
258 // The D3D compiler includes a fake file path in some of the warning or error
259 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)260 void InfoLog::appendSanitized(const char *message)
261 {
262 ensureInitialized();
263
264 std::string msg(message);
265
266 size_t found;
267 do
268 {
269 found = msg.find(g_fakepath);
270 if (found != std::string::npos)
271 {
272 msg.erase(found, strlen(g_fakepath));
273 }
274 } while (found != std::string::npos);
275
276 if (!msg.empty())
277 {
278 *mLazyStream << message << std::endl;
279 }
280 }
281
reset()282 void InfoLog::reset()
283 {
284 if (mLazyStream)
285 {
286 mLazyStream.reset(nullptr);
287 }
288 }
289
empty() const290 bool InfoLog::empty() const
291 {
292 if (!mLazyStream)
293 {
294 return true;
295 }
296
297 return mLazyStream->rdbuf()->in_avail() == 0;
298 }
299
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)300 void LogLinkMismatch(InfoLog &infoLog,
301 const std::string &variableName,
302 const char *variableType,
303 LinkMismatchError linkError,
304 const std::string &mismatchedStructOrBlockFieldName,
305 ShaderType shaderType1,
306 ShaderType shaderType2)
307 {
308 std::ostringstream stream;
309 stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
310 << variableName;
311
312 if (!mismatchedStructOrBlockFieldName.empty())
313 {
314 stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
315 }
316
317 stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
318 << GetShaderTypeString(shaderType2) << " shaders.";
319
320 infoLog << stream.str();
321 }
322
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)323 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
324 {
325 // Only 'packed' blocks are allowed to be considered inactive.
326 return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
327 }
328
329 // VariableLocation implementation.
VariableLocation()330 VariableLocation::VariableLocation() : index(kUnused), arrayIndex(0), ignored(false) {}
331
VariableLocation(unsigned int arrayIndexIn,unsigned int index)332 VariableLocation::VariableLocation(unsigned int arrayIndexIn, unsigned int index)
333 : index(index), ignored(false)
334 {
335 ASSERT(arrayIndex != GL_INVALID_INDEX);
336 SetBitField(arrayIndex, arrayIndexIn);
337 }
338
339 // ProgramBindings implementation.
ProgramBindings()340 ProgramBindings::ProgramBindings() {}
341
~ProgramBindings()342 ProgramBindings::~ProgramBindings() {}
343
bindLocation(GLuint index,const std::string & name)344 void ProgramBindings::bindLocation(GLuint index, const std::string &name)
345 {
346 mBindings[name] = index;
347 }
348
getBindingByName(const std::string & name) const349 int ProgramBindings::getBindingByName(const std::string &name) const
350 {
351 auto iter = mBindings.find(name);
352 return (iter != mBindings.end()) ? iter->second : -1;
353 }
354
355 template <typename T>
getBinding(const T & variable) const356 int ProgramBindings::getBinding(const T &variable) const
357 {
358 return getBindingByName(variable.name);
359 }
360
begin() const361 ProgramBindings::const_iterator ProgramBindings::begin() const
362 {
363 return mBindings.begin();
364 }
365
end() const366 ProgramBindings::const_iterator ProgramBindings::end() const
367 {
368 return mBindings.end();
369 }
370
getStableIterationMap() const371 std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
372 {
373 return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
374 }
375
376 // ProgramAliasedBindings implementation.
ProgramAliasedBindings()377 ProgramAliasedBindings::ProgramAliasedBindings() {}
378
~ProgramAliasedBindings()379 ProgramAliasedBindings::~ProgramAliasedBindings() {}
380
bindLocation(GLuint index,const std::string & name)381 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
382 {
383 mBindings[name] = ProgramBinding(index);
384
385 // EXT_blend_func_extended spec: "If it specifies the base name of an array,
386 // it identifies the resources associated with the first element of the array."
387 //
388 // Normalize array bindings so that "name" and "name[0]" map to the same entry.
389 // If this binding is of the form "name[0]", then mark the "name" binding as
390 // aliased but do not update it yet in case "name" is not actually an array.
391 size_t nameLengthWithoutArrayIndex;
392 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
393 if (arrayIndex == 0)
394 {
395 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
396 auto iter = mBindings.find(baseName);
397 if (iter != mBindings.end())
398 {
399 iter->second.aliased = true;
400 }
401 }
402 }
403
getBindingByName(const std::string & name) const404 int ProgramAliasedBindings::getBindingByName(const std::string &name) const
405 {
406 auto iter = mBindings.find(name);
407 return (iter != mBindings.end()) ? iter->second.location : -1;
408 }
409
getBindingByLocation(GLuint location) const410 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
411 {
412 for (const auto &iter : mBindings)
413 {
414 if (iter.second.location == location)
415 {
416 return iter.second.location;
417 }
418 }
419 return -1;
420 }
421
422 template <typename T>
getBinding(const T & variable) const423 int ProgramAliasedBindings::getBinding(const T &variable) const
424 {
425 const std::string &name = variable.name;
426
427 // Check with the normalized array name if applicable.
428 if (variable.isArray())
429 {
430 size_t nameLengthWithoutArrayIndex;
431 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
432 if (arrayIndex == 0)
433 {
434 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
435 auto iter = mBindings.find(baseName);
436 // If "name" exists and is not aliased, that means it was modified more
437 // recently than its "name[0]" form and should be used instead of that.
438 if (iter != mBindings.end() && !iter->second.aliased)
439 {
440 return iter->second.location;
441 }
442 }
443 else if (arrayIndex == GL_INVALID_INDEX)
444 {
445 auto iter = mBindings.find(variable.name);
446 // If "name" exists and is not aliased, that means it was modified more
447 // recently than its "name[0]" form and should be used instead of that.
448 if (iter != mBindings.end() && !iter->second.aliased)
449 {
450 return iter->second.location;
451 }
452 // The base name was aliased, so use the name with the array notation.
453 return getBindingByName(name + "[0]");
454 }
455 }
456
457 return getBindingByName(name);
458 }
459 template int ProgramAliasedBindings::getBinding<UsedUniform>(const UsedUniform &variable) const;
460 template int ProgramAliasedBindings::getBinding<ProgramOutput>(const ProgramOutput &variable) const;
461 template int ProgramAliasedBindings::getBinding<sh::ShaderVariable>(
462 const sh::ShaderVariable &variable) const;
463
begin() const464 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
465 {
466 return mBindings.begin();
467 }
468
end() const469 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
470 {
471 return mBindings.end();
472 }
473
getStableIterationMap() const474 std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
475 {
476 return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
477 }
478
479 // ProgramState implementation.
ProgramState(rx::GLImplFactory * factory)480 ProgramState::ProgramState(rx::GLImplFactory *factory)
481 : mLabel(),
482 mAttachedShaders{},
483 mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
484 mBinaryRetrieveableHint(false),
485 mSeparable(false),
486 mExecutable(new ProgramExecutable(factory, &mInfoLog))
487 {}
488
~ProgramState()489 ProgramState::~ProgramState()
490 {
491 ASSERT(!hasAnyAttachedShader());
492 }
493
getLabel()494 const std::string &ProgramState::getLabel()
495 {
496 return mLabel;
497 }
498
getAttachedShader(ShaderType shaderType) const499 SharedCompiledShaderState ProgramState::getAttachedShader(ShaderType shaderType) const
500 {
501 ASSERT(shaderType != ShaderType::InvalidEnum);
502 return mAttachedShaders[shaderType];
503 }
504
hasAnyAttachedShader() const505 bool ProgramState::hasAnyAttachedShader() const
506 {
507 for (const SharedCompiledShaderState &shader : mAttachedShaders)
508 {
509 if (shader)
510 {
511 return true;
512 }
513 }
514 return false;
515 }
516
getAttachedTransformFeedbackStage() const517 ShaderType ProgramState::getAttachedTransformFeedbackStage() const
518 {
519 if (mAttachedShaders[ShaderType::Geometry])
520 {
521 return ShaderType::Geometry;
522 }
523 if (mAttachedShaders[ShaderType::TessEvaluation])
524 {
525 return ShaderType::TessEvaluation;
526 }
527 return ShaderType::Vertex;
528 }
529
530 // The common portion of parallel link and load jobs
531 class Program::MainLinkLoadTask : public angle::Closure
532 {
533 public:
MainLinkLoadTask(const std::shared_ptr<angle::WorkerThreadPool> & subTaskWorkerPool,ProgramState * state,std::shared_ptr<rx::LinkTask> && linkTask)534 MainLinkLoadTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
535 ProgramState *state,
536 std::shared_ptr<rx::LinkTask> &&linkTask)
537 : mSubTaskWorkerPool(subTaskWorkerPool), mState(*state), mLinkTask(std::move(linkTask))
538 {
539 ASSERT(subTaskWorkerPool.get());
540 }
541 ~MainLinkLoadTask() override = default;
542
getResult(const Context * context)543 angle::Result getResult(const Context *context)
544 {
545 InfoLog &infoLog = mState.getExecutable().getInfoLog();
546
547 ANGLE_TRY(mResult);
548 ANGLE_TRY(mLinkTask->getResult(context, infoLog));
549
550 for (const std::shared_ptr<rx::LinkSubTask> &task : mSubTasks)
551 {
552 ANGLE_TRY(task->getResult(context, infoLog));
553 }
554
555 return angle::Result::Continue;
556 }
557
waitSubTasks()558 void waitSubTasks() { angle::WaitableEvent::WaitMany(&mSubTaskWaitableEvents); }
559
areSubTasksLinking()560 bool areSubTasksLinking()
561 {
562 if (mLinkTask->isLinkingInternally())
563 {
564 return true;
565 }
566 return !angle::WaitableEvent::AllReady(&mSubTaskWaitableEvents);
567 }
568
569 protected:
scheduleSubTasks(std::vector<std::shared_ptr<rx::LinkSubTask>> && linkSubTasks,std::vector<std::shared_ptr<rx::LinkSubTask>> && postLinkSubTasks)570 void scheduleSubTasks(std::vector<std::shared_ptr<rx::LinkSubTask>> &&linkSubTasks,
571 std::vector<std::shared_ptr<rx::LinkSubTask>> &&postLinkSubTasks)
572 {
573 // Only one of linkSubTasks or postLinkSubTasks should have tasks. This is because
574 // currently, there is no support for ordering them.
575 ASSERT(linkSubTasks.empty() || postLinkSubTasks.empty());
576
577 // Schedule link subtasks
578 mSubTasks = std::move(linkSubTasks);
579 ScheduleSubTasks(mSubTaskWorkerPool, mSubTasks, &mSubTaskWaitableEvents);
580
581 // Schedule post-link subtasks
582 mState.mExecutable->mPostLinkSubTasks = std::move(postLinkSubTasks);
583 ScheduleSubTasks(mSubTaskWorkerPool, mState.mExecutable->mPostLinkSubTasks,
584 &mState.mExecutable->mPostLinkSubTaskWaitableEvents);
585
586 // No further use for worker pool. Release it earlier than the destructor (to avoid
587 // situations such as http://anglebug.com/42267099)
588 mSubTaskWorkerPool.reset();
589 }
590
591 std::shared_ptr<angle::WorkerThreadPool> mSubTaskWorkerPool;
592 ProgramState &mState;
593 std::shared_ptr<rx::LinkTask> mLinkTask;
594
595 // Subtask and wait events
596 std::vector<std::shared_ptr<rx::LinkSubTask>> mSubTasks;
597 std::vector<std::shared_ptr<angle::WaitableEvent>> mSubTaskWaitableEvents;
598
599 // The result of the front-end portion of the link. The backend's result is retrieved via
600 // mLinkTask->getResult(). The subtask results are retrieved via mSubTasks similarly.
601 angle::Result mResult;
602 };
603
604 class Program::MainLinkTask final : public Program::MainLinkLoadTask
605 {
606 public:
MainLinkTask(const std::shared_ptr<angle::WorkerThreadPool> & subTaskWorkerPool,const Caps & caps,const Limitations & limitations,const Version & clientVersion,bool isWebGL,Program * program,ProgramState * state,LinkingVariables * linkingVariables,ProgramLinkedResources * resources,std::shared_ptr<rx::LinkTask> && linkTask)607 MainLinkTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
608 const Caps &caps,
609 const Limitations &limitations,
610 const Version &clientVersion,
611 bool isWebGL,
612 Program *program,
613 ProgramState *state,
614 LinkingVariables *linkingVariables,
615 ProgramLinkedResources *resources,
616 std::shared_ptr<rx::LinkTask> &&linkTask)
617 : MainLinkLoadTask(subTaskWorkerPool, state, std::move(linkTask)),
618 mCaps(caps),
619 mLimitations(limitations),
620 mClientVersion(clientVersion),
621 mIsWebGL(isWebGL),
622 mProgram(program),
623 mLinkingVariables(linkingVariables),
624 mResources(resources)
625 {}
626 ~MainLinkTask() override = default;
627
operator ()()628 void operator()() override { mResult = linkImpl(); }
629
630 private:
631 angle::Result linkImpl();
632
633 // State needed for link
634 const Caps &mCaps;
635 const Limitations &mLimitations;
636 const Version mClientVersion;
637 const bool mIsWebGL;
638 Program *mProgram;
639 LinkingVariables *mLinkingVariables;
640 ProgramLinkedResources *mResources;
641 };
642
643 class Program::MainLoadTask final : public Program::MainLinkLoadTask
644 {
645 public:
MainLoadTask(const std::shared_ptr<angle::WorkerThreadPool> & subTaskWorkerPool,Program * program,ProgramState * state,std::shared_ptr<rx::LinkTask> && loadTask)646 MainLoadTask(const std::shared_ptr<angle::WorkerThreadPool> &subTaskWorkerPool,
647 Program *program,
648 ProgramState *state,
649 std::shared_ptr<rx::LinkTask> &&loadTask)
650 : MainLinkLoadTask(subTaskWorkerPool, state, std::move(loadTask))
651 {}
652 ~MainLoadTask() override = default;
653
operator ()()654 void operator()() override { mResult = loadImpl(); }
655
656 private:
657 angle::Result loadImpl();
658 };
659
660 class Program::MainLinkLoadEvent final : public LinkEvent
661 {
662 public:
MainLinkLoadEvent(const std::shared_ptr<MainLinkLoadTask> & linkTask,const std::shared_ptr<angle::WaitableEvent> & waitEvent)663 MainLinkLoadEvent(const std::shared_ptr<MainLinkLoadTask> &linkTask,
664 const std::shared_ptr<angle::WaitableEvent> &waitEvent)
665 : mLinkTask(linkTask), mWaitableEvent(waitEvent)
666 {}
~MainLinkLoadEvent()667 ~MainLinkLoadEvent() override {}
668
wait(const Context * context)669 angle::Result wait(const Context *context) override
670 {
671 ANGLE_TRACE_EVENT0("gpu.angle", "Program::MainLinkLoadEvent::wait");
672
673 mWaitableEvent->wait();
674 mLinkTask->waitSubTasks();
675
676 return mLinkTask->getResult(context);
677 }
isLinking()678 bool isLinking() override
679 {
680 return !mWaitableEvent->isReady() || mLinkTask->areSubTasksLinking();
681 }
682
683 private:
684 std::shared_ptr<MainLinkLoadTask> mLinkTask;
685 std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
686 };
687
linkImpl()688 angle::Result Program::MainLinkTask::linkImpl()
689 {
690 ProgramMergedVaryings mergedVaryings;
691
692 // Do the front-end portion of the link.
693 ANGLE_TRY(mProgram->linkJobImpl(mCaps, mLimitations, mClientVersion, mIsWebGL,
694 mLinkingVariables, mResources, &mergedVaryings));
695
696 // Next, do the backend portion of the link. If there are any subtasks to be scheduled, they
697 // are collected now.
698 std::vector<std::shared_ptr<rx::LinkSubTask>> linkSubTasks;
699 std::vector<std::shared_ptr<rx::LinkSubTask>> postLinkSubTasks;
700 mLinkTask->link(*mResources, mergedVaryings, &linkSubTasks, &postLinkSubTasks);
701
702 // Must be after backend's link to avoid misleading the linker about input/output variables.
703 mState.updateProgramInterfaceInputs();
704 mState.updateProgramInterfaceOutputs();
705
706 // Schedule the subtasks
707 scheduleSubTasks(std::move(linkSubTasks), std::move(postLinkSubTasks));
708
709 return angle::Result::Continue;
710 }
711
loadImpl()712 angle::Result Program::MainLoadTask::loadImpl()
713 {
714 std::vector<std::shared_ptr<rx::LinkSubTask>> linkSubTasks;
715 std::vector<std::shared_ptr<rx::LinkSubTask>> postLinkSubTasks;
716 mLinkTask->load(&linkSubTasks, &postLinkSubTasks);
717
718 // Schedule the subtasks
719 scheduleSubTasks(std::move(linkSubTasks), std::move(postLinkSubTasks));
720
721 return angle::Result::Continue;
722 }
723
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)724 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
725 : mSerial(factory->generateSerial()),
726 mState(factory),
727 mProgram(factory->createProgram(mState)),
728 mValidated(false),
729 mDeleteStatus(false),
730 mIsBinaryCached(true),
731 mLinked(false),
732 mProgramHash{0},
733 mRefCount(0),
734 mResourceManager(manager),
735 mHandle(handle),
736 mAttachedShaders{}
737 {
738 ASSERT(mProgram);
739
740 unlink();
741 }
742
~Program()743 Program::~Program()
744 {
745 ASSERT(!mProgram);
746 }
747
onDestroy(const Context * context)748 void Program::onDestroy(const Context *context)
749 {
750 resolveLink(context);
751 waitForPostLinkTasks(context);
752
753 for (ShaderType shaderType : AllShaderTypes())
754 {
755 Shader *shader = getAttachedShader(shaderType);
756 if (shader != nullptr)
757 {
758 shader->release(context);
759 }
760 mState.mShaderCompileJobs[shaderType].reset();
761 mState.mAttachedShaders[shaderType].reset();
762 mAttachedShaders[shaderType] = nullptr;
763 }
764
765 mProgram->destroy(context);
766 UninstallExecutable(context, &mState.mExecutable);
767
768 ASSERT(!mState.hasAnyAttachedShader());
769 SafeDelete(mProgram);
770
771 mBinary.clear();
772
773 delete this;
774 }
775
id() const776 ShaderProgramID Program::id() const
777 {
778 return mHandle;
779 }
780
setLabel(const Context * context,const std::string & label)781 angle::Result Program::setLabel(const Context *context, const std::string &label)
782 {
783 ASSERT(!mLinkingState);
784 mState.mLabel = label;
785
786 if (mProgram)
787 {
788 return mProgram->onLabelUpdate(context);
789 }
790 return angle::Result::Continue;
791 }
792
getLabel() const793 const std::string &Program::getLabel() const
794 {
795 ASSERT(!mLinkingState);
796 return mState.mLabel;
797 }
798
attachShader(const Context * context,Shader * shader)799 void Program::attachShader(const Context *context, Shader *shader)
800 {
801 resolveLink(context);
802
803 ShaderType shaderType = shader->getType();
804 ASSERT(shaderType != ShaderType::InvalidEnum);
805
806 shader->addRef();
807 mAttachedShaders[shaderType] = shader;
808 }
809
detachShader(const Context * context,Shader * shader)810 void Program::detachShader(const Context *context, Shader *shader)
811 {
812 resolveLink(context);
813
814 ShaderType shaderType = shader->getType();
815 ASSERT(shaderType != ShaderType::InvalidEnum);
816
817 ASSERT(mAttachedShaders[shaderType] == shader);
818 shader->release(context);
819 mAttachedShaders[shaderType] = nullptr;
820 mState.mShaderCompileJobs[shaderType].reset();
821 mState.mAttachedShaders[shaderType].reset();
822 }
823
getAttachedShadersCount() const824 int Program::getAttachedShadersCount() const
825 {
826 ASSERT(!mLinkingState);
827 int numAttachedShaders = 0;
828 for (const Shader *shader : mAttachedShaders)
829 {
830 if (shader != nullptr)
831 {
832 ++numAttachedShaders;
833 }
834 }
835
836 return numAttachedShaders;
837 }
838
getAttachedShader(ShaderType shaderType) const839 Shader *Program::getAttachedShader(ShaderType shaderType) const
840 {
841 return mAttachedShaders[shaderType];
842 }
843
bindAttributeLocation(const Context * context,GLuint index,const char * name)844 void Program::bindAttributeLocation(const Context *context, GLuint index, const char *name)
845 {
846 ASSERT(!mLinkingState);
847 mState.mAttributeBindings.bindLocation(index, name);
848 }
849
bindUniformLocation(const Context * context,UniformLocation location,const char * name)850 void Program::bindUniformLocation(const Context *context,
851 UniformLocation location,
852 const char *name)
853 {
854 ASSERT(!mLinkingState);
855 mState.mUniformLocationBindings.bindLocation(location.value, name);
856 }
857
bindFragmentOutputLocation(const Context * context,GLuint index,const char * name)858 void Program::bindFragmentOutputLocation(const Context *context, GLuint index, const char *name)
859 {
860 ASSERT(!mLinkingState);
861 mState.mFragmentOutputLocations.bindLocation(index, name);
862 }
863
bindFragmentOutputIndex(const Context * context,GLuint index,const char * name)864 void Program::bindFragmentOutputIndex(const Context *context, GLuint index, const char *name)
865 {
866 ASSERT(!mLinkingState);
867 mState.mFragmentOutputIndexes.bindLocation(index, name);
868 }
869
makeNewExecutable(const Context * context)870 void Program::makeNewExecutable(const Context *context)
871 {
872 ASSERT(!mLinkingState);
873 waitForPostLinkTasks(context);
874
875 // Unlink the program, but do not clear the validation-related caching yet, since we can still
876 // use the previously linked program if linking the shaders fails.
877 mLinked = false;
878
879 mLinkingState = std::make_unique<LinkingState>();
880
881 // By default, set the link event as failing. If link succeeds, it will be replaced by the
882 // appropriate event.
883 mLinkingState->linkEvent = std::make_unique<LinkEventDone>(angle::Result::Stop);
884
885 InstallExecutable(
886 context,
887 std::make_shared<ProgramExecutable>(context->getImplementation(), &mState.mInfoLog),
888 &mState.mExecutable);
889 onStateChange(angle::SubjectMessage::ProgramUnlinked);
890
891 // If caching is disabled, consider it cached!
892 mIsBinaryCached = context->getFrontendFeatures().disableProgramCaching.enabled;
893
894 // Start with a clean slate every time a new executable is installed. Note that the executable
895 // binary is not mutable; once linked it remains constant. When the program changes, a new
896 // executable is installed in this function.
897 mBinary.clear();
898 }
899
setupExecutableForLink(const Context * context)900 void Program::setupExecutableForLink(const Context *context)
901 {
902 // Create a new executable to hold the result of the link. The previous executable may still be
903 // referenced by the contexts the program is current on, and any program pipelines it may be
904 // used in. Once link succeeds, the users of the program are notified to update their
905 // executables.
906 makeNewExecutable(context);
907
908 // For every attached shader, get the compile job and compiled state. This is done at link time
909 // (instead of earlier, such as attachShader time), because the shader could get recompiled
910 // between attach and link.
911 //
912 // Additionally, make sure the backend is also able to cache the compiled state of its own
913 // ShaderImpl objects.
914 ShaderMap<rx::ShaderImpl *> shaderImpls = {};
915 for (ShaderType shaderType : AllShaderTypes())
916 {
917 Shader *shader = mAttachedShaders[shaderType];
918 SharedCompileJob compileJob;
919 SharedCompiledShaderState shaderCompiledState;
920 if (shader != nullptr)
921 {
922 compileJob = shader->getCompileJob(&shaderCompiledState);
923 shaderImpls[shaderType] = shader->getImplementation();
924 }
925 mState.mShaderCompileJobs[shaderType] = std::move(compileJob);
926 mState.mAttachedShaders[shaderType] = std::move(shaderCompiledState);
927 }
928 mProgram->prepareForLink(shaderImpls);
929
930 const angle::FrontendFeatures &frontendFeatures = context->getFrontendFeatures();
931 if (frontendFeatures.dumpShaderSource.enabled)
932 {
933 dumpProgramInfo(context);
934 }
935
936 // Make sure the executable state is in sync with the program.
937 //
938 // The transform feedback buffer mode is duplicated in the executable as it is the only
939 // link-input that is also needed at draw time.
940 //
941 // The transform feedback varying names are duplicated because the program pipeline link is not
942 // currently able to use the link result of the program directly (and redoes the link, using
943 // these names).
944 //
945 // The isSeparable state is duplicated for convenience; it is used when setting sampler/image
946 // uniforms.
947 mState.mExecutable->mPod.transformFeedbackBufferMode = mState.mTransformFeedbackBufferMode;
948 mState.mExecutable->mTransformFeedbackVaryingNames = mState.mTransformFeedbackVaryingNames;
949 mState.mExecutable->mPod.isSeparable = mState.mSeparable;
950
951 mState.mInfoLog.reset();
952 }
953
link(const Context * context,angle::JobResultExpectancy resultExpectancy)954 angle::Result Program::link(const Context *context, angle::JobResultExpectancy resultExpectancy)
955 {
956 auto *platform = ANGLEPlatformCurrent();
957 double startTime = platform->currentTime(platform);
958
959 setupExecutableForLink(context);
960
961 mProgramHash = {0};
962 MemoryProgramCache *cache = (context->getFrontendFeatures().disableProgramCaching.enabled)
963 ? nullptr
964 : context->getMemoryProgramCache();
965
966 // TODO: http://anglebug.com/42263141: Enable program caching for separable programs
967 if (cache && !isSeparable())
968 {
969 std::lock_guard<angle::SimpleMutex> cacheLock(context->getProgramCacheMutex());
970 egl::CacheGetResult result = egl::CacheGetResult::NotFound;
971 ANGLE_TRY(cache->getProgram(context, this, &mProgramHash, &result));
972
973 switch (result)
974 {
975 case egl::CacheGetResult::Success:
976 {
977 // No need to care about the compile jobs any more.
978 mState.mShaderCompileJobs = {};
979
980 std::scoped_lock lock(mHistogramMutex);
981 // Succeeded in loading the binaries in the front-end, back end may still be loading
982 // asynchronously
983 double delta = platform->currentTime(platform) - startTime;
984 int us = static_cast<int>(delta * 1000'000.0);
985 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
986 return angle::Result::Continue;
987 }
988 case egl::CacheGetResult::Rejected:
989 // If the program binary was found but rejected, the program executable may be in an
990 // inconsistent half-loaded state. In that case, start over.
991 mLinkingState.reset();
992 setupExecutableForLink(context);
993 break;
994 case egl::CacheGetResult::NotFound:
995 default:
996 break;
997 }
998 }
999
1000 const Caps &caps = context->getCaps();
1001 const Limitations &limitations = context->getLimitations();
1002 const Version &clientVersion = context->getClientVersion();
1003 const bool isWebGL = context->isWebGL();
1004
1005 // Ask the backend to prepare the link task.
1006 std::shared_ptr<rx::LinkTask> linkTask;
1007 ANGLE_TRY(mProgram->link(context, &linkTask));
1008
1009 std::unique_ptr<LinkingState> linkingState = std::make_unique<LinkingState>();
1010
1011 // Prepare the main link job
1012 std::shared_ptr<MainLinkLoadTask> mainLinkTask(new MainLinkTask(
1013 context->getLinkSubTaskThreadPool(), caps, limitations, clientVersion, isWebGL, this,
1014 &mState, &linkingState->linkingVariables, &linkingState->resources, std::move(linkTask)));
1015
1016 // While the subtasks are currently always thread-safe, the main task is not safe on all
1017 // backends. A front-end feature selects whether the single-threaded pool must be used.
1018 const angle::JobThreadSafety threadSafety =
1019 context->getFrontendFeatures().linkJobIsThreadSafe.enabled ? angle::JobThreadSafety::Safe
1020 : angle::JobThreadSafety::Unsafe;
1021 std::shared_ptr<angle::WaitableEvent> mainLinkEvent =
1022 context->postCompileLinkTask(mainLinkTask, threadSafety, resultExpectancy);
1023
1024 mLinkingState = std::move(linkingState);
1025 mLinkingState->linkingFromBinary = false;
1026 mLinkingState->linkEvent = std::make_unique<MainLinkLoadEvent>(mainLinkTask, mainLinkEvent);
1027
1028 return angle::Result::Continue;
1029 }
1030
linkJobImpl(const Caps & caps,const Limitations & limitations,const Version & clientVersion,bool isWebGL,LinkingVariables * linkingVariables,ProgramLinkedResources * resources,ProgramMergedVaryings * mergedVaryingsOut)1031 angle::Result Program::linkJobImpl(const Caps &caps,
1032 const Limitations &limitations,
1033 const Version &clientVersion,
1034 bool isWebGL,
1035 LinkingVariables *linkingVariables,
1036 ProgramLinkedResources *resources,
1037 ProgramMergedVaryings *mergedVaryingsOut)
1038 {
1039 // Cache load failed, fall through to normal linking.
1040 unlink();
1041
1042 // Validate we have properly attached shaders after checking the cache. Since the input to the
1043 // shaders is part of the cache key, if there was a cache hit, the shaders would have linked
1044 // correctly.
1045 if (!linkValidateShaders())
1046 {
1047 return angle::Result::Stop;
1048 }
1049
1050 linkShaders();
1051
1052 linkingVariables->initForProgram(mState);
1053 resources->init(
1054 &mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1055 &mState.mExecutable->mUniformNames, &mState.mExecutable->mUniformMappedNames,
1056 &mState.mExecutable->mShaderStorageBlocks, &mState.mExecutable->mBufferVariables,
1057 &mState.mExecutable->mAtomicCounterBuffers, &mState.mExecutable->mPixelLocalStorageFormats);
1058
1059 updateLinkedShaderStages();
1060
1061 InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
1062 InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
1063
1064 if (mState.mAttachedShaders[ShaderType::Compute])
1065 {
1066 GLuint combinedImageUniforms = 0;
1067 if (!linkUniforms(caps, clientVersion, &resources->unusedUniforms, &combinedImageUniforms))
1068 {
1069 return angle::Result::Stop;
1070 }
1071
1072 GLuint combinedShaderStorageBlocks = 0u;
1073 if (!LinkValidateProgramInterfaceBlocks(
1074 caps, clientVersion, isWebGL, mState.mExecutable->getLinkedShaderStages(),
1075 *resources, mState.mInfoLog, &combinedShaderStorageBlocks))
1076 {
1077 return angle::Result::Stop;
1078 }
1079
1080 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1081 // A link error will be generated if the sum of the number of active image uniforms used in
1082 // all shaders, the number of active shader storage blocks, and the number of active
1083 // fragment shader outputs exceeds the implementation-dependent value of
1084 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1085 if (combinedImageUniforms + combinedShaderStorageBlocks >
1086 static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
1087 {
1088 mState.mInfoLog
1089 << "The sum of the number of active image uniforms, active shader storage blocks "
1090 "and active fragment shader outputs exceeds "
1091 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1092 << caps.maxCombinedShaderOutputResources << ")";
1093 return angle::Result::Stop;
1094 }
1095 }
1096 else
1097 {
1098 if (!linkAttributes(caps, limitations, isWebGL))
1099 {
1100 return angle::Result::Stop;
1101 }
1102
1103 if (!linkVaryings())
1104 {
1105 return angle::Result::Stop;
1106 }
1107
1108 GLuint combinedImageUniforms = 0;
1109 if (!linkUniforms(caps, clientVersion, &resources->unusedUniforms, &combinedImageUniforms))
1110 {
1111 return angle::Result::Stop;
1112 }
1113
1114 GLuint combinedShaderStorageBlocks = 0u;
1115 if (!LinkValidateProgramInterfaceBlocks(
1116 caps, clientVersion, isWebGL, mState.mExecutable->getLinkedShaderStages(),
1117 *resources, mState.mInfoLog, &combinedShaderStorageBlocks))
1118 {
1119 return angle::Result::Stop;
1120 }
1121
1122 if (!LinkValidateProgramGlobalNames(mState.mInfoLog, getExecutable(), *linkingVariables))
1123 {
1124 return angle::Result::Stop;
1125 }
1126
1127 const SharedCompiledShaderState &vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1128 if (vertexShader)
1129 {
1130 mState.mExecutable->mPod.numViews = vertexShader->numViews;
1131 mState.mExecutable->mPod.hasClipDistance =
1132 vertexShader->metadataFlags.test(sh::MetadataFlags::HasClipDistance);
1133 mState.mExecutable->mPod.specConstUsageBits |= vertexShader->specConstUsageBits;
1134 }
1135
1136 const SharedCompiledShaderState &fragmentShader =
1137 mState.mAttachedShaders[ShaderType::Fragment];
1138 if (fragmentShader)
1139 {
1140 ASSERT(mState.mExecutable->mOutputVariables.empty());
1141 mState.mExecutable->mOutputVariables.reserve(
1142 fragmentShader->activeOutputVariables.size());
1143 for (const sh::ShaderVariable &shaderVariable : fragmentShader->activeOutputVariables)
1144 {
1145 mState.mExecutable->mOutputVariables.emplace_back(shaderVariable);
1146 }
1147 if (!mState.mExecutable->linkValidateOutputVariables(
1148 caps, clientVersion, combinedImageUniforms, combinedShaderStorageBlocks,
1149 fragmentShader->shaderVersion, mState.mFragmentOutputLocations,
1150 mState.mFragmentOutputIndexes))
1151 {
1152 return angle::Result::Stop;
1153 }
1154
1155 mState.mExecutable->mPod.hasDiscard =
1156 fragmentShader->metadataFlags.test(sh::MetadataFlags::HasDiscard);
1157 mState.mExecutable->mPod.enablesPerSampleShading =
1158 fragmentShader->metadataFlags.test(sh::MetadataFlags::EnablesPerSampleShading);
1159 mState.mExecutable->mPod.hasDepthInputAttachment =
1160 fragmentShader->metadataFlags.test(sh::MetadataFlags::HasDepthInputAttachment);
1161 mState.mExecutable->mPod.hasStencilInputAttachment =
1162 fragmentShader->metadataFlags.test(sh::MetadataFlags::HasStencilInputAttachment);
1163 mState.mExecutable->mPod.advancedBlendEquations =
1164 fragmentShader->advancedBlendEquations;
1165 mState.mExecutable->mPod.specConstUsageBits |= fragmentShader->specConstUsageBits;
1166
1167 for (uint32_t index = 0; index < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++index)
1168 {
1169 const sh::MetadataFlags flag = static_cast<sh::MetadataFlags>(
1170 static_cast<uint32_t>(sh::MetadataFlags::HasInputAttachment0) + index);
1171 if (fragmentShader->metadataFlags.test(flag))
1172 {
1173 mState.mExecutable->mPod.fragmentInoutIndices.set(index);
1174 }
1175 }
1176 }
1177
1178 *mergedVaryingsOut = GetMergedVaryingsFromLinkingVariables(*linkingVariables);
1179 if (!mState.mExecutable->linkMergedVaryings(caps, limitations, clientVersion, isWebGL,
1180 *mergedVaryingsOut, *linkingVariables,
1181 &resources->varyingPacking))
1182 {
1183 return angle::Result::Stop;
1184 }
1185 }
1186
1187 mState.mExecutable->saveLinkedStateInfo(mState);
1188
1189 return angle::Result::Continue;
1190 }
1191
isLinking() const1192 bool Program::isLinking() const
1193 {
1194 return mLinkingState.get() && mLinkingState->linkEvent && mLinkingState->linkEvent->isLinking();
1195 }
1196
isBinaryReady(const Context * context)1197 bool Program::isBinaryReady(const Context *context)
1198 {
1199 if (mState.mExecutable->mPostLinkSubTasks.empty())
1200 {
1201 // Ensure the program binary is cached, even if the backend waits for post-link tasks
1202 // without the knowledge of the front-end.
1203 cacheProgramBinaryIfNotAlready(context);
1204 return true;
1205 }
1206
1207 const bool allPostLinkTasksComplete =
1208 angle::WaitableEvent::AllReady(&mState.mExecutable->getPostLinkSubTaskWaitableEvents());
1209
1210 // Once the binary is ready, the |glGetProgramBinary| call will result in
1211 // |waitForPostLinkTasks| which in turn may internally cache the binary. However, for the sake
1212 // of blob cache tests, call |waitForPostLinkTasks| anyway if tasks are already complete.
1213 if (allPostLinkTasksComplete)
1214 {
1215 waitForPostLinkTasks(context);
1216 }
1217
1218 return allPostLinkTasksComplete;
1219 }
1220
resolveLinkImpl(const Context * context)1221 void Program::resolveLinkImpl(const Context *context)
1222 {
1223 ASSERT(mLinkingState.get());
1224
1225 angle::Result result = mLinkingState->linkEvent->wait(context);
1226 mLinked = result == angle::Result::Continue;
1227 std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1228 if (!mLinked)
1229 {
1230 // If the link fails, the spec allows program queries to either return empty results (all
1231 // zeros) or whatever parts of the link happened to have been done before the failure:
1232 //
1233 // > Implementations may return information on variables and interface blocks that would
1234 // > have been active had the program been linked successfully. In cases where the link
1235 // > failed because the program required too many resources, these commands may help
1236 // > applications determine why limits were exceeded. However, the information returned in
1237 // > this case is implementation-dependent and may be incomplete.
1238 //
1239 // The above means that it's ok for ANGLE to reset the executable here, but it *may* be
1240 // helpful to applications if it doesn't. We do reset it however, the info log should
1241 // already have enough debug information for the application.
1242 mState.mExecutable->reset();
1243 return;
1244 }
1245
1246 // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1247 // Only successfully linked program can replace the executables.
1248 ASSERT(mLinked);
1249
1250 // In case of a successful link, it is no longer required for the attached shaders to hold on to
1251 // the memory they have used. Therefore, the shader compilations are resolved to save memory.
1252 for (Shader *shader : mAttachedShaders)
1253 {
1254 if (shader != nullptr)
1255 {
1256 shader->resolveCompile(context);
1257 }
1258 }
1259
1260 // Mark implementation-specific unreferenced uniforms as ignored.
1261 std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1262 mProgram->markUnusedUniformLocations(&mState.mExecutable->mUniformLocations,
1263 &mState.mExecutable->mSamplerBindings, imageBindings);
1264
1265 // Must be called after markUnusedUniformLocations.
1266 postResolveLink(context);
1267
1268 // Notify observers that a new linked executable is available. If this program is current on a
1269 // context, the executable is reinstalled. If it is attached to a PPO, it is installed there
1270 // and the PPO is marked as needing to be linked again.
1271 onStateChange(angle::SubjectMessage::ProgramRelinked);
1272
1273 // Cache the program if:
1274 //
1275 // - Not loading from binary, in which case the program is already in the cache.
1276 // - There are no post link tasks. If there are any, waitForPostLinkTasks will do this
1277 // instead.
1278 // * Note that serialize() calls waitForPostLinkTasks, so caching the binary here
1279 // effectively forces a wait for the post-link tasks.
1280 //
1281 if (!linkingState->linkingFromBinary && mState.mExecutable->mPostLinkSubTasks.empty())
1282 {
1283 cacheProgramBinaryIfNotAlready(context);
1284 }
1285 }
1286
waitForPostLinkTasks(const Context * context)1287 void Program::waitForPostLinkTasks(const Context *context)
1288 {
1289 // No-op if no tasks.
1290 mState.mExecutable->waitForPostLinkTasks(context);
1291
1292 // Now that the subtasks are done, cache the binary (this was deferred in resolveLinkImpl).
1293 cacheProgramBinaryIfNotAlready(context);
1294 }
1295
updateLinkedShaderStages()1296 void Program::updateLinkedShaderStages()
1297 {
1298 mState.mExecutable->resetLinkedShaderStages();
1299
1300 for (ShaderType shaderType : AllShaderTypes())
1301 {
1302 if (mState.mAttachedShaders[shaderType])
1303 {
1304 mState.mExecutable->setLinkedShaderStages(shaderType);
1305 }
1306 }
1307 }
1308
updateActiveSamplers()1309 void ProgramState::updateActiveSamplers()
1310 {
1311 mExecutable->mActiveSamplerRefCounts.fill(0);
1312 mExecutable->updateActiveSamplers(*mExecutable);
1313 }
1314
updateProgramInterfaceInputs()1315 void ProgramState::updateProgramInterfaceInputs()
1316 {
1317 const ShaderType firstAttachedShaderType = mExecutable->getFirstLinkedShaderStageType();
1318
1319 if (firstAttachedShaderType == ShaderType::Vertex)
1320 {
1321 // Vertex attributes are already what we need, so nothing to do
1322 return;
1323 }
1324
1325 const SharedCompiledShaderState &shader = getAttachedShader(firstAttachedShaderType);
1326 ASSERT(shader);
1327
1328 // Copy over each input varying, since the Shader could go away
1329 if (shader->shaderType == ShaderType::Compute)
1330 {
1331 for (const sh::ShaderVariable &attribute : shader->allAttributes)
1332 {
1333 // Compute Shaders have the following built-in input variables.
1334 //
1335 // in uvec3 gl_NumWorkGroups;
1336 // in uvec3 gl_WorkGroupID;
1337 // in uvec3 gl_LocalInvocationID;
1338 // in uvec3 gl_GlobalInvocationID;
1339 // in uint gl_LocalInvocationIndex;
1340 // They are all vecs or uints, so no special handling is required.
1341 mExecutable->mProgramInputs.emplace_back(attribute);
1342 }
1343 }
1344 else
1345 {
1346 for (const sh::ShaderVariable &varying : shader->inputVaryings)
1347 {
1348 UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1349 }
1350 }
1351 }
1352
updateProgramInterfaceOutputs()1353 void ProgramState::updateProgramInterfaceOutputs()
1354 {
1355 const ShaderType lastAttachedShaderType = mExecutable->getLastLinkedShaderStageType();
1356
1357 if (lastAttachedShaderType == ShaderType::Fragment)
1358 {
1359 // Fragment outputs are already what we need, so nothing to do
1360 return;
1361 }
1362 if (lastAttachedShaderType == ShaderType::Compute)
1363 {
1364 // If the program only contains a Compute Shader, then there are no user-defined outputs.
1365 return;
1366 }
1367
1368 const SharedCompiledShaderState &shader = getAttachedShader(lastAttachedShaderType);
1369 ASSERT(shader);
1370
1371 // Copy over each output varying, since the Shader could go away
1372 for (const sh::ShaderVariable &varying : shader->outputVaryings)
1373 {
1374 UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1375 }
1376 }
1377
1378 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1379 void Program::unlink()
1380 {
1381 // There is always a new executable created on link, so the executable is already in a clean
1382 // state.
1383
1384 mValidated = false;
1385 }
1386
setBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1387 angle::Result Program::setBinary(const Context *context,
1388 GLenum binaryFormat,
1389 const void *binary,
1390 GLsizei length)
1391 {
1392 ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1393
1394 makeNewExecutable(context);
1395
1396 egl::CacheGetResult result = egl::CacheGetResult::NotFound;
1397 return loadBinary(context, binary, length, &result);
1398 }
1399
loadBinary(const Context * context,const void * binary,GLsizei length,egl::CacheGetResult * resultOut)1400 angle::Result Program::loadBinary(const Context *context,
1401 const void *binary,
1402 GLsizei length,
1403 egl::CacheGetResult *resultOut)
1404 {
1405 *resultOut = egl::CacheGetResult::Rejected;
1406
1407 ASSERT(mLinkingState);
1408 unlink();
1409
1410 BinaryInputStream stream(binary, length);
1411 if (!deserialize(context, stream))
1412 {
1413 return angle::Result::Continue;
1414 }
1415 // Currently we require the full shader text to compute the program hash.
1416 // We could also store the binary in the internal program cache.
1417
1418 // Initialize the uniform block -> buffer index map based on serialized data.
1419 mState.mExecutable->initInterfaceBlockBindings();
1420
1421 // If load does not succeed, we know for sure that the binary is not compatible with the
1422 // backend. The loaded binary could have been read from the on-disk shader cache and be
1423 // corrupted or serialized with different revision and subsystem id than the currently loaded
1424 // backend. Returning to the caller results in link happening using the original shader
1425 // sources.
1426 std::shared_ptr<rx::LinkTask> loadTask;
1427 ANGLE_TRY(mProgram->load(context, &stream, &loadTask, resultOut));
1428 if (*resultOut == egl::CacheGetResult::Rejected)
1429 {
1430 return angle::Result::Continue;
1431 }
1432
1433 std::unique_ptr<LinkEvent> loadEvent;
1434 if (loadTask)
1435 {
1436 std::shared_ptr<MainLinkLoadTask> mainLoadTask(new MainLoadTask(
1437 context->getLinkSubTaskThreadPool(), this, &mState, std::move(loadTask)));
1438
1439 std::shared_ptr<angle::WaitableEvent> mainLoadEvent =
1440 context->getShaderCompileThreadPool()->postWorkerTask(mainLoadTask);
1441 loadEvent = std::make_unique<MainLinkLoadEvent>(mainLoadTask, mainLoadEvent);
1442 }
1443 else
1444 {
1445 loadEvent = std::make_unique<LinkEventDone>(angle::Result::Continue);
1446 }
1447
1448 mLinkingState->linkingFromBinary = true;
1449 mLinkingState->linkEvent = std::move(loadEvent);
1450
1451 // Don't attempt to cache the binary that's just loaded
1452 mIsBinaryCached = true;
1453
1454 *resultOut = egl::CacheGetResult::Success;
1455
1456 return angle::Result::Continue;
1457 }
1458
getBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length)1459 angle::Result Program::getBinary(Context *context,
1460 GLenum *binaryFormat,
1461 void *binary,
1462 GLsizei bufSize,
1463 GLsizei *length)
1464 {
1465 if (!mState.mBinaryRetrieveableHint)
1466 {
1467 ANGLE_PERF_WARNING(
1468 context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
1469 "Saving program binary without GL_PROGRAM_BINARY_RETRIEVABLE_HINT is suboptimal.");
1470 }
1471
1472 ASSERT(!mLinkingState);
1473 if (binaryFormat)
1474 {
1475 *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1476 }
1477
1478 // Serialize the program only if not already done.
1479 if (mBinary.empty())
1480 {
1481 ANGLE_TRY(serialize(context));
1482 }
1483
1484 GLsizei streamLength = static_cast<GLsizei>(mBinary.size());
1485 const uint8_t *streamState = mBinary.data();
1486
1487 if (streamLength > bufSize)
1488 {
1489 if (length)
1490 {
1491 *length = 0;
1492 }
1493
1494 // TODO: This should be moved to the validation layer but computing the size of the binary
1495 // before saving it causes the save to happen twice. It may be possible to write the binary
1496 // to a separate buffer, validate sizes and then copy it.
1497 ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1498 }
1499
1500 if (binary)
1501 {
1502 char *ptr = reinterpret_cast<char *>(binary);
1503
1504 memcpy(ptr, streamState, streamLength);
1505 ptr += streamLength;
1506
1507 ASSERT(ptr - streamLength == binary);
1508
1509 // Once the binary is retrieved, assume the application will never need the binary and
1510 // release the memory. Note that implicit caching to blob cache is disabled when the
1511 // GL_PROGRAM_BINARY_RETRIEVABLE_HINT is set. If that hint is not set, serialization is
1512 // done twice, which is what the perf warning above is about!
1513 mBinary.clear();
1514 }
1515
1516 if (length)
1517 {
1518 *length = streamLength;
1519 }
1520
1521 return angle::Result::Continue;
1522 }
1523
getBinaryLength(Context * context)1524 GLint Program::getBinaryLength(Context *context)
1525 {
1526 ASSERT(!mLinkingState);
1527 if (!mLinked)
1528 {
1529 return 0;
1530 }
1531
1532 GLint length;
1533 angle::Result result =
1534 getBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1535 if (result != angle::Result::Continue)
1536 {
1537 return 0;
1538 }
1539
1540 return length;
1541 }
1542
setBinaryRetrievableHint(bool retrievable)1543 void Program::setBinaryRetrievableHint(bool retrievable)
1544 {
1545 ASSERT(!mLinkingState);
1546 // TODO(jmadill) : replace with dirty bits
1547 mProgram->setBinaryRetrievableHint(retrievable);
1548 mState.mBinaryRetrieveableHint = retrievable;
1549 }
1550
getBinaryRetrievableHint() const1551 bool Program::getBinaryRetrievableHint() const
1552 {
1553 ASSERT(!mLinkingState);
1554 return mState.mBinaryRetrieveableHint;
1555 }
1556
getInfoLogLength() const1557 int Program::getInfoLogLength() const
1558 {
1559 return static_cast<int>(mState.mInfoLog.getLength());
1560 }
1561
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const1562 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
1563 {
1564 return mState.mInfoLog.getLog(bufSize, length, infoLog);
1565 }
1566
setSeparable(const Context * context,bool separable)1567 void Program::setSeparable(const Context *context, bool separable)
1568 {
1569 ASSERT(!mLinkingState);
1570
1571 if (isSeparable() != separable)
1572 {
1573 mProgram->setSeparable(separable);
1574 mState.mSeparable = separable;
1575 }
1576 }
1577
deleteSelf(const Context * context)1578 void Program::deleteSelf(const Context *context)
1579 {
1580 ASSERT(mRefCount == 0 && mDeleteStatus);
1581 mResourceManager->deleteProgram(context, mHandle);
1582 }
1583
getRefCount() const1584 unsigned int Program::getRefCount() const
1585 {
1586 return mRefCount;
1587 }
1588
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const1589 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
1590 {
1591 int total = 0;
1592
1593 for (const Shader *shader : mAttachedShaders)
1594 {
1595 if (shader != nullptr && total < maxCount)
1596 {
1597 shaders[total] = shader->getHandle();
1598 ++total;
1599 }
1600 }
1601
1602 if (count)
1603 {
1604 *count = total;
1605 }
1606 }
1607
flagForDeletion()1608 void Program::flagForDeletion()
1609 {
1610 ASSERT(!mLinkingState);
1611 mDeleteStatus = true;
1612 }
1613
isFlaggedForDeletion() const1614 bool Program::isFlaggedForDeletion() const
1615 {
1616 ASSERT(!mLinkingState);
1617 return mDeleteStatus;
1618 }
1619
validate(const Caps & caps)1620 void Program::validate(const Caps &caps)
1621 {
1622 ASSERT(!mLinkingState);
1623 mState.mInfoLog.reset();
1624
1625 if (mLinked)
1626 {
1627 mValidated = ConvertToBool(mProgram->validate(caps));
1628 }
1629 else
1630 {
1631 mState.mInfoLog << "Program has not been successfully linked.";
1632 }
1633 }
1634
isValidated() const1635 bool Program::isValidated() const
1636 {
1637 ASSERT(!mLinkingState);
1638 return mValidated;
1639 }
1640
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)1641 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
1642 {
1643 ASSERT(!mLinkingState);
1644
1645 mState.mExecutable->remapUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
1646
1647 mProgram->onUniformBlockBinding(uniformBlockIndex);
1648
1649 onStateChange(
1650 angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(uniformBlockIndex.value));
1651 }
1652
setTransformFeedbackVaryings(const Context * context,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)1653 void Program::setTransformFeedbackVaryings(const Context *context,
1654 GLsizei count,
1655 const GLchar *const *varyings,
1656 GLenum bufferMode)
1657 {
1658 ASSERT(!mLinkingState);
1659
1660 mState.mTransformFeedbackVaryingNames.resize(count);
1661 for (GLsizei i = 0; i < count; i++)
1662 {
1663 mState.mTransformFeedbackVaryingNames[i] = varyings[i];
1664 }
1665
1666 mState.mTransformFeedbackBufferMode = bufferMode;
1667 }
1668
linkValidateShaders()1669 bool Program::linkValidateShaders()
1670 {
1671 // Wait for attached shaders to finish compilation. At this point, they need to be checked
1672 // whether they successfully compiled. This information is cached so that all compile jobs can
1673 // be waited on and their corresponding objects released before the actual check.
1674 //
1675 // Note that this function is called from the link job, and is therefore not protected by any
1676 // locks.
1677 ShaderBitSet successfullyCompiledShaders;
1678 for (ShaderType shaderType : AllShaderTypes())
1679 {
1680 const SharedCompileJob &compileJob = mState.mShaderCompileJobs[shaderType];
1681 if (compileJob)
1682 {
1683 const bool success = WaitCompileJobUnlocked(compileJob);
1684 successfullyCompiledShaders.set(shaderType, success);
1685 }
1686 }
1687 mState.mShaderCompileJobs = {};
1688
1689 const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;
1690
1691 bool isComputeShaderAttached = shaders[ShaderType::Compute].get() != nullptr;
1692 bool isGraphicsShaderAttached = shaders[ShaderType::Vertex].get() != nullptr ||
1693 shaders[ShaderType::TessControl].get() != nullptr ||
1694 shaders[ShaderType::TessEvaluation].get() != nullptr ||
1695 shaders[ShaderType::Geometry].get() != nullptr ||
1696 shaders[ShaderType::Fragment].get() != nullptr;
1697 // Check whether we both have a compute and non-compute shaders attached.
1698 // If there are of both types attached, then linking should fail.
1699 // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
1700 if (isComputeShaderAttached && isGraphicsShaderAttached)
1701 {
1702 mState.mInfoLog << "Both compute and graphics shaders are attached to the same program.";
1703 return false;
1704 }
1705
1706 Optional<int> version;
1707 for (ShaderType shaderType : kAllGraphicsShaderTypes)
1708 {
1709 const SharedCompiledShaderState &shader = shaders[shaderType];
1710 ASSERT(!shader || shader->shaderType == shaderType);
1711
1712 if (!shader)
1713 {
1714 continue;
1715 }
1716
1717 if (!successfullyCompiledShaders.test(shaderType))
1718 {
1719 mState.mInfoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
1720 return false;
1721 }
1722
1723 if (!version.valid())
1724 {
1725 version = shader->shaderVersion;
1726 }
1727 else if (version != shader->shaderVersion)
1728 {
1729 mState.mInfoLog << ShaderTypeToString(shaderType)
1730 << " shader version does not match other shader versions.";
1731 return false;
1732 }
1733 }
1734
1735 if (isComputeShaderAttached)
1736 {
1737 ASSERT(shaders[ShaderType::Compute]->shaderType == ShaderType::Compute);
1738
1739 // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
1740 // If the work group size is not specified, a link time error should occur.
1741 if (!shaders[ShaderType::Compute]->localSize.isDeclared())
1742 {
1743 mState.mInfoLog << "Work group size is not specified.";
1744 return false;
1745 }
1746 }
1747 else
1748 {
1749 if (!isGraphicsShaderAttached)
1750 {
1751 mState.mInfoLog << "No compiled shaders.";
1752 return false;
1753 }
1754
1755 bool hasVertex = shaders[ShaderType::Vertex].get() != nullptr;
1756 bool hasFragment = shaders[ShaderType::Fragment].get() != nullptr;
1757 if (!isSeparable() && (!hasVertex || !hasFragment))
1758 {
1759 mState.mInfoLog
1760 << "The program must contain objects to form both a vertex and fragment shader.";
1761 return false;
1762 }
1763
1764 bool hasTessControl = shaders[ShaderType::TessControl].get() != nullptr;
1765 bool hasTessEvaluation = shaders[ShaderType::TessEvaluation].get() != nullptr;
1766 if (!isSeparable() && (hasTessControl != hasTessEvaluation))
1767 {
1768 mState.mInfoLog
1769 << "Tessellation control and evaluation shaders must be specified together.";
1770 return false;
1771 }
1772
1773 const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
1774 if (geometryShader)
1775 {
1776 // [GL_EXT_geometry_shader] Chapter 7
1777 // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
1778 // Language Specification, as well as any of the following reasons:
1779 // * One or more of the shader objects attached to <program> are not compiled
1780 // successfully.
1781 // * The shaders do not use the same shader language version.
1782 // * <program> contains objects to form a geometry shader, and
1783 // - <program> is not separable and contains no objects to form a vertex shader; or
1784 // - the input primitive type, output primitive type, or maximum output vertex count
1785 // is not specified in the compiled geometry shader object.
1786 if (!geometryShader->hasValidGeometryShaderInputPrimitiveType())
1787 {
1788 mState.mInfoLog << "Input primitive type is not specified in the geometry shader.";
1789 return false;
1790 }
1791
1792 if (!geometryShader->hasValidGeometryShaderOutputPrimitiveType())
1793 {
1794 mState.mInfoLog << "Output primitive type is not specified in the geometry shader.";
1795 return false;
1796 }
1797
1798 if (!geometryShader->hasValidGeometryShaderMaxVertices())
1799 {
1800 mState.mInfoLog << "'max_vertices' is not specified in the geometry shader.";
1801 return false;
1802 }
1803 }
1804
1805 const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
1806 if (tessControlShader)
1807 {
1808 int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
1809 if (tcsShaderVertices == 0)
1810 {
1811 // In tessellation control shader, output vertices should be specified at least
1812 // once.
1813 // > GLSL ES Version 3.20.6 spec:
1814 // > 4.4.2. Output Layout Qualifiers
1815 // > Tessellation Control Outputs
1816 // > ...
1817 // > There must be at least one layout qualifier specifying an output patch vertex
1818 // > count in any program containing a tessellation control shader.
1819 mState.mInfoLog << "In Tessellation Control Shader, at least one layout qualifier "
1820 "specifying an output patch vertex count must exist.";
1821 return false;
1822 }
1823 }
1824
1825 const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
1826 if (tessEvaluationShader)
1827 {
1828 GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;
1829 if (tesPrimitiveMode == 0)
1830 {
1831 // In tessellation evaluation shader, a primitive mode should be specified at least
1832 // once.
1833 // > GLSL ES Version 3.20.6 spec:
1834 // > 4.4.1. Input Layout Qualifiers
1835 // > Tessellation Evaluation Inputs
1836 // > ...
1837 // > The tessellation evaluation shader object in a program must declare a primitive
1838 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
1839 // > identifiers is optional.
1840 mState.mInfoLog
1841 << "The Tessellation Evaluation Shader object in a program must declare a "
1842 "primitive mode in its input layout.";
1843 return false;
1844 }
1845 }
1846 }
1847
1848 return true;
1849 }
1850
1851 // Assumes linkValidateShaders() has validated the shaders and caches some values from the shaders.
linkShaders()1852 void Program::linkShaders()
1853 {
1854 const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;
1855
1856 const bool isComputeShaderAttached = shaders[ShaderType::Compute].get() != nullptr;
1857
1858 if (isComputeShaderAttached)
1859 {
1860 mState.mExecutable->mPod.computeShaderLocalSize = shaders[ShaderType::Compute]->localSize;
1861 }
1862 else
1863 {
1864 const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
1865 if (geometryShader)
1866 {
1867 mState.mExecutable->mPod.geometryShaderInputPrimitiveType =
1868 geometryShader->geometryShaderInputPrimitiveType;
1869 mState.mExecutable->mPod.geometryShaderOutputPrimitiveType =
1870 geometryShader->geometryShaderOutputPrimitiveType;
1871 mState.mExecutable->mPod.geometryShaderMaxVertices =
1872 geometryShader->geometryShaderMaxVertices;
1873 mState.mExecutable->mPod.geometryShaderInvocations =
1874 geometryShader->geometryShaderInvocations;
1875 }
1876
1877 const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
1878 if (tessControlShader)
1879 {
1880 int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
1881 mState.mExecutable->mPod.tessControlShaderVertices = tcsShaderVertices;
1882 }
1883
1884 const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
1885 if (tessEvaluationShader)
1886 {
1887 GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;
1888
1889 mState.mExecutable->mPod.tessGenMode = tesPrimitiveMode;
1890 mState.mExecutable->mPod.tessGenSpacing = tessEvaluationShader->tessGenSpacing;
1891 mState.mExecutable->mPod.tessGenVertexOrder = tessEvaluationShader->tessGenVertexOrder;
1892 mState.mExecutable->mPod.tessGenPointMode = tessEvaluationShader->tessGenPointMode;
1893 }
1894 }
1895 }
1896
linkVaryings()1897 bool Program::linkVaryings()
1898 {
1899 ShaderType previousShaderType = ShaderType::InvalidEnum;
1900 for (ShaderType shaderType : kAllGraphicsShaderTypes)
1901 {
1902 const SharedCompiledShaderState ¤tShader = mState.mAttachedShaders[shaderType];
1903 if (!currentShader)
1904 {
1905 continue;
1906 }
1907
1908 if (previousShaderType != ShaderType::InvalidEnum)
1909 {
1910 const SharedCompiledShaderState &previousShader =
1911 mState.mAttachedShaders[previousShaderType];
1912 const std::vector<sh::ShaderVariable> &outputVaryings = previousShader->outputVaryings;
1913
1914 if (!LinkValidateShaderInterfaceMatching(
1915 outputVaryings, currentShader->inputVaryings, previousShaderType,
1916 currentShader->shaderType, previousShader->shaderVersion,
1917 currentShader->shaderVersion, isSeparable(), mState.mInfoLog))
1918 {
1919 return false;
1920 }
1921 }
1922 previousShaderType = currentShader->shaderType;
1923 }
1924
1925 // TODO: http://anglebug.com/42262233 and http://anglebug.com/42262234
1926 // Need to move logic of validating builtin varyings inside the for-loop above.
1927 // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
1928 // can be redeclared in Geometry or Tessellation shaders as well.
1929 const SharedCompiledShaderState &vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1930 const SharedCompiledShaderState &fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1931 if (vertexShader && fragmentShader &&
1932 !LinkValidateBuiltInVaryings(vertexShader->outputVaryings, fragmentShader->inputVaryings,
1933 vertexShader->shaderType, fragmentShader->shaderType,
1934 vertexShader->shaderVersion, fragmentShader->shaderVersion,
1935 mState.mInfoLog))
1936 {
1937 return false;
1938 }
1939
1940 return true;
1941 }
1942
linkUniforms(const Caps & caps,const Version & clientVersion,std::vector<UnusedUniform> * unusedUniformsOutOrNull,GLuint * combinedImageUniformsOut)1943 bool Program::linkUniforms(const Caps &caps,
1944 const Version &clientVersion,
1945 std::vector<UnusedUniform> *unusedUniformsOutOrNull,
1946 GLuint *combinedImageUniformsOut)
1947 {
1948 // Initialize executable shader map.
1949 ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
1950 for (const SharedCompiledShaderState &shader : mState.mAttachedShaders)
1951 {
1952 if (shader)
1953 {
1954 shaderUniforms[shader->shaderType] = shader->uniforms;
1955 }
1956 }
1957
1958 if (!mState.mExecutable->linkUniforms(caps, shaderUniforms, mState.mUniformLocationBindings,
1959 combinedImageUniformsOut, unusedUniformsOutOrNull))
1960 {
1961 return false;
1962 }
1963
1964 if (clientVersion >= Version(3, 1))
1965 {
1966 GLint locationSize = static_cast<GLint>(mState.mExecutable->getUniformLocations().size());
1967
1968 if (locationSize > caps.maxUniformLocations)
1969 {
1970 mState.mInfoLog << "Exceeded maximum uniform location size";
1971 return false;
1972 }
1973 }
1974
1975 return true;
1976 }
1977
1978 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Caps & caps,const Limitations & limitations,bool webglCompatibility)1979 bool Program::linkAttributes(const Caps &caps,
1980 const Limitations &limitations,
1981 bool webglCompatibility)
1982 {
1983 int shaderVersion = -1;
1984 unsigned int usedLocations = 0;
1985
1986 const SharedCompiledShaderState &vertexShader = mState.getAttachedShader(ShaderType::Vertex);
1987
1988 if (!vertexShader)
1989 {
1990 // No vertex shader, so no attributes, so nothing to do
1991 return true;
1992 }
1993
1994 // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
1995 // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
1996 // aliasing checks.
1997 // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
1998 shaderVersion = vertexShader->shaderVersion;
1999 const std::vector<sh::ShaderVariable> &shaderAttributes =
2000 shaderVersion >= 300 ? vertexShader->allAttributes : vertexShader->activeAttributes;
2001
2002 ASSERT(mState.mExecutable->mProgramInputs.empty());
2003 mState.mExecutable->mProgramInputs.reserve(shaderAttributes.size());
2004
2005 GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
2006 std::vector<ProgramInput *> usedAttribMap(maxAttribs, nullptr);
2007
2008 for (const sh::ShaderVariable &shaderAttribute : shaderAttributes)
2009 {
2010 // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
2011 // structures, so we don't need to worry about adjusting their names or generating entries
2012 // for each member/element (unlike uniforms for example).
2013 ASSERT(!shaderAttribute.isArray() && !shaderAttribute.isStruct());
2014
2015 mState.mExecutable->mProgramInputs.emplace_back(shaderAttribute);
2016
2017 // Assign locations to attributes that have a binding location and check for attribute
2018 // aliasing.
2019 ProgramInput &attribute = mState.mExecutable->mProgramInputs.back();
2020 int bindingLocation = mState.mAttributeBindings.getBinding(attribute);
2021 if (attribute.getLocation() == -1 && bindingLocation != -1)
2022 {
2023 attribute.setLocation(bindingLocation);
2024 }
2025
2026 if (attribute.getLocation() != -1)
2027 {
2028 // Location is set by glBindAttribLocation or by location layout qualifier
2029 const int regs = VariableRegisterCount(attribute.getType());
2030
2031 if (static_cast<GLuint>(regs + attribute.getLocation()) > maxAttribs)
2032 {
2033 mState.mInfoLog << "Attribute (" << attribute.name << ") at location "
2034 << attribute.getLocation() << " is too big to fit";
2035
2036 return false;
2037 }
2038
2039 for (int reg = 0; reg < regs; reg++)
2040 {
2041 const int regLocation = attribute.getLocation() + reg;
2042 ProgramInput *linkedAttribute = usedAttribMap[regLocation];
2043
2044 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
2045 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
2046 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
2047 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
2048 if (linkedAttribute)
2049 {
2050 if (shaderVersion >= 300 || webglCompatibility ||
2051 limitations.noVertexAttributeAliasing)
2052 {
2053 mState.mInfoLog << "Attribute '" << attribute.name
2054 << "' aliases attribute '" << linkedAttribute->name
2055 << "' at location " << regLocation;
2056 return false;
2057 }
2058 }
2059 else
2060 {
2061 usedAttribMap[regLocation] = &attribute;
2062 }
2063
2064 usedLocations |= 1 << regLocation;
2065 }
2066 }
2067 }
2068
2069 // Assign locations to attributes that don't have a binding location.
2070 for (ProgramInput &attribute : mState.mExecutable->mProgramInputs)
2071 {
2072 // Not set by glBindAttribLocation or by location layout qualifier
2073 if (attribute.getLocation() == -1)
2074 {
2075 int regs = VariableRegisterCount(attribute.getType());
2076 int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
2077
2078 if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
2079 {
2080 mState.mInfoLog << "Too many attributes (" << attribute.name << ")";
2081 return false;
2082 }
2083
2084 attribute.setLocation(availableIndex);
2085 }
2086 }
2087
2088 ASSERT(mState.mExecutable->mPod.attributesTypeMask.none());
2089 ASSERT(mState.mExecutable->mPod.attributesMask.none());
2090
2091 // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
2092 // shader versions we're only processing active attributes to begin with.
2093 if (shaderVersion >= 300)
2094 {
2095 for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
2096 attributeIter != mState.mExecutable->getProgramInputs().end();)
2097 {
2098 if (attributeIter->isActive())
2099 {
2100 ++attributeIter;
2101 }
2102 else
2103 {
2104 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
2105 }
2106 }
2107 }
2108
2109 for (const ProgramInput &attribute : mState.mExecutable->getProgramInputs())
2110 {
2111 ASSERT(attribute.isActive());
2112 ASSERT(attribute.getLocation() != -1);
2113 unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.getType()));
2114
2115 unsigned int location = static_cast<unsigned int>(attribute.getLocation());
2116 for (unsigned int r = 0; r < regs; r++)
2117 {
2118 // Built-in active program inputs don't have a bound attribute.
2119 if (!attribute.isBuiltIn())
2120 {
2121 mState.mExecutable->mPod.activeAttribLocationsMask.set(location);
2122 mState.mExecutable->mPod.maxActiveAttribLocation =
2123 std::max(mState.mExecutable->mPod.maxActiveAttribLocation, location + 1);
2124
2125 ComponentType componentType =
2126 GLenumToComponentType(VariableComponentType(attribute.getType()));
2127
2128 SetComponentTypeMask(componentType, location,
2129 &mState.mExecutable->mPod.attributesTypeMask);
2130 mState.mExecutable->mPod.attributesMask.set(location);
2131
2132 location++;
2133 }
2134 }
2135 }
2136
2137 return true;
2138 }
2139
serialize(const Context * context)2140 angle::Result Program::serialize(const Context *context)
2141 {
2142 // In typical applications, the binary should already be empty here. However, in unusual
2143 // situations this may not be true. In particular, if the application doesn't set
2144 // GL_PROGRAM_BINARY_RETRIEVABLE_HINT, gets the program length but doesn't get the binary, the
2145 // cached binary remains until the program is destroyed or the program is bound (both causing
2146 // |waitForPostLinkTasks()| to cache the program in the blob cache).
2147 if (!mBinary.empty())
2148 {
2149 return angle::Result::Continue;
2150 }
2151
2152 BinaryOutputStream stream;
2153
2154 stream.writeBytes(
2155 reinterpret_cast<const unsigned char *>(angle::GetANGLEShaderProgramVersion()),
2156 angle::GetANGLEShaderProgramVersionHashSize());
2157
2158 stream.writeBool(angle::Is64Bit());
2159
2160 stream.writeInt(angle::GetANGLESHVersion());
2161
2162 stream.writeString(context->getRendererString());
2163
2164 // nullptr context is supported when computing binary length.
2165 if (context)
2166 {
2167 stream.writeInt(context->getClientVersion().major);
2168 stream.writeInt(context->getClientVersion().minor);
2169 }
2170 else
2171 {
2172 stream.writeInt(2);
2173 stream.writeInt(0);
2174 }
2175
2176 // mSeparable must be before mExecutable->save(), since it uses the value.
2177 stream.writeBool(mState.mSeparable);
2178 stream.writeInt(mState.mTransformFeedbackBufferMode);
2179
2180 stream.writeInt(mState.mTransformFeedbackVaryingNames.size());
2181 for (const std::string &name : mState.mTransformFeedbackVaryingNames)
2182 {
2183 stream.writeString(name);
2184 }
2185
2186 mState.mExecutable->save(&stream);
2187
2188 // Warn the app layer if saving a binary with unsupported transform feedback.
2189 if (!mState.mExecutable->getLinkedTransformFeedbackVaryings().empty() &&
2190 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
2191 {
2192 ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2193 "Saving program binary with transform feedback, which is not supported "
2194 "on this driver.");
2195 }
2196
2197 if (context->getShareGroup()->getFrameCaptureShared()->enabled())
2198 {
2199 // Serialize the source for each stage for re-use during capture
2200 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
2201 {
2202 Shader *shader = getAttachedShader(shaderType);
2203 if (shader)
2204 {
2205 stream.writeString(shader->getSourceString());
2206 }
2207 else
2208 {
2209 // If we don't have an attached shader, which would occur if this program was
2210 // created via glProgramBinary, pull from our cached copy
2211 const angle::ProgramSources &cachedLinkedSources =
2212 context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id());
2213 const std::string &cachedSourceString = cachedLinkedSources[shaderType];
2214 ASSERT(!cachedSourceString.empty());
2215 stream.writeString(cachedSourceString.c_str());
2216 }
2217 }
2218 }
2219
2220 mProgram->save(context, &stream);
2221 ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());
2222
2223 if (!mBinary.resize(stream.length()))
2224 {
2225 ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2226 "Failed to allocate enough memory to serialize a program. (%zu bytes)",
2227 stream.length());
2228 return angle::Result::Stop;
2229 }
2230 memcpy(mBinary.data(), stream.data(), stream.length());
2231 return angle::Result::Continue;
2232 }
2233
deserialize(const Context * context,BinaryInputStream & stream)2234 bool Program::deserialize(const Context *context, BinaryInputStream &stream)
2235 {
2236 std::vector<uint8_t> angleShaderProgramVersionString(
2237 angle::GetANGLEShaderProgramVersionHashSize(), 0);
2238 stream.readBytes(angleShaderProgramVersionString.data(),
2239 angleShaderProgramVersionString.size());
2240 if (memcmp(angleShaderProgramVersionString.data(), angle::GetANGLEShaderProgramVersion(),
2241 angleShaderProgramVersionString.size()) != 0)
2242 {
2243 mState.mInfoLog << "Invalid program binary version.";
2244 return false;
2245 }
2246
2247 bool binaryIs64Bit = stream.readBool();
2248 if (binaryIs64Bit != angle::Is64Bit())
2249 {
2250 mState.mInfoLog << "cannot load program binaries across CPU architectures.";
2251 return false;
2252 }
2253
2254 int angleSHVersion = stream.readInt<int>();
2255 if (angleSHVersion != angle::GetANGLESHVersion())
2256 {
2257 mState.mInfoLog << "cannot load program binaries across different angle sh version.";
2258 return false;
2259 }
2260
2261 std::string rendererString = stream.readString();
2262 if (rendererString != context->getRendererString())
2263 {
2264 mState.mInfoLog << "Cannot load program binary due to changed renderer string.";
2265 return false;
2266 }
2267
2268 int majorVersion = stream.readInt<int>();
2269 int minorVersion = stream.readInt<int>();
2270 if (majorVersion != context->getClientMajorVersion() ||
2271 minorVersion != context->getClientMinorVersion())
2272 {
2273 mState.mInfoLog << "Cannot load program binaries across different ES context versions.";
2274 return false;
2275 }
2276
2277 mState.mSeparable = stream.readBool();
2278 mState.mTransformFeedbackBufferMode = stream.readInt<GLenum>();
2279
2280 mState.mTransformFeedbackVaryingNames.resize(stream.readInt<size_t>());
2281 for (std::string &name : mState.mTransformFeedbackVaryingNames)
2282 {
2283 name = stream.readString();
2284 }
2285
2286 // mSeparable must be before mExecutable->load(), since it uses the value. This state is
2287 // duplicated in the executable for convenience.
2288 mState.mExecutable->mPod.isSeparable = mState.mSeparable;
2289 mState.mExecutable->load(&stream);
2290
2291 static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
2292 "Too many shader types");
2293
2294 // Reject programs that use transform feedback varyings if the hardware cannot support them.
2295 if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
2296 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
2297 {
2298 mState.mInfoLog << "Current driver does not support transform feedback in binary programs.";
2299 return false;
2300 }
2301
2302 if (!mState.mAttachedShaders[ShaderType::Compute])
2303 {
2304 mState.mExecutable->updateTransformFeedbackStrides();
2305 mState.mExecutable->mTransformFeedbackVaryingNames = mState.mTransformFeedbackVaryingNames;
2306 }
2307
2308 if (context->getShareGroup()->getFrameCaptureShared()->enabled())
2309 {
2310 // Extract the source for each stage from the program binary
2311 angle::ProgramSources sources;
2312
2313 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
2314 {
2315 std::string shaderSource = stream.readString();
2316 ASSERT(shaderSource.length() > 0);
2317 sources[shaderType] = std::move(shaderSource);
2318 }
2319
2320 // Store it for use during mid-execution capture
2321 context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(),
2322 std::move(sources));
2323 }
2324
2325 return true;
2326 }
2327
postResolveLink(const Context * context)2328 void Program::postResolveLink(const Context *context)
2329 {
2330 mState.updateActiveSamplers();
2331 mState.mExecutable->mActiveImageShaderBits.fill({});
2332 mState.mExecutable->updateActiveImages(getExecutable());
2333
2334 mState.mExecutable->initInterfaceBlockBindings();
2335 mState.mExecutable->setUniformValuesFromBindingQualifiers();
2336
2337 if (context->getExtensions().multiDrawANGLE)
2338 {
2339 mState.mExecutable->mPod.drawIDLocation =
2340 mState.mExecutable->getUniformLocation("gl_DrawID").value;
2341 }
2342
2343 if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE)
2344 {
2345 mState.mExecutable->mPod.baseVertexLocation =
2346 mState.mExecutable->getUniformLocation("gl_BaseVertex").value;
2347 mState.mExecutable->mPod.baseInstanceLocation =
2348 mState.mExecutable->getUniformLocation("gl_BaseInstance").value;
2349 }
2350 }
2351
cacheProgramBinaryIfNotAlready(const Context * context)2352 void Program::cacheProgramBinaryIfNotAlready(const Context *context)
2353 {
2354 // If program caching is disabled, we already consider the binary cached.
2355 ASSERT(!context->getFrontendFeatures().disableProgramCaching.enabled || mIsBinaryCached);
2356 if (!mLinked || mIsBinaryCached || mState.mBinaryRetrieveableHint)
2357 {
2358 // Program caching is disabled, the program is yet to be linked, it's already cached, or the
2359 // application has specified that it prefers to cache the program binary itself.
2360 return;
2361 }
2362
2363 // No post-link tasks should be pending.
2364 ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());
2365
2366 // Save to the program cache.
2367 std::lock_guard<angle::SimpleMutex> cacheLock(context->getProgramCacheMutex());
2368 MemoryProgramCache *cache = context->getMemoryProgramCache();
2369 // TODO: http://anglebug.com/42263141: Enable program caching for separable programs
2370 if (cache && !isSeparable() &&
2371 (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
2372 !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
2373 {
2374 if (cache->putProgram(mProgramHash, context, this) == angle::Result::Stop)
2375 {
2376 // Don't fail linking if putting the program binary into the cache fails, the program is
2377 // still usable.
2378 ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2379 "Failed to save linked program to memory program cache.");
2380 }
2381
2382 // Drop the binary; the application didn't specify that it wants to retrieve the binary. If
2383 // it did, we wouldn't be implicitly caching it.
2384 mBinary.clear();
2385 }
2386
2387 mIsBinaryCached = true;
2388 }
2389
dumpProgramInfo(const Context * context) const2390 void Program::dumpProgramInfo(const Context *context) const
2391 {
2392 std::stringstream dumpStream;
2393 for (ShaderType shaderType : angle::AllEnums<ShaderType>())
2394 {
2395 Shader *shader = getAttachedShader(shaderType);
2396 if (shader)
2397 {
2398 dumpStream << shader->getType() << ": "
2399 << GetShaderDumpFileName(shader->getSourceHash()) << std::endl;
2400 }
2401 }
2402
2403 std::string dump = dumpStream.str();
2404 size_t dumpHash = std::hash<std::string>{}(dump);
2405
2406 std::stringstream pathStream;
2407 std::string shaderDumpDir = GetShaderDumpFileDirectory();
2408 if (!shaderDumpDir.empty())
2409 {
2410 pathStream << shaderDumpDir << "/";
2411 }
2412 pathStream << dumpHash << ".program";
2413 std::string path = pathStream.str();
2414
2415 writeFile(path.c_str(), dump.c_str(), dump.length());
2416 INFO() << "Dumped program: " << path;
2417 }
2418 } // namespace gl
2419