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