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