• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/8661)
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/4530: 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(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1054                     &mState.mExecutable->mUniformNames, &mState.mExecutable->mUniformMappedNames,
1055                     &mState.mExecutable->mShaderStorageBlocks,
1056                     &mState.mExecutable->mBufferVariables,
1057                     &mState.mExecutable->mAtomicCounterBuffers);
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.advancedBlendEquations =
1160                 fragmentShader->advancedBlendEquations;
1161             mState.mExecutable->mPod.specConstUsageBits |= fragmentShader->specConstUsageBits;
1162 
1163             for (uint32_t index = 0; index < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++index)
1164             {
1165                 const sh::MetadataFlags flag = static_cast<sh::MetadataFlags>(
1166                     static_cast<uint32_t>(sh::MetadataFlags::HasInputAttachment0) + index);
1167                 if (fragmentShader->metadataFlags.test(flag))
1168                 {
1169                     mState.mExecutable->mPod.fragmentInoutIndices.set(index);
1170                 }
1171             }
1172         }
1173 
1174         *mergedVaryingsOut = GetMergedVaryingsFromLinkingVariables(*linkingVariables);
1175         if (!mState.mExecutable->linkMergedVaryings(caps, limitations, clientVersion, isWebGL,
1176                                                     *mergedVaryingsOut, *linkingVariables,
1177                                                     &resources->varyingPacking))
1178         {
1179             return angle::Result::Stop;
1180         }
1181     }
1182 
1183     mState.mExecutable->saveLinkedStateInfo(mState);
1184 
1185     return angle::Result::Continue;
1186 }
1187 
isLinking() const1188 bool Program::isLinking() const
1189 {
1190     return mLinkingState.get() && mLinkingState->linkEvent && mLinkingState->linkEvent->isLinking();
1191 }
1192 
isBinaryReady(const Context * context)1193 bool Program::isBinaryReady(const Context *context)
1194 {
1195     if (mState.mExecutable->mPostLinkSubTasks.empty())
1196     {
1197         // Ensure the program binary is cached, even if the backend waits for post-link tasks
1198         // without the knowledge of the front-end.
1199         cacheProgramBinaryIfNotAlready(context);
1200         return true;
1201     }
1202 
1203     const bool allPostLinkTasksComplete =
1204         angle::WaitableEvent::AllReady(&mState.mExecutable->getPostLinkSubTaskWaitableEvents());
1205 
1206     // Once the binary is ready, the |glGetProgramBinary| call will result in
1207     // |waitForPostLinkTasks| which in turn may internally cache the binary.  However, for the sake
1208     // of blob cache tests, call |waitForPostLinkTasks| anyway if tasks are already complete.
1209     if (allPostLinkTasksComplete)
1210     {
1211         waitForPostLinkTasks(context);
1212     }
1213 
1214     return allPostLinkTasksComplete;
1215 }
1216 
resolveLinkImpl(const Context * context)1217 void Program::resolveLinkImpl(const Context *context)
1218 {
1219     ASSERT(mLinkingState.get());
1220 
1221     angle::Result result                       = mLinkingState->linkEvent->wait(context);
1222     mLinked                                    = result == angle::Result::Continue;
1223     std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1224     if (!mLinked)
1225     {
1226         // If the link fails, the spec allows program queries to either return empty results (all
1227         // zeros) or whatever parts of the link happened to have been done before the failure:
1228         //
1229         // > Implementations may return information on variables and interface blocks that would
1230         // > have been active had the program been linked successfully.  In cases where the link
1231         // > failed because the program required too many resources, these commands may help
1232         // > applications determine why limits were exceeded. However, the information returned in
1233         // > this case is implementation-dependent and may be incomplete.
1234         //
1235         // The above means that it's ok for ANGLE to reset the executable here, but it *may* be
1236         // helpful to applications if it doesn't.  We do reset it however, the info log should
1237         // already have enough debug information for the application.
1238         mState.mExecutable->reset();
1239         return;
1240     }
1241 
1242     // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1243     // Only successfully linked program can replace the executables.
1244     ASSERT(mLinked);
1245 
1246     // Mark implementation-specific unreferenced uniforms as ignored.
1247     std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1248     mProgram->markUnusedUniformLocations(&mState.mExecutable->mUniformLocations,
1249                                          &mState.mExecutable->mSamplerBindings, imageBindings);
1250 
1251     // Must be called after markUnusedUniformLocations.
1252     postResolveLink(context);
1253 
1254     // Notify observers that a new linked executable is available.  If this program is current on a
1255     // context, the executable is reinstalled.  If it is attached to a PPO, it is installed there
1256     // and the PPO is marked as needing to be linked again.
1257     onStateChange(angle::SubjectMessage::ProgramRelinked);
1258 
1259     // Cache the program if:
1260     //
1261     // - Not loading from binary, in which case the program is already in the cache.
1262     // - There are no post link tasks. If there are any, waitForPostLinkTasks will do this
1263     //   instead.
1264     //   * Note that serialize() calls waitForPostLinkTasks, so caching the binary here
1265     //     effectively forces a wait for the post-link tasks.
1266     //
1267     if (!linkingState->linkingFromBinary && mState.mExecutable->mPostLinkSubTasks.empty())
1268     {
1269         cacheProgramBinaryIfNotAlready(context);
1270     }
1271 }
1272 
waitForPostLinkTasks(const Context * context)1273 void Program::waitForPostLinkTasks(const Context *context)
1274 {
1275     // No-op if no tasks.
1276     mState.mExecutable->waitForPostLinkTasks(context);
1277 
1278     // Now that the subtasks are done, cache the binary (this was deferred in resolveLinkImpl).
1279     cacheProgramBinaryIfNotAlready(context);
1280 }
1281 
updateLinkedShaderStages()1282 void Program::updateLinkedShaderStages()
1283 {
1284     mState.mExecutable->resetLinkedShaderStages();
1285 
1286     for (ShaderType shaderType : AllShaderTypes())
1287     {
1288         if (mState.mAttachedShaders[shaderType])
1289         {
1290             mState.mExecutable->setLinkedShaderStages(shaderType);
1291         }
1292     }
1293 }
1294 
updateActiveSamplers()1295 void ProgramState::updateActiveSamplers()
1296 {
1297     mExecutable->mActiveSamplerRefCounts.fill(0);
1298     mExecutable->updateActiveSamplers(*mExecutable);
1299 }
1300 
updateProgramInterfaceInputs()1301 void ProgramState::updateProgramInterfaceInputs()
1302 {
1303     const ShaderType firstAttachedShaderType = mExecutable->getFirstLinkedShaderStageType();
1304 
1305     if (firstAttachedShaderType == ShaderType::Vertex)
1306     {
1307         // Vertex attributes are already what we need, so nothing to do
1308         return;
1309     }
1310 
1311     const SharedCompiledShaderState &shader = getAttachedShader(firstAttachedShaderType);
1312     ASSERT(shader);
1313 
1314     // Copy over each input varying, since the Shader could go away
1315     if (shader->shaderType == ShaderType::Compute)
1316     {
1317         for (const sh::ShaderVariable &attribute : shader->allAttributes)
1318         {
1319             // Compute Shaders have the following built-in input variables.
1320             //
1321             // in uvec3 gl_NumWorkGroups;
1322             // in uvec3 gl_WorkGroupID;
1323             // in uvec3 gl_LocalInvocationID;
1324             // in uvec3 gl_GlobalInvocationID;
1325             // in uint  gl_LocalInvocationIndex;
1326             // They are all vecs or uints, so no special handling is required.
1327             mExecutable->mProgramInputs.emplace_back(attribute);
1328         }
1329     }
1330     else
1331     {
1332         for (const sh::ShaderVariable &varying : shader->inputVaryings)
1333         {
1334             UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1335         }
1336     }
1337 }
1338 
updateProgramInterfaceOutputs()1339 void ProgramState::updateProgramInterfaceOutputs()
1340 {
1341     const ShaderType lastAttachedShaderType = mExecutable->getLastLinkedShaderStageType();
1342 
1343     if (lastAttachedShaderType == ShaderType::Fragment)
1344     {
1345         // Fragment outputs are already what we need, so nothing to do
1346         return;
1347     }
1348     if (lastAttachedShaderType == ShaderType::Compute)
1349     {
1350         // If the program only contains a Compute Shader, then there are no user-defined outputs.
1351         return;
1352     }
1353 
1354     const SharedCompiledShaderState &shader = getAttachedShader(lastAttachedShaderType);
1355     ASSERT(shader);
1356 
1357     // Copy over each output varying, since the Shader could go away
1358     for (const sh::ShaderVariable &varying : shader->outputVaryings)
1359     {
1360         UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1361     }
1362 }
1363 
1364 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1365 void Program::unlink()
1366 {
1367     // There is always a new executable created on link, so the executable is already in a clean
1368     // state.
1369 
1370     mValidated = false;
1371 }
1372 
setBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1373 angle::Result Program::setBinary(const Context *context,
1374                                  GLenum binaryFormat,
1375                                  const void *binary,
1376                                  GLsizei length)
1377 {
1378     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1379 
1380     makeNewExecutable(context);
1381 
1382     egl::CacheGetResult result = egl::CacheGetResult::NotFound;
1383     return loadBinary(context, binary, length, &result);
1384 }
1385 
loadBinary(const Context * context,const void * binary,GLsizei length,egl::CacheGetResult * resultOut)1386 angle::Result Program::loadBinary(const Context *context,
1387                                   const void *binary,
1388                                   GLsizei length,
1389                                   egl::CacheGetResult *resultOut)
1390 {
1391     *resultOut = egl::CacheGetResult::Rejected;
1392 
1393     ASSERT(mLinkingState);
1394     unlink();
1395 
1396     BinaryInputStream stream(binary, length);
1397     if (!deserialize(context, stream))
1398     {
1399         return angle::Result::Continue;
1400     }
1401     // Currently we require the full shader text to compute the program hash.
1402     // We could also store the binary in the internal program cache.
1403 
1404     // Initialize the uniform block -> buffer index map based on serialized data.
1405     mState.mExecutable->initInterfaceBlockBindings();
1406 
1407     // If load does not succeed, we know for sure that the binary is not compatible with the
1408     // backend.  The loaded binary could have been read from the on-disk shader cache and be
1409     // corrupted or serialized with different revision and subsystem id than the currently loaded
1410     // backend.  Returning to the caller results in link happening using the original shader
1411     // sources.
1412     std::shared_ptr<rx::LinkTask> loadTask;
1413     ANGLE_TRY(mProgram->load(context, &stream, &loadTask, resultOut));
1414     if (*resultOut == egl::CacheGetResult::Rejected)
1415     {
1416         return angle::Result::Continue;
1417     }
1418 
1419     std::unique_ptr<LinkEvent> loadEvent;
1420     if (loadTask)
1421     {
1422         std::shared_ptr<MainLinkLoadTask> mainLoadTask(new MainLoadTask(
1423             context->getLinkSubTaskThreadPool(), this, &mState, std::move(loadTask)));
1424 
1425         std::shared_ptr<angle::WaitableEvent> mainLoadEvent =
1426             context->getShaderCompileThreadPool()->postWorkerTask(mainLoadTask);
1427         loadEvent = std::make_unique<MainLinkLoadEvent>(mainLoadTask, mainLoadEvent);
1428     }
1429     else
1430     {
1431         loadEvent = std::make_unique<LinkEventDone>(angle::Result::Continue);
1432     }
1433 
1434     mLinkingState->linkingFromBinary = true;
1435     mLinkingState->linkEvent         = std::move(loadEvent);
1436 
1437     // Don't attempt to cache the binary that's just loaded
1438     mIsBinaryCached = true;
1439 
1440     *resultOut = egl::CacheGetResult::Success;
1441 
1442     return angle::Result::Continue;
1443 }
1444 
getBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length)1445 angle::Result Program::getBinary(Context *context,
1446                                  GLenum *binaryFormat,
1447                                  void *binary,
1448                                  GLsizei bufSize,
1449                                  GLsizei *length)
1450 {
1451     if (!mState.mBinaryRetrieveableHint)
1452     {
1453         ANGLE_PERF_WARNING(
1454             context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
1455             "Saving program binary without GL_PROGRAM_BINARY_RETRIEVABLE_HINT is suboptimal.");
1456     }
1457 
1458     ASSERT(!mLinkingState);
1459     if (binaryFormat)
1460     {
1461         *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1462     }
1463 
1464     // Serialize the program only if not already done.
1465     if (mBinary.empty())
1466     {
1467         ANGLE_TRY(serialize(context));
1468     }
1469 
1470     GLsizei streamLength       = static_cast<GLsizei>(mBinary.size());
1471     const uint8_t *streamState = mBinary.data();
1472 
1473     if (streamLength > bufSize)
1474     {
1475         if (length)
1476         {
1477             *length = 0;
1478         }
1479 
1480         // TODO: This should be moved to the validation layer but computing the size of the binary
1481         // before saving it causes the save to happen twice.  It may be possible to write the binary
1482         // to a separate buffer, validate sizes and then copy it.
1483         ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1484     }
1485 
1486     if (binary)
1487     {
1488         char *ptr = reinterpret_cast<char *>(binary);
1489 
1490         memcpy(ptr, streamState, streamLength);
1491         ptr += streamLength;
1492 
1493         ASSERT(ptr - streamLength == binary);
1494 
1495         // Once the binary is retrieved, assume the application will never need the binary and
1496         // release the memory.  Note that implicit caching to blob cache is disabled when the
1497         // GL_PROGRAM_BINARY_RETRIEVABLE_HINT is set.  If that hint is not set, serialization is
1498         // done twice, which is what the perf warning above is about!
1499         mBinary.clear();
1500     }
1501 
1502     if (length)
1503     {
1504         *length = streamLength;
1505     }
1506 
1507     return angle::Result::Continue;
1508 }
1509 
getBinaryLength(Context * context)1510 GLint Program::getBinaryLength(Context *context)
1511 {
1512     ASSERT(!mLinkingState);
1513     if (!mLinked)
1514     {
1515         return 0;
1516     }
1517 
1518     GLint length;
1519     angle::Result result =
1520         getBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1521     if (result != angle::Result::Continue)
1522     {
1523         return 0;
1524     }
1525 
1526     return length;
1527 }
1528 
setBinaryRetrievableHint(bool retrievable)1529 void Program::setBinaryRetrievableHint(bool retrievable)
1530 {
1531     ASSERT(!mLinkingState);
1532     // TODO(jmadill) : replace with dirty bits
1533     mProgram->setBinaryRetrievableHint(retrievable);
1534     mState.mBinaryRetrieveableHint = retrievable;
1535 }
1536 
getBinaryRetrievableHint() const1537 bool Program::getBinaryRetrievableHint() const
1538 {
1539     ASSERT(!mLinkingState);
1540     return mState.mBinaryRetrieveableHint;
1541 }
1542 
getInfoLogLength() const1543 int Program::getInfoLogLength() const
1544 {
1545     return static_cast<int>(mState.mInfoLog.getLength());
1546 }
1547 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const1548 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
1549 {
1550     return mState.mInfoLog.getLog(bufSize, length, infoLog);
1551 }
1552 
setSeparable(const Context * context,bool separable)1553 void Program::setSeparable(const Context *context, bool separable)
1554 {
1555     ASSERT(!mLinkingState);
1556 
1557     if (isSeparable() != separable)
1558     {
1559         mProgram->setSeparable(separable);
1560         mState.mSeparable = separable;
1561     }
1562 }
1563 
deleteSelf(const Context * context)1564 void Program::deleteSelf(const Context *context)
1565 {
1566     ASSERT(mRefCount == 0 && mDeleteStatus);
1567     mResourceManager->deleteProgram(context, mHandle);
1568 }
1569 
getRefCount() const1570 unsigned int Program::getRefCount() const
1571 {
1572     return mRefCount;
1573 }
1574 
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const1575 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
1576 {
1577     int total = 0;
1578 
1579     for (const Shader *shader : mAttachedShaders)
1580     {
1581         if (shader != nullptr && total < maxCount)
1582         {
1583             shaders[total] = shader->getHandle();
1584             ++total;
1585         }
1586     }
1587 
1588     if (count)
1589     {
1590         *count = total;
1591     }
1592 }
1593 
flagForDeletion()1594 void Program::flagForDeletion()
1595 {
1596     ASSERT(!mLinkingState);
1597     mDeleteStatus = true;
1598 }
1599 
isFlaggedForDeletion() const1600 bool Program::isFlaggedForDeletion() const
1601 {
1602     ASSERT(!mLinkingState);
1603     return mDeleteStatus;
1604 }
1605 
validate(const Caps & caps)1606 void Program::validate(const Caps &caps)
1607 {
1608     ASSERT(!mLinkingState);
1609     mState.mInfoLog.reset();
1610 
1611     if (mLinked)
1612     {
1613         mValidated = ConvertToBool(mProgram->validate(caps));
1614     }
1615     else
1616     {
1617         mState.mInfoLog << "Program has not been successfully linked.";
1618     }
1619 }
1620 
isValidated() const1621 bool Program::isValidated() const
1622 {
1623     ASSERT(!mLinkingState);
1624     return mValidated;
1625 }
1626 
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)1627 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
1628 {
1629     ASSERT(!mLinkingState);
1630 
1631     mState.mExecutable->remapUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
1632 
1633     mProgram->onUniformBlockBinding(uniformBlockIndex);
1634 
1635     onStateChange(
1636         angle::ProgramUniformBlockBindingUpdatedMessageFromIndex(uniformBlockIndex.value));
1637 }
1638 
setTransformFeedbackVaryings(const Context * context,GLsizei count,const GLchar * const * varyings,GLenum bufferMode)1639 void Program::setTransformFeedbackVaryings(const Context *context,
1640                                            GLsizei count,
1641                                            const GLchar *const *varyings,
1642                                            GLenum bufferMode)
1643 {
1644     ASSERT(!mLinkingState);
1645 
1646     mState.mTransformFeedbackVaryingNames.resize(count);
1647     for (GLsizei i = 0; i < count; i++)
1648     {
1649         mState.mTransformFeedbackVaryingNames[i] = varyings[i];
1650     }
1651 
1652     mState.mTransformFeedbackBufferMode = bufferMode;
1653 }
1654 
linkValidateShaders()1655 bool Program::linkValidateShaders()
1656 {
1657     // Wait for attached shaders to finish compilation.  At this point, they need to be checked
1658     // whether they successfully compiled.  This information is cached so that all compile jobs can
1659     // be waited on and their corresponding objects released before the actual check.
1660     //
1661     // Note that this function is called from the link job, and is therefore not protected by any
1662     // locks.
1663     ShaderBitSet successfullyCompiledShaders;
1664     for (ShaderType shaderType : AllShaderTypes())
1665     {
1666         const SharedCompileJob &compileJob = mState.mShaderCompileJobs[shaderType];
1667         if (compileJob)
1668         {
1669             const bool success = WaitCompileJobUnlocked(compileJob);
1670             successfullyCompiledShaders.set(shaderType, success);
1671         }
1672     }
1673     mState.mShaderCompileJobs = {};
1674 
1675     const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;
1676 
1677     bool isComputeShaderAttached  = shaders[ShaderType::Compute].get() != nullptr;
1678     bool isGraphicsShaderAttached = shaders[ShaderType::Vertex].get() != nullptr ||
1679                                     shaders[ShaderType::TessControl].get() != nullptr ||
1680                                     shaders[ShaderType::TessEvaluation].get() != nullptr ||
1681                                     shaders[ShaderType::Geometry].get() != nullptr ||
1682                                     shaders[ShaderType::Fragment].get() != nullptr;
1683     // Check whether we both have a compute and non-compute shaders attached.
1684     // If there are of both types attached, then linking should fail.
1685     // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
1686     if (isComputeShaderAttached && isGraphicsShaderAttached)
1687     {
1688         mState.mInfoLog << "Both compute and graphics shaders are attached to the same program.";
1689         return false;
1690     }
1691 
1692     Optional<int> version;
1693     for (ShaderType shaderType : kAllGraphicsShaderTypes)
1694     {
1695         const SharedCompiledShaderState &shader = shaders[shaderType];
1696         ASSERT(!shader || shader->shaderType == shaderType);
1697 
1698         if (!shader)
1699         {
1700             continue;
1701         }
1702 
1703         if (!successfullyCompiledShaders.test(shaderType))
1704         {
1705             mState.mInfoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
1706             return false;
1707         }
1708 
1709         if (!version.valid())
1710         {
1711             version = shader->shaderVersion;
1712         }
1713         else if (version != shader->shaderVersion)
1714         {
1715             mState.mInfoLog << ShaderTypeToString(shaderType)
1716                             << " shader version does not match other shader versions.";
1717             return false;
1718         }
1719     }
1720 
1721     if (isComputeShaderAttached)
1722     {
1723         ASSERT(shaders[ShaderType::Compute]->shaderType == ShaderType::Compute);
1724 
1725         // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
1726         // If the work group size is not specified, a link time error should occur.
1727         if (!shaders[ShaderType::Compute]->localSize.isDeclared())
1728         {
1729             mState.mInfoLog << "Work group size is not specified.";
1730             return false;
1731         }
1732     }
1733     else
1734     {
1735         if (!isGraphicsShaderAttached)
1736         {
1737             mState.mInfoLog << "No compiled shaders.";
1738             return false;
1739         }
1740 
1741         bool hasVertex   = shaders[ShaderType::Vertex].get() != nullptr;
1742         bool hasFragment = shaders[ShaderType::Fragment].get() != nullptr;
1743         if (!isSeparable() && (!hasVertex || !hasFragment))
1744         {
1745             mState.mInfoLog
1746                 << "The program must contain objects to form both a vertex and fragment shader.";
1747             return false;
1748         }
1749 
1750         bool hasTessControl    = shaders[ShaderType::TessControl].get() != nullptr;
1751         bool hasTessEvaluation = shaders[ShaderType::TessEvaluation].get() != nullptr;
1752         if (!isSeparable() && (hasTessControl != hasTessEvaluation))
1753         {
1754             mState.mInfoLog
1755                 << "Tessellation control and evaluation shaders must be specified together.";
1756             return false;
1757         }
1758 
1759         const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
1760         if (geometryShader)
1761         {
1762             // [GL_EXT_geometry_shader] Chapter 7
1763             // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
1764             // Language Specification, as well as any of the following reasons:
1765             // * One or more of the shader objects attached to <program> are not compiled
1766             //   successfully.
1767             // * The shaders do not use the same shader language version.
1768             // * <program> contains objects to form a geometry shader, and
1769             //   - <program> is not separable and contains no objects to form a vertex shader; or
1770             //   - the input primitive type, output primitive type, or maximum output vertex count
1771             //     is not specified in the compiled geometry shader object.
1772             if (!geometryShader->hasValidGeometryShaderInputPrimitiveType())
1773             {
1774                 mState.mInfoLog << "Input primitive type is not specified in the geometry shader.";
1775                 return false;
1776             }
1777 
1778             if (!geometryShader->hasValidGeometryShaderOutputPrimitiveType())
1779             {
1780                 mState.mInfoLog << "Output primitive type is not specified in the geometry shader.";
1781                 return false;
1782             }
1783 
1784             if (!geometryShader->hasValidGeometryShaderMaxVertices())
1785             {
1786                 mState.mInfoLog << "'max_vertices' is not specified in the geometry shader.";
1787                 return false;
1788             }
1789         }
1790 
1791         const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
1792         if (tessControlShader)
1793         {
1794             int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
1795             if (tcsShaderVertices == 0)
1796             {
1797                 // In tessellation control shader, output vertices should be specified at least
1798                 // once.
1799                 // > GLSL ES Version 3.20.6 spec:
1800                 // > 4.4.2. Output Layout Qualifiers
1801                 // > Tessellation Control Outputs
1802                 // > ...
1803                 // > There must be at least one layout qualifier specifying an output patch vertex
1804                 // > count in any program containing a tessellation control shader.
1805                 mState.mInfoLog << "In Tessellation Control Shader, at least one layout qualifier "
1806                                    "specifying an output patch vertex count must exist.";
1807                 return false;
1808             }
1809         }
1810 
1811         const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
1812         if (tessEvaluationShader)
1813         {
1814             GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;
1815             if (tesPrimitiveMode == 0)
1816             {
1817                 // In tessellation evaluation shader, a primitive mode should be specified at least
1818                 // once.
1819                 // > GLSL ES Version 3.20.6 spec:
1820                 // > 4.4.1. Input Layout Qualifiers
1821                 // > Tessellation Evaluation Inputs
1822                 // > ...
1823                 // > The tessellation evaluation shader object in a program must declare a primitive
1824                 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
1825                 // > identifiers is optional.
1826                 mState.mInfoLog
1827                     << "The Tessellation Evaluation Shader object in a program must declare a "
1828                        "primitive mode in its input layout.";
1829                 return false;
1830             }
1831         }
1832     }
1833 
1834     return true;
1835 }
1836 
1837 // Assumes linkValidateShaders() has validated the shaders and caches some values from the shaders.
linkShaders()1838 void Program::linkShaders()
1839 {
1840     const ShaderMap<SharedCompiledShaderState> &shaders = mState.mAttachedShaders;
1841 
1842     const bool isComputeShaderAttached = shaders[ShaderType::Compute].get() != nullptr;
1843 
1844     if (isComputeShaderAttached)
1845     {
1846         mState.mExecutable->mPod.computeShaderLocalSize = shaders[ShaderType::Compute]->localSize;
1847     }
1848     else
1849     {
1850         const SharedCompiledShaderState &geometryShader = shaders[ShaderType::Geometry];
1851         if (geometryShader)
1852         {
1853             mState.mExecutable->mPod.geometryShaderInputPrimitiveType =
1854                 geometryShader->geometryShaderInputPrimitiveType;
1855             mState.mExecutable->mPod.geometryShaderOutputPrimitiveType =
1856                 geometryShader->geometryShaderOutputPrimitiveType;
1857             mState.mExecutable->mPod.geometryShaderMaxVertices =
1858                 geometryShader->geometryShaderMaxVertices;
1859             mState.mExecutable->mPod.geometryShaderInvocations =
1860                 geometryShader->geometryShaderInvocations;
1861         }
1862 
1863         const SharedCompiledShaderState &tessControlShader = shaders[ShaderType::TessControl];
1864         if (tessControlShader)
1865         {
1866             int tcsShaderVertices = tessControlShader->tessControlShaderVertices;
1867             mState.mExecutable->mPod.tessControlShaderVertices = tcsShaderVertices;
1868         }
1869 
1870         const SharedCompiledShaderState &tessEvaluationShader = shaders[ShaderType::TessEvaluation];
1871         if (tessEvaluationShader)
1872         {
1873             GLenum tesPrimitiveMode = tessEvaluationShader->tessGenMode;
1874 
1875             mState.mExecutable->mPod.tessGenMode        = tesPrimitiveMode;
1876             mState.mExecutable->mPod.tessGenSpacing     = tessEvaluationShader->tessGenSpacing;
1877             mState.mExecutable->mPod.tessGenVertexOrder = tessEvaluationShader->tessGenVertexOrder;
1878             mState.mExecutable->mPod.tessGenPointMode   = tessEvaluationShader->tessGenPointMode;
1879         }
1880     }
1881 }
1882 
linkVaryings()1883 bool Program::linkVaryings()
1884 {
1885     ShaderType previousShaderType = ShaderType::InvalidEnum;
1886     for (ShaderType shaderType : kAllGraphicsShaderTypes)
1887     {
1888         const SharedCompiledShaderState &currentShader = mState.mAttachedShaders[shaderType];
1889         if (!currentShader)
1890         {
1891             continue;
1892         }
1893 
1894         if (previousShaderType != ShaderType::InvalidEnum)
1895         {
1896             const SharedCompiledShaderState &previousShader =
1897                 mState.mAttachedShaders[previousShaderType];
1898             const std::vector<sh::ShaderVariable> &outputVaryings = previousShader->outputVaryings;
1899 
1900             if (!LinkValidateShaderInterfaceMatching(
1901                     outputVaryings, currentShader->inputVaryings, previousShaderType,
1902                     currentShader->shaderType, previousShader->shaderVersion,
1903                     currentShader->shaderVersion, isSeparable(), mState.mInfoLog))
1904             {
1905                 return false;
1906             }
1907         }
1908         previousShaderType = currentShader->shaderType;
1909     }
1910 
1911     // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
1912     // Need to move logic of validating builtin varyings inside the for-loop above.
1913     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
1914     // can be redeclared in Geometry or Tessellation shaders as well.
1915     const SharedCompiledShaderState &vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
1916     const SharedCompiledShaderState &fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1917     if (vertexShader && fragmentShader &&
1918         !LinkValidateBuiltInVaryings(vertexShader->outputVaryings, fragmentShader->inputVaryings,
1919                                      vertexShader->shaderType, fragmentShader->shaderType,
1920                                      vertexShader->shaderVersion, fragmentShader->shaderVersion,
1921                                      mState.mInfoLog))
1922     {
1923         return false;
1924     }
1925 
1926     return true;
1927 }
1928 
linkUniforms(const Caps & caps,const Version & clientVersion,std::vector<UnusedUniform> * unusedUniformsOutOrNull,GLuint * combinedImageUniformsOut)1929 bool Program::linkUniforms(const Caps &caps,
1930                            const Version &clientVersion,
1931                            std::vector<UnusedUniform> *unusedUniformsOutOrNull,
1932                            GLuint *combinedImageUniformsOut)
1933 {
1934     // Initialize executable shader map.
1935     ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
1936     for (const SharedCompiledShaderState &shader : mState.mAttachedShaders)
1937     {
1938         if (shader)
1939         {
1940             shaderUniforms[shader->shaderType] = shader->uniforms;
1941         }
1942     }
1943 
1944     if (!mState.mExecutable->linkUniforms(caps, shaderUniforms, mState.mUniformLocationBindings,
1945                                           combinedImageUniformsOut, unusedUniformsOutOrNull))
1946     {
1947         return false;
1948     }
1949 
1950     if (clientVersion >= Version(3, 1))
1951     {
1952         GLint locationSize = static_cast<GLint>(mState.mExecutable->getUniformLocations().size());
1953 
1954         if (locationSize > caps.maxUniformLocations)
1955         {
1956             mState.mInfoLog << "Exceeded maximum uniform location size";
1957             return false;
1958         }
1959     }
1960 
1961     return true;
1962 }
1963 
1964 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Caps & caps,const Limitations & limitations,bool webglCompatibility)1965 bool Program::linkAttributes(const Caps &caps,
1966                              const Limitations &limitations,
1967                              bool webglCompatibility)
1968 {
1969     int shaderVersion          = -1;
1970     unsigned int usedLocations = 0;
1971 
1972     const SharedCompiledShaderState &vertexShader = mState.getAttachedShader(ShaderType::Vertex);
1973 
1974     if (!vertexShader)
1975     {
1976         // No vertex shader, so no attributes, so nothing to do
1977         return true;
1978     }
1979 
1980     // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
1981     // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
1982     // aliasing checks.
1983     // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
1984     shaderVersion = vertexShader->shaderVersion;
1985     const std::vector<sh::ShaderVariable> &shaderAttributes =
1986         shaderVersion >= 300 ? vertexShader->allAttributes : vertexShader->activeAttributes;
1987 
1988     ASSERT(mState.mExecutable->mProgramInputs.empty());
1989     mState.mExecutable->mProgramInputs.reserve(shaderAttributes.size());
1990 
1991     GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
1992     std::vector<ProgramInput *> usedAttribMap(maxAttribs, nullptr);
1993 
1994     for (const sh::ShaderVariable &shaderAttribute : shaderAttributes)
1995     {
1996         // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
1997         // structures, so we don't need to worry about adjusting their names or generating entries
1998         // for each member/element (unlike uniforms for example).
1999         ASSERT(!shaderAttribute.isArray() && !shaderAttribute.isStruct());
2000 
2001         mState.mExecutable->mProgramInputs.emplace_back(shaderAttribute);
2002 
2003         // Assign locations to attributes that have a binding location and check for attribute
2004         // aliasing.
2005         ProgramInput &attribute = mState.mExecutable->mProgramInputs.back();
2006         int bindingLocation     = mState.mAttributeBindings.getBinding(attribute);
2007         if (attribute.getLocation() == -1 && bindingLocation != -1)
2008         {
2009             attribute.setLocation(bindingLocation);
2010         }
2011 
2012         if (attribute.getLocation() != -1)
2013         {
2014             // Location is set by glBindAttribLocation or by location layout qualifier
2015             const int regs = VariableRegisterCount(attribute.getType());
2016 
2017             if (static_cast<GLuint>(regs + attribute.getLocation()) > maxAttribs)
2018             {
2019                 mState.mInfoLog << "Attribute (" << attribute.name << ") at location "
2020                                 << attribute.getLocation() << " is too big to fit";
2021 
2022                 return false;
2023             }
2024 
2025             for (int reg = 0; reg < regs; reg++)
2026             {
2027                 const int regLocation         = attribute.getLocation() + reg;
2028                 ProgramInput *linkedAttribute = usedAttribMap[regLocation];
2029 
2030                 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
2031                 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
2032                 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
2033                 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
2034                 if (linkedAttribute)
2035                 {
2036                     if (shaderVersion >= 300 || webglCompatibility ||
2037                         limitations.noVertexAttributeAliasing)
2038                     {
2039                         mState.mInfoLog << "Attribute '" << attribute.name
2040                                         << "' aliases attribute '" << linkedAttribute->name
2041                                         << "' at location " << regLocation;
2042                         return false;
2043                     }
2044                 }
2045                 else
2046                 {
2047                     usedAttribMap[regLocation] = &attribute;
2048                 }
2049 
2050                 usedLocations |= 1 << regLocation;
2051             }
2052         }
2053     }
2054 
2055     // Assign locations to attributes that don't have a binding location.
2056     for (ProgramInput &attribute : mState.mExecutable->mProgramInputs)
2057     {
2058         // Not set by glBindAttribLocation or by location layout qualifier
2059         if (attribute.getLocation() == -1)
2060         {
2061             int regs           = VariableRegisterCount(attribute.getType());
2062             int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
2063 
2064             if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
2065             {
2066                 mState.mInfoLog << "Too many attributes (" << attribute.name << ")";
2067                 return false;
2068             }
2069 
2070             attribute.setLocation(availableIndex);
2071         }
2072     }
2073 
2074     ASSERT(mState.mExecutable->mPod.attributesTypeMask.none());
2075     ASSERT(mState.mExecutable->mPod.attributesMask.none());
2076 
2077     // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
2078     // shader versions we're only processing active attributes to begin with.
2079     if (shaderVersion >= 300)
2080     {
2081         for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
2082              attributeIter != mState.mExecutable->getProgramInputs().end();)
2083         {
2084             if (attributeIter->isActive())
2085             {
2086                 ++attributeIter;
2087             }
2088             else
2089             {
2090                 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
2091             }
2092         }
2093     }
2094 
2095     for (const ProgramInput &attribute : mState.mExecutable->getProgramInputs())
2096     {
2097         ASSERT(attribute.isActive());
2098         ASSERT(attribute.getLocation() != -1);
2099         unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.getType()));
2100 
2101         unsigned int location = static_cast<unsigned int>(attribute.getLocation());
2102         for (unsigned int r = 0; r < regs; r++)
2103         {
2104             // Built-in active program inputs don't have a bound attribute.
2105             if (!attribute.isBuiltIn())
2106             {
2107                 mState.mExecutable->mPod.activeAttribLocationsMask.set(location);
2108                 mState.mExecutable->mPod.maxActiveAttribLocation =
2109                     std::max(mState.mExecutable->mPod.maxActiveAttribLocation, location + 1);
2110 
2111                 ComponentType componentType =
2112                     GLenumToComponentType(VariableComponentType(attribute.getType()));
2113 
2114                 SetComponentTypeMask(componentType, location,
2115                                      &mState.mExecutable->mPod.attributesTypeMask);
2116                 mState.mExecutable->mPod.attributesMask.set(location);
2117 
2118                 location++;
2119             }
2120         }
2121     }
2122 
2123     return true;
2124 }
2125 
serialize(const Context * context)2126 angle::Result Program::serialize(const Context *context)
2127 {
2128     // In typical applications, the binary should already be empty here.  However, in unusual
2129     // situations this may not be true.  In particular, if the application doesn't set
2130     // GL_PROGRAM_BINARY_RETRIEVABLE_HINT, gets the program length but doesn't get the binary, the
2131     // cached binary remains until the program is destroyed or the program is bound (both causing
2132     // |waitForPostLinkTasks()| to cache the program in the blob cache).
2133     if (!mBinary.empty())
2134     {
2135         return angle::Result::Continue;
2136     }
2137 
2138     BinaryOutputStream stream;
2139 
2140     stream.writeBytes(
2141         reinterpret_cast<const unsigned char *>(angle::GetANGLEShaderProgramVersion()),
2142         angle::GetANGLEShaderProgramVersionHashSize());
2143 
2144     stream.writeBool(angle::Is64Bit());
2145 
2146     stream.writeInt(angle::GetANGLESHVersion());
2147 
2148     stream.writeString(context->getRendererString());
2149 
2150     // nullptr context is supported when computing binary length.
2151     if (context)
2152     {
2153         stream.writeInt(context->getClientVersion().major);
2154         stream.writeInt(context->getClientVersion().minor);
2155     }
2156     else
2157     {
2158         stream.writeInt(2);
2159         stream.writeInt(0);
2160     }
2161 
2162     // mSeparable must be before mExecutable->save(), since it uses the value.
2163     stream.writeBool(mState.mSeparable);
2164     stream.writeInt(mState.mTransformFeedbackBufferMode);
2165 
2166     stream.writeInt(mState.mTransformFeedbackVaryingNames.size());
2167     for (const std::string &name : mState.mTransformFeedbackVaryingNames)
2168     {
2169         stream.writeString(name);
2170     }
2171 
2172     mState.mExecutable->save(&stream);
2173 
2174     // Warn the app layer if saving a binary with unsupported transform feedback.
2175     if (!mState.mExecutable->getLinkedTransformFeedbackVaryings().empty() &&
2176         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
2177     {
2178         ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2179                            "Saving program binary with transform feedback, which is not supported "
2180                            "on this driver.");
2181     }
2182 
2183     if (context->getShareGroup()->getFrameCaptureShared()->enabled())
2184     {
2185         // Serialize the source for each stage for re-use during capture
2186         for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
2187         {
2188             Shader *shader = getAttachedShader(shaderType);
2189             if (shader)
2190             {
2191                 stream.writeString(shader->getSourceString());
2192             }
2193             else
2194             {
2195                 // If we don't have an attached shader, which would occur if this program was
2196                 // created via glProgramBinary, pull from our cached copy
2197                 const angle::ProgramSources &cachedLinkedSources =
2198                     context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id());
2199                 const std::string &cachedSourceString = cachedLinkedSources[shaderType];
2200                 ASSERT(!cachedSourceString.empty());
2201                 stream.writeString(cachedSourceString.c_str());
2202             }
2203         }
2204     }
2205 
2206     mProgram->save(context, &stream);
2207     ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());
2208 
2209     if (!mBinary.resize(stream.length()))
2210     {
2211         ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2212                            "Failed to allocate enough memory to serialize a program. (%zu bytes)",
2213                            stream.length());
2214         return angle::Result::Stop;
2215     }
2216     memcpy(mBinary.data(), stream.data(), stream.length());
2217     return angle::Result::Continue;
2218 }
2219 
deserialize(const Context * context,BinaryInputStream & stream)2220 bool Program::deserialize(const Context *context, BinaryInputStream &stream)
2221 {
2222     std::vector<uint8_t> angleShaderProgramVersionString(
2223         angle::GetANGLEShaderProgramVersionHashSize(), 0);
2224     stream.readBytes(angleShaderProgramVersionString.data(),
2225                      angleShaderProgramVersionString.size());
2226     if (memcmp(angleShaderProgramVersionString.data(), angle::GetANGLEShaderProgramVersion(),
2227                angleShaderProgramVersionString.size()) != 0)
2228     {
2229         mState.mInfoLog << "Invalid program binary version.";
2230         return false;
2231     }
2232 
2233     bool binaryIs64Bit = stream.readBool();
2234     if (binaryIs64Bit != angle::Is64Bit())
2235     {
2236         mState.mInfoLog << "cannot load program binaries across CPU architectures.";
2237         return false;
2238     }
2239 
2240     int angleSHVersion = stream.readInt<int>();
2241     if (angleSHVersion != angle::GetANGLESHVersion())
2242     {
2243         mState.mInfoLog << "cannot load program binaries across different angle sh version.";
2244         return false;
2245     }
2246 
2247     std::string rendererString = stream.readString();
2248     if (rendererString != context->getRendererString())
2249     {
2250         mState.mInfoLog << "Cannot load program binary due to changed renderer string.";
2251         return false;
2252     }
2253 
2254     int majorVersion = stream.readInt<int>();
2255     int minorVersion = stream.readInt<int>();
2256     if (majorVersion != context->getClientMajorVersion() ||
2257         minorVersion != context->getClientMinorVersion())
2258     {
2259         mState.mInfoLog << "Cannot load program binaries across different ES context versions.";
2260         return false;
2261     }
2262 
2263     mState.mSeparable                   = stream.readBool();
2264     mState.mTransformFeedbackBufferMode = stream.readInt<GLenum>();
2265 
2266     mState.mTransformFeedbackVaryingNames.resize(stream.readInt<size_t>());
2267     for (std::string &name : mState.mTransformFeedbackVaryingNames)
2268     {
2269         name = stream.readString();
2270     }
2271 
2272     // mSeparable must be before mExecutable->load(), since it uses the value.  This state is
2273     // duplicated in the executable for convenience.
2274     mState.mExecutable->mPod.isSeparable = mState.mSeparable;
2275     mState.mExecutable->load(&stream);
2276 
2277     static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
2278                   "Too many shader types");
2279 
2280     // Reject programs that use transform feedback varyings if the hardware cannot support them.
2281     if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
2282         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
2283     {
2284         mState.mInfoLog << "Current driver does not support transform feedback in binary programs.";
2285         return false;
2286     }
2287 
2288     if (!mState.mAttachedShaders[ShaderType::Compute])
2289     {
2290         mState.mExecutable->updateTransformFeedbackStrides();
2291         mState.mExecutable->mTransformFeedbackVaryingNames = mState.mTransformFeedbackVaryingNames;
2292     }
2293 
2294     if (context->getShareGroup()->getFrameCaptureShared()->enabled())
2295     {
2296         // Extract the source for each stage from the program binary
2297         angle::ProgramSources sources;
2298 
2299         for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
2300         {
2301             std::string shaderSource = stream.readString();
2302             ASSERT(shaderSource.length() > 0);
2303             sources[shaderType] = std::move(shaderSource);
2304         }
2305 
2306         // Store it for use during mid-execution capture
2307         context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(),
2308                                                                              std::move(sources));
2309     }
2310 
2311     return true;
2312 }
2313 
postResolveLink(const Context * context)2314 void Program::postResolveLink(const Context *context)
2315 {
2316     mState.updateActiveSamplers();
2317     mState.mExecutable->mActiveImageShaderBits.fill({});
2318     mState.mExecutable->updateActiveImages(getExecutable());
2319 
2320     mState.mExecutable->initInterfaceBlockBindings();
2321     mState.mExecutable->setUniformValuesFromBindingQualifiers();
2322 
2323     if (context->getExtensions().multiDrawANGLE)
2324     {
2325         mState.mExecutable->mPod.drawIDLocation =
2326             mState.mExecutable->getUniformLocation("gl_DrawID").value;
2327     }
2328 
2329     if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE)
2330     {
2331         mState.mExecutable->mPod.baseVertexLocation =
2332             mState.mExecutable->getUniformLocation("gl_BaseVertex").value;
2333         mState.mExecutable->mPod.baseInstanceLocation =
2334             mState.mExecutable->getUniformLocation("gl_BaseInstance").value;
2335     }
2336 }
2337 
cacheProgramBinaryIfNotAlready(const Context * context)2338 void Program::cacheProgramBinaryIfNotAlready(const Context *context)
2339 {
2340     // If program caching is disabled, we already consider the binary cached.
2341     ASSERT(!context->getFrontendFeatures().disableProgramCaching.enabled || mIsBinaryCached);
2342     if (!mLinked || mIsBinaryCached || mState.mBinaryRetrieveableHint)
2343     {
2344         // Program caching is disabled, the program is yet to be linked, it's already cached, or the
2345         // application has specified that it prefers to cache the program binary itself.
2346         return;
2347     }
2348 
2349     // No post-link tasks should be pending.
2350     ASSERT(mState.mExecutable->mPostLinkSubTasks.empty());
2351 
2352     // Save to the program cache.
2353     std::lock_guard<angle::SimpleMutex> cacheLock(context->getProgramCacheMutex());
2354     MemoryProgramCache *cache = context->getMemoryProgramCache();
2355     // TODO: http://anglebug.com/4530: Enable program caching for separable programs
2356     if (cache && !isSeparable() &&
2357         (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
2358          !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
2359     {
2360         if (cache->putProgram(mProgramHash, context, this) == angle::Result::Stop)
2361         {
2362             // Don't fail linking if putting the program binary into the cache fails, the program is
2363             // still usable.
2364             ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
2365                                "Failed to save linked program to memory program cache.");
2366         }
2367 
2368         // Drop the binary; the application didn't specify that it wants to retrieve the binary.  If
2369         // it did, we wouldn't be implicitly caching it.
2370         mBinary.clear();
2371     }
2372 
2373     mIsBinaryCached = true;
2374 }
2375 
dumpProgramInfo(const Context * context) const2376 void Program::dumpProgramInfo(const Context *context) const
2377 {
2378     std::stringstream dumpStream;
2379     for (ShaderType shaderType : angle::AllEnums<ShaderType>())
2380     {
2381         Shader *shader = getAttachedShader(shaderType);
2382         if (shader)
2383         {
2384             dumpStream << shader->getType() << ": "
2385                        << GetShaderDumpFileName(shader->getSourceHash()) << std::endl;
2386         }
2387     }
2388 
2389     std::string dump = dumpStream.str();
2390     size_t dumpHash  = std::hash<std::string>{}(dump);
2391 
2392     std::stringstream pathStream;
2393     std::string shaderDumpDir = GetShaderDumpFileDirectory();
2394     if (!shaderDumpDir.empty())
2395     {
2396         pathStream << shaderDumpDir << "/";
2397     }
2398     pathStream << dumpHash << ".program";
2399     std::string path = pathStream.str();
2400 
2401     writeFile(path.c_str(), dump.c_str(), dump.length());
2402     INFO() << "Dumped program: " << path;
2403 }
2404 }  // namespace gl
2405