• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Program.cpp: Implements the gl::Program class. Implements GL program objects
8 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9 
10 #include "libANGLE/Program.h"
11 
12 #include <algorithm>
13 #include <utility>
14 
15 #include "common/angle_version_info.h"
16 #include "common/bitset_utils.h"
17 #include "common/debug.h"
18 #include "common/platform.h"
19 #include "common/string_utils.h"
20 #include "common/utilities.h"
21 #include "compiler/translator/blocklayout.h"
22 #include "libANGLE/Context.h"
23 #include "libANGLE/ErrorStrings.h"
24 #include "libANGLE/MemoryProgramCache.h"
25 #include "libANGLE/ProgramLinkedResources.h"
26 #include "libANGLE/ResourceManager.h"
27 #include "libANGLE/Uniform.h"
28 #include "libANGLE/VaryingPacking.h"
29 #include "libANGLE/Version.h"
30 #include "libANGLE/capture/FrameCapture.h"
31 #include "libANGLE/features.h"
32 #include "libANGLE/histogram_macros.h"
33 #include "libANGLE/queryconversions.h"
34 #include "libANGLE/renderer/GLImplFactory.h"
35 #include "libANGLE/renderer/ProgramImpl.h"
36 #include "platform/FrontendFeatures.h"
37 #include "platform/PlatformMethods.h"
38 
39 namespace gl
40 {
41 
42 namespace
43 {
44 
45 // This simplified cast function doesn't need to worry about advanced concepts like
46 // depth range values, or casting to bool.
47 template <typename DestT, typename SrcT>
48 DestT UniformStateQueryCast(SrcT value);
49 
50 // From-Float-To-Integer Casts
51 template <>
UniformStateQueryCast(GLfloat value)52 GLint UniformStateQueryCast(GLfloat value)
53 {
54     return clampCast<GLint>(roundf(value));
55 }
56 
57 template <>
UniformStateQueryCast(GLfloat value)58 GLuint UniformStateQueryCast(GLfloat value)
59 {
60     return clampCast<GLuint>(roundf(value));
61 }
62 
63 // From-Integer-to-Integer Casts
64 template <>
UniformStateQueryCast(GLuint value)65 GLint UniformStateQueryCast(GLuint value)
66 {
67     return clampCast<GLint>(value);
68 }
69 
70 template <>
UniformStateQueryCast(GLint value)71 GLuint UniformStateQueryCast(GLint value)
72 {
73     return clampCast<GLuint>(value);
74 }
75 
76 // From-Boolean-to-Anything Casts
77 template <>
UniformStateQueryCast(GLboolean value)78 GLfloat UniformStateQueryCast(GLboolean value)
79 {
80     return (ConvertToBool(value) ? 1.0f : 0.0f);
81 }
82 
83 template <>
UniformStateQueryCast(GLboolean value)84 GLint UniformStateQueryCast(GLboolean value)
85 {
86     return (ConvertToBool(value) ? 1 : 0);
87 }
88 
89 template <>
UniformStateQueryCast(GLboolean value)90 GLuint UniformStateQueryCast(GLboolean value)
91 {
92     return (ConvertToBool(value) ? 1u : 0u);
93 }
94 
95 // Default to static_cast
96 template <typename DestT, typename SrcT>
UniformStateQueryCast(SrcT value)97 DestT UniformStateQueryCast(SrcT value)
98 {
99     return static_cast<DestT>(value);
100 }
101 
102 template <typename SrcT, typename DestT>
UniformStateQueryCastLoop(DestT * dataOut,const uint8_t * srcPointer,int components)103 void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
104 {
105     for (int comp = 0; comp < components; ++comp)
106     {
107         // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
108         // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
109         size_t offset               = comp * 4;
110         const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
111         dataOut[comp]               = UniformStateQueryCast<DestT>(*typedSrcPointer);
112     }
113 }
114 
115 template <typename VarT>
GetResourceIndexFromName(const std::vector<VarT> & list,const std::string & name)116 GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
117 {
118     std::string nameAsArrayName = name + "[0]";
119     for (size_t index = 0; index < list.size(); index++)
120     {
121         const VarT &resource = list[index];
122         if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
123         {
124             return static_cast<GLuint>(index);
125         }
126     }
127 
128     return GL_INVALID_INDEX;
129 }
130 
GetVariableLocation(const std::vector<sh::ShaderVariable> & list,const std::vector<VariableLocation> & locationList,const std::string & name)131 GLint GetVariableLocation(const std::vector<sh::ShaderVariable> &list,
132                           const std::vector<VariableLocation> &locationList,
133                           const std::string &name)
134 {
135     size_t nameLengthWithoutArrayIndex;
136     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
137 
138     for (size_t location = 0u; location < locationList.size(); ++location)
139     {
140         const VariableLocation &variableLocation = locationList[location];
141         if (!variableLocation.used())
142         {
143             continue;
144         }
145 
146         const sh::ShaderVariable &variable = list[variableLocation.index];
147 
148         // Array output variables may be bound out of order, so we need to ensure we only pick the
149         // first element if given the base name.
150         if ((variable.name == name) && (variableLocation.arrayIndex == 0))
151         {
152             return static_cast<GLint>(location);
153         }
154         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
155             angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
156         {
157             return static_cast<GLint>(location);
158         }
159     }
160 
161     return -1;
162 }
163 
GetVariableLocation(const std::vector<LinkedUniform> & list,const std::vector<VariableLocation> & locationList,const std::string & name)164 GLint GetVariableLocation(const std::vector<LinkedUniform> &list,
165                           const std::vector<VariableLocation> &locationList,
166                           const std::string &name)
167 {
168     size_t nameLengthWithoutArrayIndex;
169     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
170 
171     for (size_t location = 0u; location < locationList.size(); ++location)
172     {
173         const VariableLocation &variableLocation = locationList[location];
174         if (!variableLocation.used())
175         {
176             continue;
177         }
178 
179         const LinkedUniform &variable = list[variableLocation.index];
180 
181         // Array output variables may be bound out of order, so we need to ensure we only pick the
182         // first element if given the base name. Uniforms don't allow this behavior and some code
183         // seemingly depends on the opposite behavior, so only enable it for output variables.
184         if (angle::BeginsWith(variable.name, name) && (variableLocation.arrayIndex == 0))
185         {
186             if (name.length() == variable.name.length())
187             {
188                 ASSERT(name == variable.name);
189                 // GLES 3.1 November 2016 page 87.
190                 // The string exactly matches the name of the active variable.
191                 return static_cast<GLint>(location);
192             }
193             if (name.length() + 3u == variable.name.length() && variable.isArray())
194             {
195                 ASSERT(name + "[0]" == variable.name);
196                 // The string identifies the base name of an active array, where the string would
197                 // exactly match the name of the variable if the suffix "[0]" were appended to the
198                 // string.
199                 return static_cast<GLint>(location);
200             }
201         }
202         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
203             nameLengthWithoutArrayIndex + 3u == variable.name.length() &&
204             angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
205         {
206             ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name);
207             // The string identifies an active element of the array, where the string ends with the
208             // concatenation of the "[" character, an integer (with no "+" sign, extra leading
209             // zeroes, or whitespace) identifying an array element, and the "]" character, the
210             // integer is less than the number of active elements of the array variable, and where
211             // the string would exactly match the enumerated name of the array if the decimal
212             // integer were replaced with zero.
213             return static_cast<GLint>(location);
214         }
215     }
216 
217     return -1;
218 }
219 
CopyStringToBuffer(GLchar * buffer,const std::string & string,GLsizei bufSize,GLsizei * lengthOut)220 void CopyStringToBuffer(GLchar *buffer,
221                         const std::string &string,
222                         GLsizei bufSize,
223                         GLsizei *lengthOut)
224 {
225     ASSERT(bufSize > 0);
226     size_t length = std::min<size_t>(bufSize - 1, string.length());
227     memcpy(buffer, string.c_str(), length);
228     buffer[length] = '\0';
229 
230     if (lengthOut)
231     {
232         *lengthOut = static_cast<GLsizei>(length);
233     }
234 }
235 
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)236 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
237 {
238     std::vector<unsigned int> subscripts;
239     std::string baseName = ParseResourceName(name, &subscripts);
240 
241     unsigned int numBlocks = static_cast<unsigned int>(list.size());
242     for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
243     {
244         const auto &block = list[blockIndex];
245         if (block.name == baseName)
246         {
247             const bool arrayElementZero =
248                 (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
249             const bool arrayElementMatches =
250                 (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
251             if (arrayElementMatches || arrayElementZero)
252             {
253                 return blockIndex;
254             }
255         }
256     }
257 
258     return GL_INVALID_INDEX;
259 }
260 
GetInterfaceBlockName(const UniformBlockIndex index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)261 void GetInterfaceBlockName(const UniformBlockIndex index,
262                            const std::vector<InterfaceBlock> &list,
263                            GLsizei bufSize,
264                            GLsizei *length,
265                            GLchar *name)
266 {
267     ASSERT(index.value < list.size());
268 
269     const auto &block = list[index.value];
270 
271     if (bufSize > 0)
272     {
273         std::string blockName = block.name;
274 
275         if (block.isArray)
276         {
277             blockName += ArrayString(block.arrayElement);
278         }
279         CopyStringToBuffer(name, blockName, bufSize, length);
280     }
281 }
282 
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)283 void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
284 {
285     for (ShaderType shaderType : AllShaderTypes())
286     {
287         Shader *shader = state.getAttachedShader(shaderType);
288         if (shader)
289         {
290             blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks());
291         }
292     }
293 }
294 
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)295 void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
296 {
297     for (ShaderType shaderType : AllShaderTypes())
298     {
299         Shader *shader = state.getAttachedShader(shaderType);
300         if (shader != nullptr)
301         {
302             blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks());
303         }
304     }
305 }
306 }  // anonymous namespace
307 
GetLinkMismatchErrorString(LinkMismatchError linkError)308 const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
309 {
310     switch (linkError)
311     {
312         case LinkMismatchError::TYPE_MISMATCH:
313             return "Type";
314         case LinkMismatchError::ARRAYNESS_MISMATCH:
315             return "Array-ness";
316         case LinkMismatchError::ARRAY_SIZE_MISMATCH:
317             return "Array size";
318         case LinkMismatchError::PRECISION_MISMATCH:
319             return "Precision";
320         case LinkMismatchError::STRUCT_NAME_MISMATCH:
321             return "Structure name";
322         case LinkMismatchError::FIELD_NUMBER_MISMATCH:
323             return "Field number";
324         case LinkMismatchError::FIELD_NAME_MISMATCH:
325             return "Field name";
326 
327         case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
328             return "Interpolation type";
329         case LinkMismatchError::INVARIANCE_MISMATCH:
330             return "Invariance";
331 
332         case LinkMismatchError::BINDING_MISMATCH:
333             return "Binding layout qualifier";
334         case LinkMismatchError::LOCATION_MISMATCH:
335             return "Location layout qualifier";
336         case LinkMismatchError::OFFSET_MISMATCH:
337             return "Offset layout qualifier";
338         case LinkMismatchError::INSTANCE_NAME_MISMATCH:
339             return "Instance name qualifier";
340         case LinkMismatchError::FORMAT_MISMATCH:
341             return "Format qualifier";
342 
343         case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
344             return "Layout qualifier";
345         case LinkMismatchError::MATRIX_PACKING_MISMATCH:
346             return "Matrix Packing";
347 
348         case LinkMismatchError::FIELD_LOCATION_MISMATCH:
349             return "Field location";
350         case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
351             return "Field structure name";
352         default:
353             UNREACHABLE();
354             return "";
355     }
356 }
357 
UpdateInterfaceVariable(std::vector<sh::ShaderVariable> * block,const sh::ShaderVariable & var)358 void UpdateInterfaceVariable(std::vector<sh::ShaderVariable> *block, const sh::ShaderVariable &var)
359 {
360     if (!var.isStruct())
361     {
362         block->emplace_back(var);
363         block->back().resetEffectiveLocation();
364     }
365 
366     for (const sh::ShaderVariable &field : var.fields)
367     {
368         ASSERT(!var.name.empty() || var.isShaderIOBlock);
369 
370         // Shader I/O block naming is similar to UBOs and SSBOs:
371         //
372         //     in Block
373         //     {
374         //         type field;  // produces "field"
375         //     };
376         //
377         //     in Block2
378         //     {
379         //         type field;  // produces "Block2.field"
380         //     } block2;
381         //
382         const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
383         const std::string prefix    = var.name.empty() ? "" : baseName + ".";
384 
385         if (!field.isStruct())
386         {
387             sh::ShaderVariable fieldCopy = field;
388             fieldCopy.updateEffectiveLocation(var);
389             fieldCopy.name = prefix + field.name;
390             block->emplace_back(fieldCopy);
391         }
392 
393         for (const sh::ShaderVariable &nested : field.fields)
394         {
395             sh::ShaderVariable nestedCopy = nested;
396             nestedCopy.updateEffectiveLocation(field);
397             nestedCopy.name = prefix + field.name + "." + nested.name;
398             block->emplace_back(nestedCopy);
399         }
400     }
401 }
402 
WriteShaderVariableBuffer(BinaryOutputStream * stream,const ShaderVariableBuffer & var)403 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
404 {
405     stream->writeInt(var.binding);
406     stream->writeInt(var.dataSize);
407 
408     for (ShaderType shaderType : AllShaderTypes())
409     {
410         stream->writeBool(var.isActive(shaderType));
411     }
412 
413     stream->writeInt(var.memberIndexes.size());
414     for (unsigned int memberCounterIndex : var.memberIndexes)
415     {
416         stream->writeInt(memberCounterIndex);
417     }
418 }
419 
LoadShaderVariableBuffer(BinaryInputStream * stream,ShaderVariableBuffer * var)420 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
421 {
422     var->binding  = stream->readInt<int>();
423     var->dataSize = stream->readInt<unsigned int>();
424 
425     for (ShaderType shaderType : AllShaderTypes())
426     {
427         var->setActive(shaderType, stream->readBool());
428     }
429 
430     size_t numMembers = stream->readInt<size_t>();
431     for (size_t blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
432     {
433         var->memberIndexes.push_back(stream->readInt<unsigned int>());
434     }
435 }
436 
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)437 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
438 {
439     WriteShaderVar(stream, var);
440 
441     stream->writeInt(var.bufferIndex);
442     WriteBlockMemberInfo(stream, var.blockInfo);
443     stream->writeInt(var.topLevelArraySize);
444 
445     for (ShaderType shaderType : AllShaderTypes())
446     {
447         stream->writeBool(var.isActive(shaderType));
448     }
449 }
450 
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)451 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
452 {
453     LoadShaderVar(stream, var);
454 
455     var->bufferIndex = stream->readInt<int>();
456     LoadBlockMemberInfo(stream, &var->blockInfo);
457     var->topLevelArraySize = stream->readInt<int>();
458 
459     for (ShaderType shaderType : AllShaderTypes())
460     {
461         var->setActive(shaderType, stream->readBool());
462     }
463 }
464 
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)465 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
466 {
467     stream->writeString(block.name);
468     stream->writeString(block.mappedName);
469     stream->writeBool(block.isArray);
470     stream->writeInt(block.arrayElement);
471 
472     WriteShaderVariableBuffer(stream, block);
473 }
474 
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)475 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
476 {
477     block->name         = stream->readString();
478     block->mappedName   = stream->readString();
479     block->isArray      = stream->readBool();
480     block->arrayElement = stream->readInt<unsigned int>();
481 
482     LoadShaderVariableBuffer(stream, block);
483 }
484 
WriteShInterfaceBlock(BinaryOutputStream * stream,const sh::InterfaceBlock & block)485 void WriteShInterfaceBlock(BinaryOutputStream *stream, const sh::InterfaceBlock &block)
486 {
487     stream->writeString(block.name);
488     stream->writeString(block.mappedName);
489     stream->writeString(block.instanceName);
490     stream->writeInt(block.arraySize);
491     stream->writeEnum(block.layout);
492     stream->writeBool(block.isRowMajorLayout);
493     stream->writeInt(block.binding);
494     stream->writeBool(block.staticUse);
495     stream->writeBool(block.active);
496     stream->writeEnum(block.blockType);
497 
498     stream->writeInt<size_t>(block.fields.size());
499     for (const sh::ShaderVariable &shaderVariable : block.fields)
500     {
501         WriteShaderVar(stream, shaderVariable);
502     }
503 }
504 
LoadShInterfaceBlock(BinaryInputStream * stream,sh::InterfaceBlock * block)505 void LoadShInterfaceBlock(BinaryInputStream *stream, sh::InterfaceBlock *block)
506 {
507     block->name             = stream->readString();
508     block->mappedName       = stream->readString();
509     block->instanceName     = stream->readString();
510     block->arraySize        = stream->readInt<unsigned int>();
511     block->layout           = stream->readEnum<sh::BlockLayoutType>();
512     block->isRowMajorLayout = stream->readBool();
513     block->binding          = stream->readInt<int>();
514     block->staticUse        = stream->readBool();
515     block->active           = stream->readBool();
516     block->blockType        = stream->readEnum<sh::BlockType>();
517 
518     block->fields.resize(stream->readInt<size_t>());
519     for (sh::ShaderVariable &variable : block->fields)
520     {
521         LoadShaderVar(stream, &variable);
522     }
523 }
524 
525 // Saves the linking context for later use in resolveLink().
526 struct Program::LinkingState
527 {
528     std::shared_ptr<ProgramExecutable> linkedExecutable;
529     ProgramLinkedResources resources;
530     egl::BlobCache::Key programHash;
531     std::unique_ptr<rx::LinkEvent> linkEvent;
532     bool linkingFromBinary;
533 };
534 
535 const char *const g_fakepath = "C:\\fakepath";
536 
537 // InfoLog implementation.
InfoLog()538 InfoLog::InfoLog() : mLazyStream(nullptr) {}
539 
~InfoLog()540 InfoLog::~InfoLog() {}
541 
getLength() const542 size_t InfoLog::getLength() const
543 {
544     if (!mLazyStream)
545     {
546         return 0;
547     }
548 
549     const std::string &logString = mLazyStream->str();
550     return logString.empty() ? 0 : logString.length() + 1;
551 }
552 
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const553 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
554 {
555     size_t index = 0;
556 
557     if (bufSize > 0)
558     {
559         const std::string logString(str());
560 
561         if (!logString.empty())
562         {
563             index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
564             memcpy(infoLog, logString.c_str(), index);
565         }
566 
567         infoLog[index] = '\0';
568     }
569 
570     if (length)
571     {
572         *length = static_cast<GLsizei>(index);
573     }
574 }
575 
576 // append a santized message to the program info log.
577 // The D3D compiler includes a fake file path in some of the warning or error
578 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)579 void InfoLog::appendSanitized(const char *message)
580 {
581     ensureInitialized();
582 
583     std::string msg(message);
584 
585     size_t found;
586     do
587     {
588         found = msg.find(g_fakepath);
589         if (found != std::string::npos)
590         {
591             msg.erase(found, strlen(g_fakepath));
592         }
593     } while (found != std::string::npos);
594 
595     if (!msg.empty())
596     {
597         *mLazyStream << message << std::endl;
598     }
599 }
600 
reset()601 void InfoLog::reset()
602 {
603     if (mLazyStream)
604     {
605         mLazyStream.reset(nullptr);
606     }
607 }
608 
empty() const609 bool InfoLog::empty() const
610 {
611     if (!mLazyStream)
612     {
613         return true;
614     }
615 
616     return mLazyStream->rdbuf()->in_avail() == 0;
617 }
618 
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)619 void LogLinkMismatch(InfoLog &infoLog,
620                      const std::string &variableName,
621                      const char *variableType,
622                      LinkMismatchError linkError,
623                      const std::string &mismatchedStructOrBlockFieldName,
624                      ShaderType shaderType1,
625                      ShaderType shaderType2)
626 {
627     std::ostringstream stream;
628     stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
629            << variableName;
630 
631     if (!mismatchedStructOrBlockFieldName.empty())
632     {
633         stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
634     }
635 
636     stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
637            << GetShaderTypeString(shaderType2) << " shaders.";
638 
639     infoLog << stream.str();
640 }
641 
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)642 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
643 {
644     // Only 'packed' blocks are allowed to be considered inactive.
645     return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
646 }
647 
WriteBlockMemberInfo(BinaryOutputStream * stream,const sh::BlockMemberInfo & var)648 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var)
649 {
650     stream->writeInt(var.arrayStride);
651     stream->writeBool(var.isRowMajorMatrix);
652     stream->writeInt(var.matrixStride);
653     stream->writeInt(var.offset);
654     stream->writeInt(var.topLevelArrayStride);
655 }
656 
LoadBlockMemberInfo(BinaryInputStream * stream,sh::BlockMemberInfo * var)657 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
658 {
659     var->arrayStride         = stream->readInt<int>();
660     var->isRowMajorMatrix    = stream->readBool();
661     var->matrixStride        = stream->readInt<int>();
662     var->offset              = stream->readInt<int>();
663     var->topLevelArrayStride = stream->readInt<int>();
664 }
665 
WriteShaderVar(BinaryOutputStream * stream,const sh::ShaderVariable & var)666 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
667 {
668     stream->writeInt(var.type);
669     stream->writeInt(var.precision);
670     stream->writeString(var.name);
671     stream->writeString(var.mappedName);
672     stream->writeIntVector(var.arraySizes);
673     stream->writeBool(var.staticUse);
674     stream->writeBool(var.active);
675     stream->writeInt<size_t>(var.fields.size());
676     for (const sh::ShaderVariable &shaderVariable : var.fields)
677     {
678         WriteShaderVar(stream, shaderVariable);
679     }
680     stream->writeString(var.structOrBlockName);
681     stream->writeString(var.mappedStructOrBlockName);
682     stream->writeBool(var.isRowMajorLayout);
683     stream->writeInt(var.location);
684     stream->writeBool(var.hasImplicitLocation);
685     stream->writeInt(var.binding);
686     stream->writeInt(var.imageUnitFormat);
687     stream->writeInt(var.offset);
688     stream->writeBool(var.readonly);
689     stream->writeBool(var.writeonly);
690     stream->writeBool(var.isFragmentInOut);
691     stream->writeInt(var.index);
692     stream->writeBool(var.yuv);
693     stream->writeEnum(var.interpolation);
694     stream->writeBool(var.isInvariant);
695     stream->writeBool(var.isShaderIOBlock);
696     stream->writeBool(var.isPatch);
697     stream->writeBool(var.texelFetchStaticUse);
698     stream->writeInt(var.getFlattenedOffsetInParentArrays());
699 }
700 
LoadShaderVar(gl::BinaryInputStream * stream,sh::ShaderVariable * var)701 void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
702 {
703     var->type      = stream->readInt<GLenum>();
704     var->precision = stream->readInt<GLenum>();
705     stream->readString(&var->name);
706     stream->readString(&var->mappedName);
707     stream->readIntVector<unsigned int>(&var->arraySizes);
708     var->staticUse      = stream->readBool();
709     var->active         = stream->readBool();
710     size_t elementCount = stream->readInt<size_t>();
711     var->fields.resize(elementCount);
712     for (sh::ShaderVariable &variable : var->fields)
713     {
714         LoadShaderVar(stream, &variable);
715     }
716     stream->readString(&var->structOrBlockName);
717     stream->readString(&var->mappedStructOrBlockName);
718     var->isRowMajorLayout    = stream->readBool();
719     var->location            = stream->readInt<int>();
720     var->hasImplicitLocation = stream->readBool();
721     var->binding             = stream->readInt<int>();
722     var->imageUnitFormat     = stream->readInt<GLenum>();
723     var->offset              = stream->readInt<int>();
724     var->readonly            = stream->readBool();
725     var->writeonly           = stream->readBool();
726     var->isFragmentInOut     = stream->readBool();
727     var->index               = stream->readInt<int>();
728     var->yuv                 = stream->readBool();
729     var->interpolation       = stream->readEnum<sh::InterpolationType>();
730     var->isInvariant         = stream->readBool();
731     var->isShaderIOBlock     = stream->readBool();
732     var->isPatch             = stream->readBool();
733     var->texelFetchStaticUse = stream->readBool();
734     var->setParentArrayIndex(stream->readInt<int>());
735 }
736 
737 // VariableLocation implementation.
VariableLocation()738 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
739 
VariableLocation(unsigned int arrayIndex,unsigned int index)740 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
741     : arrayIndex(arrayIndex), index(index), ignored(false)
742 {
743     ASSERT(arrayIndex != GL_INVALID_INDEX);
744 }
745 
746 // SamplerBindings implementation.
SamplerBinding(TextureType textureTypeIn,GLenum samplerTypeIn,SamplerFormat formatIn,size_t elementCount)747 SamplerBinding::SamplerBinding(TextureType textureTypeIn,
748                                GLenum samplerTypeIn,
749                                SamplerFormat formatIn,
750                                size_t elementCount)
751     : textureType(textureTypeIn),
752       samplerType(samplerTypeIn),
753       format(formatIn),
754       boundTextureUnits(elementCount, 0)
755 {}
756 
757 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
758 
759 SamplerBinding::~SamplerBinding() = default;
760 
761 // ProgramBindings implementation.
ProgramBindings()762 ProgramBindings::ProgramBindings() {}
763 
~ProgramBindings()764 ProgramBindings::~ProgramBindings() {}
765 
bindLocation(GLuint index,const std::string & name)766 void ProgramBindings::bindLocation(GLuint index, const std::string &name)
767 {
768     mBindings[name] = index;
769 }
770 
getBindingByName(const std::string & name) const771 int ProgramBindings::getBindingByName(const std::string &name) const
772 {
773     auto iter = mBindings.find(name);
774     return (iter != mBindings.end()) ? iter->second : -1;
775 }
776 
getBinding(const sh::ShaderVariable & variable) const777 int ProgramBindings::getBinding(const sh::ShaderVariable &variable) const
778 {
779     return getBindingByName(variable.name);
780 }
781 
begin() const782 ProgramBindings::const_iterator ProgramBindings::begin() const
783 {
784     return mBindings.begin();
785 }
786 
end() const787 ProgramBindings::const_iterator ProgramBindings::end() const
788 {
789     return mBindings.end();
790 }
791 
getStableIterationMap() const792 std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
793 {
794     return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
795 }
796 
797 // ProgramAliasedBindings implementation.
ProgramAliasedBindings()798 ProgramAliasedBindings::ProgramAliasedBindings() {}
799 
~ProgramAliasedBindings()800 ProgramAliasedBindings::~ProgramAliasedBindings() {}
801 
bindLocation(GLuint index,const std::string & name)802 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
803 {
804     mBindings[name] = ProgramBinding(index);
805 
806     // EXT_blend_func_extended spec: "If it specifies the base name of an array,
807     // it identifies the resources associated with the first element of the array."
808     //
809     // Normalize array bindings so that "name" and "name[0]" map to the same entry.
810     // If this binding is of the form "name[0]", then mark the "name" binding as
811     // aliased but do not update it yet in case "name" is not actually an array.
812     size_t nameLengthWithoutArrayIndex;
813     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
814     if (arrayIndex == 0)
815     {
816         std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
817         auto iter            = mBindings.find(baseName);
818         if (iter != mBindings.end())
819         {
820             iter->second.aliased = true;
821         }
822     }
823 }
824 
getBindingByName(const std::string & name) const825 int ProgramAliasedBindings::getBindingByName(const std::string &name) const
826 {
827     auto iter = mBindings.find(name);
828     return (iter != mBindings.end()) ? iter->second.location : -1;
829 }
830 
getBindingByLocation(GLuint location) const831 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
832 {
833     for (const auto &iter : mBindings)
834     {
835         if (iter.second.location == location)
836         {
837             return iter.second.location;
838         }
839     }
840     return -1;
841 }
842 
getBinding(const sh::ShaderVariable & variable) const843 int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const
844 {
845     const std::string &name = variable.name;
846 
847     // Check with the normalized array name if applicable.
848     if (variable.isArray())
849     {
850         size_t nameLengthWithoutArrayIndex;
851         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
852         if (arrayIndex == 0)
853         {
854             std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
855             auto iter            = mBindings.find(baseName);
856             // If "name" exists and is not aliased, that means it was modified more
857             // recently than its "name[0]" form and should be used instead of that.
858             if (iter != mBindings.end() && !iter->second.aliased)
859             {
860                 return iter->second.location;
861             }
862         }
863         else if (arrayIndex == GL_INVALID_INDEX)
864         {
865             auto iter = mBindings.find(variable.name);
866             // If "name" exists and is not aliased, that means it was modified more
867             // recently than its "name[0]" form and should be used instead of that.
868             if (iter != mBindings.end() && !iter->second.aliased)
869             {
870                 return iter->second.location;
871             }
872             // The base name was aliased, so use the name with the array notation.
873             return getBindingByName(name + "[0]");
874         }
875     }
876 
877     return getBindingByName(name);
878 }
879 
begin() const880 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
881 {
882     return mBindings.begin();
883 }
884 
end() const885 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
886 {
887     return mBindings.end();
888 }
889 
getStableIterationMap() const890 std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
891 {
892     return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
893 }
894 
895 // ImageBinding implementation.
ImageBinding(size_t count,TextureType textureTypeIn)896 ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn)
897     : textureType(textureTypeIn), boundImageUnits(count, 0)
898 {}
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)899 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
900     : textureType(textureTypeIn)
901 {
902     for (size_t index = 0; index < count; ++index)
903     {
904         boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
905     }
906 }
907 
908 ImageBinding::ImageBinding(const ImageBinding &other) = default;
909 
910 ImageBinding::~ImageBinding() = default;
911 
912 // ProgramState implementation.
ProgramState()913 ProgramState::ProgramState()
914     : mLabel(),
915       mAttachedShaders{},
916       mLocationsUsedForXfbExtension(0),
917       mBinaryRetrieveableHint(false),
918       mSeparable(false),
919       mNumViews(-1),
920       mDrawIDLocation(-1),
921       mBaseVertexLocation(-1),
922       mBaseInstanceLocation(-1),
923       mCachedBaseVertex(0),
924       mCachedBaseInstance(0),
925       mExecutable(new ProgramExecutable())
926 {
927     mComputeShaderLocalSize.fill(1);
928 }
929 
~ProgramState()930 ProgramState::~ProgramState()
931 {
932     ASSERT(!hasAttachedShader());
933 }
934 
getLabel()935 const std::string &ProgramState::getLabel()
936 {
937     return mLabel;
938 }
939 
getAttachedShader(ShaderType shaderType) const940 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
941 {
942     ASSERT(shaderType != ShaderType::InvalidEnum);
943     return mAttachedShaders[shaderType];
944 }
945 
getUniformIndexFromName(const std::string & name) const946 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
947 {
948     return GetResourceIndexFromName(mExecutable->mUniforms, name);
949 }
950 
getBufferVariableIndexFromName(const std::string & name) const951 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
952 {
953     return GetResourceIndexFromName(mBufferVariables, name);
954 }
955 
getUniformIndexFromLocation(UniformLocation location) const956 GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const
957 {
958     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
959     return mUniformLocations[location.value].index;
960 }
961 
getSamplerIndex(UniformLocation location) const962 Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
963 {
964     GLuint index = getUniformIndexFromLocation(location);
965     if (!isSamplerUniformIndex(index))
966     {
967         return Optional<GLuint>::Invalid();
968     }
969 
970     return getSamplerIndexFromUniformIndex(index);
971 }
972 
isSamplerUniformIndex(GLuint index) const973 bool ProgramState::isSamplerUniformIndex(GLuint index) const
974 {
975     return mExecutable->mSamplerUniformRange.contains(index);
976 }
977 
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const978 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
979 {
980     ASSERT(isSamplerUniformIndex(uniformIndex));
981     return uniformIndex - mExecutable->mSamplerUniformRange.low();
982 }
983 
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const984 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
985 {
986     return mExecutable->getUniformIndexFromSamplerIndex(samplerIndex);
987 }
988 
isImageUniformIndex(GLuint index) const989 bool ProgramState::isImageUniformIndex(GLuint index) const
990 {
991     return mExecutable->mImageUniformRange.contains(index);
992 }
993 
getImageIndexFromUniformIndex(GLuint uniformIndex) const994 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
995 {
996     ASSERT(isImageUniformIndex(uniformIndex));
997     return uniformIndex - mExecutable->mImageUniformRange.low();
998 }
999 
getAttributeLocation(const std::string & name) const1000 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1001 {
1002     for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
1003     {
1004         if (attribute.name == name)
1005         {
1006             return attribute.location;
1007         }
1008     }
1009 
1010     return static_cast<GLuint>(-1);
1011 }
1012 
hasAttachedShader() const1013 bool ProgramState::hasAttachedShader() const
1014 {
1015     for (const Shader *shader : mAttachedShaders)
1016     {
1017         if (shader)
1018         {
1019             return true;
1020         }
1021     }
1022     return false;
1023 }
1024 
getFirstAttachedShaderStageType() const1025 ShaderType ProgramState::getFirstAttachedShaderStageType() const
1026 {
1027     const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1028     if (linkedStages.none())
1029     {
1030         return ShaderType::InvalidEnum;
1031     }
1032 
1033     return linkedStages.first();
1034 }
1035 
getLastAttachedShaderStageType() const1036 ShaderType ProgramState::getLastAttachedShaderStageType() const
1037 {
1038     const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1039     if (linkedStages.none())
1040     {
1041         return ShaderType::InvalidEnum;
1042     }
1043 
1044     return linkedStages.last();
1045 }
1046 
getAttachedTransformFeedbackStage() const1047 ShaderType ProgramState::getAttachedTransformFeedbackStage() const
1048 {
1049     if (mAttachedShaders[ShaderType::Geometry])
1050     {
1051         return ShaderType::Geometry;
1052     }
1053     if (mAttachedShaders[ShaderType::TessEvaluation])
1054     {
1055         return ShaderType::TessEvaluation;
1056     }
1057     return ShaderType::Vertex;
1058 }
1059 
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)1060 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
1061     : mSerial(factory->generateSerial()),
1062       mProgram(factory->createProgram(mState)),
1063       mValidated(false),
1064       mLinked(false),
1065       mDeleteStatus(false),
1066       mRefCount(0),
1067       mResourceManager(manager),
1068       mHandle(handle)
1069 {
1070     ASSERT(mProgram);
1071 
1072     unlink();
1073 }
1074 
~Program()1075 Program::~Program()
1076 {
1077     ASSERT(!mProgram);
1078 }
1079 
onDestroy(const Context * context)1080 void Program::onDestroy(const Context *context)
1081 {
1082     resolveLink(context);
1083     for (ShaderType shaderType : AllShaderTypes())
1084     {
1085         if (mState.mAttachedShaders[shaderType])
1086         {
1087             mState.mAttachedShaders[shaderType]->release(context);
1088             mState.mAttachedShaders[shaderType] = nullptr;
1089         }
1090     }
1091 
1092     mProgram->destroy(context);
1093 
1094     ASSERT(!mState.hasAttachedShader());
1095     SafeDelete(mProgram);
1096 
1097     delete this;
1098 }
id() const1099 ShaderProgramID Program::id() const
1100 {
1101     ASSERT(!mLinkingState);
1102     return mHandle;
1103 }
1104 
setLabel(const Context * context,const std::string & label)1105 void Program::setLabel(const Context *context, const std::string &label)
1106 {
1107     ASSERT(!mLinkingState);
1108     mState.mLabel = label;
1109 }
1110 
getLabel() const1111 const std::string &Program::getLabel() const
1112 {
1113     ASSERT(!mLinkingState);
1114     return mState.mLabel;
1115 }
1116 
attachShader(Shader * shader)1117 void Program::attachShader(Shader *shader)
1118 {
1119     ShaderType shaderType = shader->getType();
1120     ASSERT(shaderType != ShaderType::InvalidEnum);
1121 
1122     mState.mAttachedShaders[shaderType] = shader;
1123     mState.mAttachedShaders[shaderType]->addRef();
1124 }
1125 
detachShader(const Context * context,Shader * shader)1126 void Program::detachShader(const Context *context, Shader *shader)
1127 {
1128     resolveLink(context);
1129     ShaderType shaderType = shader->getType();
1130     ASSERT(shaderType != ShaderType::InvalidEnum);
1131 
1132     ASSERT(mState.mAttachedShaders[shaderType] == shader);
1133     shader->release(context);
1134     mState.mAttachedShaders[shaderType] = nullptr;
1135 }
1136 
getAttachedShadersCount() const1137 int Program::getAttachedShadersCount() const
1138 {
1139     ASSERT(!mLinkingState);
1140     int numAttachedShaders = 0;
1141     for (const Shader *shader : mState.mAttachedShaders)
1142     {
1143         if (shader)
1144         {
1145             ++numAttachedShaders;
1146         }
1147     }
1148 
1149     return numAttachedShaders;
1150 }
1151 
getAttachedShader(ShaderType shaderType) const1152 Shader *Program::getAttachedShader(ShaderType shaderType) const
1153 {
1154     ASSERT(!mLinkingState);
1155     return mState.getAttachedShader(shaderType);
1156 }
1157 
bindAttributeLocation(GLuint index,const char * name)1158 void Program::bindAttributeLocation(GLuint index, const char *name)
1159 {
1160     ASSERT(!mLinkingState);
1161     mAttributeBindings.bindLocation(index, name);
1162 }
1163 
bindUniformLocation(UniformLocation location,const char * name)1164 void Program::bindUniformLocation(UniformLocation location, const char *name)
1165 {
1166     ASSERT(!mLinkingState);
1167     mState.mUniformLocationBindings.bindLocation(location.value, name);
1168 }
1169 
bindFragmentOutputLocation(GLuint index,const char * name)1170 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1171 {
1172     mFragmentOutputLocations.bindLocation(index, name);
1173 }
1174 
bindFragmentOutputIndex(GLuint index,const char * name)1175 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1176 {
1177     mFragmentOutputIndexes.bindLocation(index, name);
1178 }
1179 
link(const Context * context)1180 angle::Result Program::link(const Context *context)
1181 {
1182     angle::Result result = linkImpl(context);
1183 
1184     // Avoid having two ProgramExecutables if the link failed and the Program had successfully
1185     // linked previously.
1186     if (mLinkingState && mLinkingState->linkedExecutable)
1187     {
1188         mState.mExecutable = mLinkingState->linkedExecutable;
1189     }
1190 
1191     return result;
1192 }
1193 
1194 // The attached shaders are checked for linking errors by matching up their variables.
1195 // Uniform, input and output variables get collected.
1196 // The code gets compiled into binaries.
linkImpl(const Context * context)1197 angle::Result Program::linkImpl(const Context *context)
1198 {
1199     ASSERT(!mLinkingState);
1200     // Don't make any local variables pointing to anything within the ProgramExecutable, since
1201     // unlink() could make a new ProgramExecutable making any references/pointers invalid.
1202     auto *platform   = ANGLEPlatformCurrent();
1203     double startTime = platform->currentTime(platform);
1204 
1205     // Unlink the program, but do not clear the validation-related caching yet, since we can still
1206     // use the previously linked program if linking the shaders fails.
1207     mLinked = false;
1208 
1209     mState.mExecutable->getInfoLog().reset();
1210 
1211     // Validate we have properly attached shaders before checking the cache.
1212     if (!linkValidateShaders(mState.mExecutable->getInfoLog()))
1213     {
1214         return angle::Result::Continue;
1215     }
1216 
1217     egl::BlobCache::Key programHash = {0};
1218     MemoryProgramCache *cache       = context->getMemoryProgramCache();
1219 
1220     // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1221     if (cache && !isSeparable())
1222     {
1223         std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1224         angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1225         ANGLE_TRY(cacheResult);
1226 
1227         // Check explicitly for Continue, Incomplete means a cache miss
1228         if (cacheResult == angle::Result::Continue)
1229         {
1230             // Succeeded in loading the binaries in the front-end, back end may still be loading
1231             // asynchronously
1232             double delta = platform->currentTime(platform) - startTime;
1233             int us       = static_cast<int>(delta * 1000000.0);
1234             ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1235             return angle::Result::Continue;
1236         }
1237     }
1238 
1239     // Cache load failed, fall through to normal linking.
1240     unlink();
1241     InfoLog &infoLog = mState.mExecutable->getInfoLog();
1242 
1243     // Re-link shaders after the unlink call.
1244     bool result = linkValidateShaders(infoLog);
1245     ASSERT(result);
1246 
1247     std::unique_ptr<LinkingState> linkingState(new LinkingState());
1248     ProgramMergedVaryings mergedVaryings;
1249     LinkingVariables linkingVariables(mState);
1250     ProgramLinkedResources &resources = linkingState->resources;
1251 
1252     resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1253                    &mState.mExecutable->mShaderStorageBlocks, &mState.mBufferVariables,
1254                    &mState.mExecutable->mAtomicCounterBuffers);
1255 
1256     // TODO: Fix incomplete linking. http://anglebug.com/6358
1257     updateLinkedShaderStages();
1258 
1259     InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1260     InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1261 
1262     if (mState.mAttachedShaders[ShaderType::Compute])
1263     {
1264         GLuint combinedImageUniforms = 0;
1265         if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog))
1266         {
1267             return angle::Result::Continue;
1268         }
1269 
1270         GLuint combinedShaderStorageBlocks = 0u;
1271         if (!LinkValidateProgramInterfaceBlocks(context,
1272                                                 mState.mExecutable->getLinkedShaderStages(),
1273                                                 resources, infoLog, &combinedShaderStorageBlocks))
1274         {
1275             return angle::Result::Continue;
1276         }
1277 
1278         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1279         // A link error will be generated if the sum of the number of active image uniforms used in
1280         // all shaders, the number of active shader storage blocks, and the number of active
1281         // fragment shader outputs exceeds the implementation-dependent value of
1282         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1283         if (combinedImageUniforms + combinedShaderStorageBlocks >
1284             static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
1285         {
1286             infoLog
1287                 << "The sum of the number of active image uniforms, active shader storage blocks "
1288                    "and active fragment shader outputs exceeds "
1289                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1290                 << context->getCaps().maxCombinedShaderOutputResources << ")";
1291             return angle::Result::Continue;
1292         }
1293     }
1294     else
1295     {
1296         if (!linkAttributes(context, infoLog))
1297         {
1298             return angle::Result::Continue;
1299         }
1300 
1301         if (!linkVaryings(infoLog))
1302         {
1303             return angle::Result::Continue;
1304         }
1305 
1306         GLuint combinedImageUniforms = 0;
1307         if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog))
1308         {
1309             return angle::Result::Continue;
1310         }
1311 
1312         GLuint combinedShaderStorageBlocks = 0u;
1313         if (!LinkValidateProgramInterfaceBlocks(context,
1314                                                 mState.mExecutable->getLinkedShaderStages(),
1315                                                 resources, infoLog, &combinedShaderStorageBlocks))
1316         {
1317             return angle::Result::Continue;
1318         }
1319 
1320         if (!LinkValidateProgramGlobalNames(infoLog, getExecutable(), linkingVariables))
1321         {
1322             return angle::Result::Continue;
1323         }
1324 
1325         gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1326         if (vertexShader)
1327         {
1328             mState.mNumViews = vertexShader->getNumViews();
1329             mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
1330         }
1331 
1332         gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1333         if (fragmentShader)
1334         {
1335             if (!mState.mExecutable->linkValidateOutputVariables(
1336                     context->getCaps(), context->getExtensions(), context->getClientVersion(),
1337                     combinedImageUniforms, combinedShaderStorageBlocks,
1338                     fragmentShader->getActiveOutputVariables(), fragmentShader->getShaderVersion(),
1339                     mFragmentOutputLocations, mFragmentOutputIndexes))
1340             {
1341                 return angle::Result::Continue;
1342             }
1343 
1344             mState.mExecutable->mUsesEarlyFragmentTestsOptimization =
1345                 fragmentShader->hasEarlyFragmentTestsOptimization();
1346             mState.mExecutable->mAdvancedBlendEquations =
1347                 fragmentShader->getAdvancedBlendEquations();
1348             mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
1349         }
1350 
1351         mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
1352         if (!mState.mExecutable->linkMergedVaryings(
1353                 context, mergedVaryings, mState.mTransformFeedbackVaryingNames, linkingVariables,
1354                 isSeparable(), &resources.varyingPacking))
1355         {
1356             return angle::Result::Continue;
1357         }
1358     }
1359 
1360     mState.mExecutable->saveLinkedStateInfo(mState);
1361 
1362     mLinkingState                    = std::move(linkingState);
1363     mLinkingState->linkingFromBinary = false;
1364     mLinkingState->programHash       = programHash;
1365     mLinkingState->linkEvent         = mProgram->link(context, resources, infoLog, mergedVaryings);
1366 
1367     // Must be after mProgram->link() to avoid misleading the linker about output variables.
1368     mState.updateProgramInterfaceInputs();
1369     mState.updateProgramInterfaceOutputs();
1370 
1371     if (mState.mSeparable)
1372     {
1373         mLinkingState->linkedExecutable = mState.mExecutable;
1374     }
1375 
1376     return angle::Result::Continue;
1377 }
1378 
isLinking() const1379 bool Program::isLinking() const
1380 {
1381     return (mLinkingState.get() && mLinkingState->linkEvent &&
1382             mLinkingState->linkEvent->isLinking());
1383 }
1384 
resolveLinkImpl(const Context * context)1385 void Program::resolveLinkImpl(const Context *context)
1386 {
1387     ASSERT(mLinkingState.get());
1388 
1389     angle::Result result = mLinkingState->linkEvent->wait(context);
1390 
1391     mLinked                                    = result == angle::Result::Continue;
1392     std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1393     if (!mLinked)
1394     {
1395         return;
1396     }
1397 
1398     if (linkingState->linkingFromBinary)
1399     {
1400         // All internal Program state is already loaded from the binary.
1401         return;
1402     }
1403 
1404     initInterfaceBlockBindings();
1405 
1406     // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1407     // Only successfully linked program can replace the executables.
1408     ASSERT(mLinked);
1409 
1410     // Mark implementation-specific unreferenced uniforms as ignored.
1411     std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1412     mProgram->markUnusedUniformLocations(&mState.mUniformLocations,
1413                                          &mState.mExecutable->mSamplerBindings, imageBindings);
1414 
1415     // Must be called after markUnusedUniformLocations.
1416     postResolveLink(context);
1417 
1418     // Save to the program cache.
1419     std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1420     MemoryProgramCache *cache = context->getMemoryProgramCache();
1421     // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1422     if (cache && !isSeparable() &&
1423         (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
1424          !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
1425     {
1426         if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
1427         {
1428             // Don't fail linking if putting the program binary into the cache fails, the program is
1429             // still usable.
1430             WARN() << "Failed to save linked program to memory program cache.";
1431         }
1432     }
1433 }
1434 
updateLinkedShaderStages()1435 void Program::updateLinkedShaderStages()
1436 {
1437     mState.mExecutable->resetLinkedShaderStages();
1438 
1439     for (const Shader *shader : mState.mAttachedShaders)
1440     {
1441         if (shader)
1442         {
1443             mState.mExecutable->setLinkedShaderStages(shader->getType());
1444         }
1445     }
1446 }
1447 
updateActiveSamplers()1448 void ProgramState::updateActiveSamplers()
1449 {
1450     mExecutable->mActiveSamplerRefCounts.fill(0);
1451     mExecutable->updateActiveSamplers(*this);
1452 }
1453 
updateProgramInterfaceInputs()1454 void ProgramState::updateProgramInterfaceInputs()
1455 {
1456     const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType();
1457 
1458     if (firstAttachedShaderType == ShaderType::Vertex)
1459     {
1460         // Vertex attributes are already what we need, so nothing to do
1461         return;
1462     }
1463 
1464     Shader *shader = getAttachedShader(firstAttachedShaderType);
1465     ASSERT(shader);
1466 
1467     // Copy over each input varying, since the Shader could go away
1468     if (shader->getType() == ShaderType::Compute)
1469     {
1470         for (const sh::ShaderVariable &attribute : shader->getAllAttributes())
1471         {
1472             // Compute Shaders have the following built-in input variables.
1473             //
1474             // in uvec3 gl_NumWorkGroups;
1475             // in uvec3 gl_WorkGroupID;
1476             // in uvec3 gl_LocalInvocationID;
1477             // in uvec3 gl_GlobalInvocationID;
1478             // in uint  gl_LocalInvocationIndex;
1479             // They are all vecs or uints, so no special handling is required.
1480             mExecutable->mProgramInputs.emplace_back(attribute);
1481         }
1482     }
1483     else
1484     {
1485         for (const sh::ShaderVariable &varying : shader->getInputVaryings())
1486         {
1487             UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1488         }
1489     }
1490 }
1491 
updateProgramInterfaceOutputs()1492 void ProgramState::updateProgramInterfaceOutputs()
1493 {
1494     const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType();
1495 
1496     if (lastAttachedShaderType == ShaderType::Fragment)
1497     {
1498         // Fragment outputs are already what we need, so nothing to do
1499         return;
1500     }
1501     if (lastAttachedShaderType == ShaderType::Compute)
1502     {
1503         // If the program only contains a Compute Shader, then there are no user-defined outputs.
1504         return;
1505     }
1506 
1507     Shader *shader = getAttachedShader(lastAttachedShaderType);
1508     ASSERT(shader);
1509 
1510     // Copy over each output varying, since the Shader could go away
1511     for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
1512     {
1513         UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1514     }
1515 }
1516 
1517 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1518 void Program::unlink()
1519 {
1520     if (mLinkingState && mLinkingState->linkedExecutable)
1521     {
1522         // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of
1523         // the last successfully linked ProgramExecutable, so we don't lose any state information.
1524         mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable));
1525     }
1526     mState.mExecutable->reset();
1527 
1528     mState.mUniformLocations.clear();
1529     mState.mBufferVariables.clear();
1530     mState.mComputeShaderLocalSize.fill(1);
1531     mState.mNumViews             = -1;
1532     mState.mDrawIDLocation       = -1;
1533     mState.mBaseVertexLocation   = -1;
1534     mState.mBaseInstanceLocation = -1;
1535     mState.mCachedBaseVertex     = 0;
1536     mState.mCachedBaseInstance   = 0;
1537     mState.mSpecConstUsageBits.reset();
1538 
1539     mValidated = false;
1540 
1541     mLinked = false;
1542 }
1543 
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1544 angle::Result Program::loadBinary(const Context *context,
1545                                   GLenum binaryFormat,
1546                                   const void *binary,
1547                                   GLsizei length)
1548 {
1549     ASSERT(!mLinkingState);
1550     unlink();
1551     InfoLog &infoLog = mState.mExecutable->getInfoLog();
1552 
1553 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1554     return angle::Result::Continue;
1555 #else
1556     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1557     if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1558     {
1559         infoLog << "Invalid program binary format.";
1560         return angle::Result::Continue;
1561     }
1562 
1563     BinaryInputStream stream(binary, length);
1564     ANGLE_TRY(deserialize(context, stream, infoLog));
1565     // Currently we require the full shader text to compute the program hash.
1566     // We could also store the binary in the internal program cache.
1567 
1568     for (size_t uniformBlockIndex = 0;
1569          uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
1570     {
1571         mDirtyBits.set(uniformBlockIndex);
1572     }
1573 
1574     // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple
1575     // implementations. In some implementations, a background thread is used to compile the
1576     // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with
1577     // the operation.
1578 
1579     // We do not want to call LinkEvent::wait because that will cause the background thread
1580     // to finish its task before returning, thus defeating the purpose of background compilation.
1581     // We need to defer waiting on background compilation until the very last minute when we
1582     // absolutely need the results, such as when the developer binds the program or queries
1583     // for the completion status.
1584 
1585     // If load returns nullptr, we know for sure that the binary is not compatible with the backend.
1586     // The loaded binary could have been read from the on-disk shader cache and be corrupted or
1587     // serialized with different revision and subsystem id than the currently loaded backend.
1588     // Returning 'Incomplete' to the caller results in link happening using the original shader
1589     // sources.
1590     angle::Result result;
1591     std::unique_ptr<LinkingState> linkingState;
1592     std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog);
1593     if (linkEvent)
1594     {
1595         linkingState                    = std::make_unique<LinkingState>();
1596         linkingState->linkingFromBinary = true;
1597         linkingState->linkEvent         = std::move(linkEvent);
1598         result                          = angle::Result::Continue;
1599     }
1600     else
1601     {
1602         result = angle::Result::Incomplete;
1603     }
1604     mLinkingState = std::move(linkingState);
1605 
1606     return result;
1607 #endif  // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1608 }
1609 
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1610 angle::Result Program::saveBinary(Context *context,
1611                                   GLenum *binaryFormat,
1612                                   void *binary,
1613                                   GLsizei bufSize,
1614                                   GLsizei *length) const
1615 {
1616     ASSERT(!mLinkingState);
1617     if (binaryFormat)
1618     {
1619         *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1620     }
1621 
1622     angle::MemoryBuffer memoryBuf;
1623     ANGLE_TRY(serialize(context, &memoryBuf));
1624 
1625     GLsizei streamLength       = static_cast<GLsizei>(memoryBuf.size());
1626     const uint8_t *streamState = memoryBuf.data();
1627 
1628     if (streamLength > bufSize)
1629     {
1630         if (length)
1631         {
1632             *length = 0;
1633         }
1634 
1635         // TODO: This should be moved to the validation layer but computing the size of the binary
1636         // before saving it causes the save to happen twice.  It may be possible to write the binary
1637         // to a separate buffer, validate sizes and then copy it.
1638         ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1639     }
1640 
1641     if (binary)
1642     {
1643         char *ptr = reinterpret_cast<char *>(binary);
1644 
1645         memcpy(ptr, streamState, streamLength);
1646         ptr += streamLength;
1647 
1648         ASSERT(ptr - streamLength == binary);
1649     }
1650 
1651     if (length)
1652     {
1653         *length = streamLength;
1654     }
1655 
1656     return angle::Result::Continue;
1657 }
1658 
getBinaryLength(Context * context) const1659 GLint Program::getBinaryLength(Context *context) const
1660 {
1661     ASSERT(!mLinkingState);
1662     if (!mLinked)
1663     {
1664         return 0;
1665     }
1666 
1667     GLint length;
1668     angle::Result result =
1669         saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1670     if (result != angle::Result::Continue)
1671     {
1672         return 0;
1673     }
1674 
1675     return length;
1676 }
1677 
setBinaryRetrievableHint(bool retrievable)1678 void Program::setBinaryRetrievableHint(bool retrievable)
1679 {
1680     ASSERT(!mLinkingState);
1681     // TODO(jmadill) : replace with dirty bits
1682     mProgram->setBinaryRetrievableHint(retrievable);
1683     mState.mBinaryRetrieveableHint = retrievable;
1684 }
1685 
getBinaryRetrievableHint() const1686 bool Program::getBinaryRetrievableHint() const
1687 {
1688     ASSERT(!mLinkingState);
1689     return mState.mBinaryRetrieveableHint;
1690 }
1691 
setSeparable(bool separable)1692 void Program::setSeparable(bool separable)
1693 {
1694     ASSERT(!mLinkingState);
1695     // TODO(yunchao) : replace with dirty bits
1696     if (mState.mSeparable != separable)
1697     {
1698         mProgram->setSeparable(separable);
1699         mState.mSeparable = separable;
1700     }
1701 }
1702 
isSeparable() const1703 bool Program::isSeparable() const
1704 {
1705     ASSERT(!mLinkingState);
1706     return mState.mSeparable;
1707 }
1708 
deleteSelf(const Context * context)1709 void Program::deleteSelf(const Context *context)
1710 {
1711     ASSERT(mRefCount == 0 && mDeleteStatus);
1712     mResourceManager->deleteProgram(context, mHandle);
1713 }
1714 
getRefCount() const1715 unsigned int Program::getRefCount() const
1716 {
1717     return mRefCount;
1718 }
1719 
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const1720 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
1721 {
1722     ASSERT(!mLinkingState);
1723     int total = 0;
1724 
1725     for (const Shader *shader : mState.mAttachedShaders)
1726     {
1727         if (shader && (total < maxCount))
1728         {
1729             shaders[total] = shader->getHandle();
1730             ++total;
1731         }
1732     }
1733 
1734     if (count)
1735     {
1736         *count = total;
1737     }
1738 }
1739 
getAttributeLocation(const std::string & name) const1740 GLuint Program::getAttributeLocation(const std::string &name) const
1741 {
1742     ASSERT(!mLinkingState);
1743     return mState.getAttributeLocation(name);
1744 }
1745 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const1746 void Program::getActiveAttribute(GLuint index,
1747                                  GLsizei bufsize,
1748                                  GLsizei *length,
1749                                  GLint *size,
1750                                  GLenum *type,
1751                                  GLchar *name) const
1752 {
1753     ASSERT(!mLinkingState);
1754     if (!mLinked)
1755     {
1756         if (bufsize > 0)
1757         {
1758             name[0] = '\0';
1759         }
1760 
1761         if (length)
1762         {
1763             *length = 0;
1764         }
1765 
1766         *type = GL_NONE;
1767         *size = 1;
1768         return;
1769     }
1770 
1771     ASSERT(index < mState.mExecutable->getProgramInputs().size());
1772     const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
1773 
1774     if (bufsize > 0)
1775     {
1776         CopyStringToBuffer(name, attrib.name, bufsize, length);
1777     }
1778 
1779     // Always a single 'type' instance
1780     *size = 1;
1781     *type = attrib.type;
1782 }
1783 
getActiveAttributeCount() const1784 GLint Program::getActiveAttributeCount() const
1785 {
1786     ASSERT(!mLinkingState);
1787     if (!mLinked)
1788     {
1789         return 0;
1790     }
1791 
1792     return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
1793 }
1794 
getActiveAttributeMaxLength() const1795 GLint Program::getActiveAttributeMaxLength() const
1796 {
1797     ASSERT(!mLinkingState);
1798     if (!mLinked)
1799     {
1800         return 0;
1801     }
1802 
1803     size_t maxLength = 0;
1804 
1805     for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
1806     {
1807         maxLength = std::max(attrib.name.length() + 1, maxLength);
1808     }
1809 
1810     return static_cast<GLint>(maxLength);
1811 }
1812 
getAttributes() const1813 const std::vector<sh::ShaderVariable> &Program::getAttributes() const
1814 {
1815     ASSERT(!mLinkingState);
1816     return mState.mExecutable->getProgramInputs();
1817 }
1818 
getComputeShaderLocalSize() const1819 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
1820 {
1821     ASSERT(!mLinkingState);
1822     return mState.mComputeShaderLocalSize;
1823 }
1824 
getGeometryShaderInputPrimitiveType() const1825 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
1826 {
1827     ASSERT(!mLinkingState && mState.mExecutable);
1828     return mState.mExecutable->getGeometryShaderInputPrimitiveType();
1829 }
getGeometryShaderOutputPrimitiveType() const1830 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
1831 {
1832     ASSERT(!mLinkingState && mState.mExecutable);
1833     return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
1834 }
getGeometryShaderInvocations() const1835 GLint Program::getGeometryShaderInvocations() const
1836 {
1837     ASSERT(!mLinkingState && mState.mExecutable);
1838     return mState.mExecutable->getGeometryShaderInvocations();
1839 }
getGeometryShaderMaxVertices() const1840 GLint Program::getGeometryShaderMaxVertices() const
1841 {
1842     ASSERT(!mLinkingState && mState.mExecutable);
1843     return mState.mExecutable->getGeometryShaderMaxVertices();
1844 }
1845 
getTessControlShaderVertices() const1846 GLint Program::getTessControlShaderVertices() const
1847 {
1848     ASSERT(!mLinkingState && mState.mExecutable);
1849     return mState.mExecutable->mTessControlShaderVertices;
1850 }
1851 
getTessGenMode() const1852 GLenum Program::getTessGenMode() const
1853 {
1854     ASSERT(!mLinkingState && mState.mExecutable);
1855     return mState.mExecutable->mTessGenMode;
1856 }
1857 
getTessGenPointMode() const1858 GLenum Program::getTessGenPointMode() const
1859 {
1860     ASSERT(!mLinkingState && mState.mExecutable);
1861     return mState.mExecutable->mTessGenPointMode;
1862 }
1863 
getTessGenSpacing() const1864 GLenum Program::getTessGenSpacing() const
1865 {
1866     ASSERT(!mLinkingState && mState.mExecutable);
1867     return mState.mExecutable->mTessGenSpacing;
1868 }
1869 
getTessGenVertexOrder() const1870 GLenum Program::getTessGenVertexOrder() const
1871 {
1872     ASSERT(!mLinkingState && mState.mExecutable);
1873     return mState.mExecutable->mTessGenVertexOrder;
1874 }
1875 
getInputResource(size_t index) const1876 const sh::ShaderVariable &Program::getInputResource(size_t index) const
1877 {
1878     ASSERT(!mLinkingState);
1879     ASSERT(index < mState.mExecutable->getProgramInputs().size());
1880     return mState.mExecutable->getProgramInputs()[index];
1881 }
1882 
getInputResourceIndex(const GLchar * name) const1883 GLuint Program::getInputResourceIndex(const GLchar *name) const
1884 {
1885     ASSERT(!mLinkingState);
1886     const std::string nameString = StripLastArrayIndex(name);
1887 
1888     for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
1889     {
1890         sh::ShaderVariable resource = getInputResource(index);
1891         if (resource.name == nameString)
1892         {
1893             return static_cast<GLuint>(index);
1894         }
1895     }
1896 
1897     return GL_INVALID_INDEX;
1898 }
1899 
getResourceMaxNameSize(const sh::ShaderVariable & resource,GLint max) const1900 GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
1901 {
1902     if (resource.isArray())
1903     {
1904         return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
1905     }
1906     else
1907     {
1908         return std::max(max, clampCast<GLint>((resource.name).size()));
1909     }
1910 }
1911 
getInputResourceMaxNameSize() const1912 GLuint Program::getInputResourceMaxNameSize() const
1913 {
1914     GLint max = 0;
1915 
1916     for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
1917     {
1918         max = getResourceMaxNameSize(resource, max);
1919     }
1920 
1921     return max;
1922 }
1923 
getOutputResourceMaxNameSize() const1924 GLuint Program::getOutputResourceMaxNameSize() const
1925 {
1926     GLint max = 0;
1927 
1928     for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
1929     {
1930         max = getResourceMaxNameSize(resource, max);
1931     }
1932 
1933     return max;
1934 }
1935 
getResourceLocation(const GLchar * name,const sh::ShaderVariable & variable) const1936 GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
1937 {
1938     if (variable.isBuiltIn())
1939     {
1940         return GL_INVALID_INDEX;
1941     }
1942 
1943     GLint location = variable.location;
1944     if (variable.isArray())
1945     {
1946         size_t nameLengthWithoutArrayIndexOut;
1947         size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
1948         // The 'name' string may not contain the array notation "[0]"
1949         if (arrayIndex != GL_INVALID_INDEX)
1950         {
1951             location += arrayIndex;
1952         }
1953     }
1954 
1955     return location;
1956 }
1957 
getInputResourceLocation(const GLchar * name) const1958 GLuint Program::getInputResourceLocation(const GLchar *name) const
1959 {
1960     const GLuint index = getInputResourceIndex(name);
1961     if (index == GL_INVALID_INDEX)
1962     {
1963         return index;
1964     }
1965 
1966     const sh::ShaderVariable &variable = getInputResource(index);
1967 
1968     return getResourceLocation(name, variable);
1969 }
1970 
getOutputResourceLocation(const GLchar * name) const1971 GLuint Program::getOutputResourceLocation(const GLchar *name) const
1972 {
1973     const GLuint index = getOutputResourceIndex(name);
1974     if (index == GL_INVALID_INDEX)
1975     {
1976         return index;
1977     }
1978 
1979     const sh::ShaderVariable &variable = getOutputResource(index);
1980 
1981     return getResourceLocation(name, variable);
1982 }
1983 
getOutputResourceIndex(const GLchar * name) const1984 GLuint Program::getOutputResourceIndex(const GLchar *name) const
1985 {
1986     ASSERT(!mLinkingState);
1987     const std::string nameString = StripLastArrayIndex(name);
1988 
1989     for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
1990     {
1991         sh::ShaderVariable resource = getOutputResource(index);
1992         if (resource.name == nameString)
1993         {
1994             return static_cast<GLuint>(index);
1995         }
1996     }
1997 
1998     return GL_INVALID_INDEX;
1999 }
2000 
getOutputResourceCount() const2001 size_t Program::getOutputResourceCount() const
2002 {
2003     ASSERT(!mLinkingState);
2004     return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
2005 }
2006 
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2007 void Program::getResourceName(const std::string name,
2008                               GLsizei bufSize,
2009                               GLsizei *length,
2010                               GLchar *dest) const
2011 {
2012     if (length)
2013     {
2014         *length = 0;
2015     }
2016 
2017     if (!mLinked)
2018     {
2019         if (bufSize > 0)
2020         {
2021             dest[0] = '\0';
2022         }
2023         return;
2024     }
2025 
2026     if (bufSize > 0)
2027     {
2028         CopyStringToBuffer(dest, name, bufSize, length);
2029     }
2030 }
2031 
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2032 void Program::getInputResourceName(GLuint index,
2033                                    GLsizei bufSize,
2034                                    GLsizei *length,
2035                                    GLchar *name) const
2036 {
2037     ASSERT(!mLinkingState);
2038     getResourceName(getInputResourceName(index), bufSize, length, name);
2039 }
2040 
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2041 void Program::getOutputResourceName(GLuint index,
2042                                     GLsizei bufSize,
2043                                     GLsizei *length,
2044                                     GLchar *name) const
2045 {
2046     ASSERT(!mLinkingState);
2047     getResourceName(getOutputResourceName(index), bufSize, length, name);
2048 }
2049 
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2050 void Program::getUniformResourceName(GLuint index,
2051                                      GLsizei bufSize,
2052                                      GLsizei *length,
2053                                      GLchar *name) const
2054 {
2055     ASSERT(!mLinkingState);
2056     ASSERT(index < mState.mExecutable->getUniforms().size());
2057     getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
2058 }
2059 
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2060 void Program::getBufferVariableResourceName(GLuint index,
2061                                             GLsizei bufSize,
2062                                             GLsizei *length,
2063                                             GLchar *name) const
2064 {
2065     ASSERT(!mLinkingState);
2066     ASSERT(index < mState.mBufferVariables.size());
2067     getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
2068 }
2069 
getResourceName(const sh::ShaderVariable & resource) const2070 const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
2071 {
2072     std::string resourceName = resource.name;
2073 
2074     if (resource.isArray())
2075     {
2076         resourceName += "[0]";
2077     }
2078 
2079     return resourceName;
2080 }
2081 
getInputResourceName(GLuint index) const2082 const std::string Program::getInputResourceName(GLuint index) const
2083 {
2084     ASSERT(!mLinkingState);
2085     const sh::ShaderVariable &resource = getInputResource(index);
2086 
2087     return getResourceName(resource);
2088 }
2089 
getOutputResourceName(GLuint index) const2090 const std::string Program::getOutputResourceName(GLuint index) const
2091 {
2092     ASSERT(!mLinkingState);
2093     const sh::ShaderVariable &resource = getOutputResource(index);
2094 
2095     return getResourceName(resource);
2096 }
2097 
getOutputResource(size_t index) const2098 const sh::ShaderVariable &Program::getOutputResource(size_t index) const
2099 {
2100     ASSERT(!mLinkingState);
2101     ASSERT(index < mState.mExecutable->getOutputVariables().size());
2102     return mState.mExecutable->getOutputVariables()[index];
2103 }
2104 
getAttributeBindings() const2105 const ProgramBindings &Program::getAttributeBindings() const
2106 {
2107     ASSERT(!mLinkingState);
2108     return mAttributeBindings;
2109 }
getUniformLocationBindings() const2110 const ProgramAliasedBindings &Program::getUniformLocationBindings() const
2111 {
2112     ASSERT(!mLinkingState);
2113     return mState.mUniformLocationBindings;
2114 }
2115 
getFragmentOutputLocations() const2116 const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
2117 {
2118     ASSERT(!mLinkingState);
2119     return mFragmentOutputLocations;
2120 }
2121 
getFragmentOutputIndexes() const2122 const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
2123 {
2124     ASSERT(!mLinkingState);
2125     return mFragmentOutputIndexes;
2126 }
2127 
getTransformFeedbackStrides() const2128 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2129 {
2130     ASSERT(!mLinkingState);
2131     return mState.mExecutable->getTransformFeedbackStrides();
2132 }
2133 
getFragDataLocation(const std::string & name) const2134 GLint Program::getFragDataLocation(const std::string &name) const
2135 {
2136     ASSERT(!mLinkingState);
2137     GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
2138                                                 mState.mExecutable->getOutputLocations(), name);
2139     if (primaryLocation != -1)
2140     {
2141         return primaryLocation;
2142     }
2143     return GetVariableLocation(mState.mExecutable->getOutputVariables(),
2144                                mState.mExecutable->getSecondaryOutputLocations(), name);
2145 }
2146 
getFragDataIndex(const std::string & name) const2147 GLint Program::getFragDataIndex(const std::string &name) const
2148 {
2149     ASSERT(!mLinkingState);
2150     if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2151                             mState.mExecutable->getOutputLocations(), name) != -1)
2152     {
2153         return 0;
2154     }
2155     if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2156                             mState.mExecutable->getSecondaryOutputLocations(), name) != -1)
2157     {
2158         return 1;
2159     }
2160     return -1;
2161 }
2162 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2163 void Program::getActiveUniform(GLuint index,
2164                                GLsizei bufsize,
2165                                GLsizei *length,
2166                                GLint *size,
2167                                GLenum *type,
2168                                GLchar *name) const
2169 {
2170     ASSERT(!mLinkingState);
2171     if (mLinked)
2172     {
2173         // index must be smaller than getActiveUniformCount()
2174         ASSERT(index < mState.mExecutable->getUniforms().size());
2175         const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
2176 
2177         if (bufsize > 0)
2178         {
2179             std::string string = uniform.name;
2180             CopyStringToBuffer(name, string, bufsize, length);
2181         }
2182 
2183         *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2184         *type = uniform.type;
2185     }
2186     else
2187     {
2188         if (bufsize > 0)
2189         {
2190             name[0] = '\0';
2191         }
2192 
2193         if (length)
2194         {
2195             *length = 0;
2196         }
2197 
2198         *size = 0;
2199         *type = GL_NONE;
2200     }
2201 }
2202 
getActiveUniformCount() const2203 GLint Program::getActiveUniformCount() const
2204 {
2205     ASSERT(!mLinkingState);
2206     if (mLinked)
2207     {
2208         return static_cast<GLint>(mState.mExecutable->getUniforms().size());
2209     }
2210     else
2211     {
2212         return 0;
2213     }
2214 }
2215 
getActiveBufferVariableCount() const2216 size_t Program::getActiveBufferVariableCount() const
2217 {
2218     ASSERT(!mLinkingState);
2219     return mLinked ? mState.mBufferVariables.size() : 0;
2220 }
2221 
getActiveUniformMaxLength() const2222 GLint Program::getActiveUniformMaxLength() const
2223 {
2224     ASSERT(!mLinkingState);
2225     size_t maxLength = 0;
2226 
2227     if (mLinked)
2228     {
2229         for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
2230         {
2231             if (!uniform.name.empty())
2232             {
2233                 size_t length = uniform.name.length() + 1u;
2234                 if (uniform.isArray())
2235                 {
2236                     length += 3;  // Counting in "[0]".
2237                 }
2238                 maxLength = std::max(length, maxLength);
2239             }
2240         }
2241     }
2242 
2243     return static_cast<GLint>(maxLength);
2244 }
2245 
isValidUniformLocation(UniformLocation location) const2246 bool Program::isValidUniformLocation(UniformLocation location) const
2247 {
2248     ASSERT(!mLinkingState);
2249     ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2250     return (location.value >= 0 &&
2251             static_cast<size_t>(location.value) < mState.mUniformLocations.size() &&
2252             mState.mUniformLocations[static_cast<size_t>(location.value)].used());
2253 }
2254 
getUniformByLocation(UniformLocation location) const2255 const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const
2256 {
2257     ASSERT(!mLinkingState);
2258     ASSERT(location.value >= 0 &&
2259            static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2260     return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
2261 }
2262 
getUniformLocation(UniformLocation location) const2263 const VariableLocation &Program::getUniformLocation(UniformLocation location) const
2264 {
2265     ASSERT(!mLinkingState);
2266     ASSERT(location.value >= 0 &&
2267            static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2268     return mState.mUniformLocations[location.value];
2269 }
2270 
getBufferVariableByIndex(GLuint index) const2271 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2272 {
2273     ASSERT(!mLinkingState);
2274     ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2275     return mState.mBufferVariables[index];
2276 }
2277 
getUniformLocation(const std::string & name) const2278 UniformLocation Program::getUniformLocation(const std::string &name) const
2279 {
2280     ASSERT(!mLinkingState);
2281     return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
2282 }
2283 
getUniformIndex(const std::string & name) const2284 GLuint Program::getUniformIndex(const std::string &name) const
2285 {
2286     ASSERT(!mLinkingState);
2287     return mState.getUniformIndexFromName(name);
2288 }
2289 
shouldIgnoreUniform(UniformLocation location) const2290 bool Program::shouldIgnoreUniform(UniformLocation location) const
2291 {
2292     if (location.value == -1)
2293     {
2294         return true;
2295     }
2296 
2297     if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored)
2298     {
2299         return true;
2300     }
2301 
2302     return false;
2303 }
2304 
2305 template <typename UniformT,
2306           GLint UniformSize,
2307           void (rx::ProgramImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
setUniformGeneric(UniformLocation location,GLsizei count,const UniformT * v)2308 void Program::setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v)
2309 {
2310     ASSERT(!mLinkingState);
2311     if (shouldIgnoreUniform(location))
2312     {
2313         return;
2314     }
2315 
2316     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2317     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, UniformSize, v);
2318     (mProgram->*SetUniformFunc)(location.value, clampedCount, v);
2319     onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
2320 }
2321 
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2322 void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2323 {
2324     setUniformGeneric<GLfloat, 1, &rx::ProgramImpl::setUniform1fv>(location, count, v);
2325 }
2326 
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2327 void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2328 {
2329     setUniformGeneric<GLfloat, 2, &rx::ProgramImpl::setUniform2fv>(location, count, v);
2330 }
2331 
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2332 void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2333 {
2334     setUniformGeneric<GLfloat, 3, &rx::ProgramImpl::setUniform3fv>(location, count, v);
2335 }
2336 
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2337 void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2338 {
2339     setUniformGeneric<GLfloat, 4, &rx::ProgramImpl::setUniform4fv>(location, count, v);
2340 }
2341 
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2342 void Program::setUniform1iv(Context *context,
2343                             UniformLocation location,
2344                             GLsizei count,
2345                             const GLint *v)
2346 {
2347     ASSERT(!mLinkingState);
2348     if (shouldIgnoreUniform(location))
2349     {
2350         return;
2351     }
2352 
2353     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2354     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2355 
2356     mProgram->setUniform1iv(location.value, clampedCount, v);
2357 
2358     if (mState.isSamplerUniformIndex(locationInfo.index))
2359     {
2360         updateSamplerUniform(context, locationInfo, clampedCount, v);
2361     }
2362     else
2363     {
2364         onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
2365     }
2366 }
2367 
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2368 void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2369 {
2370     setUniformGeneric<GLint, 2, &rx::ProgramImpl::setUniform2iv>(location, count, v);
2371 }
2372 
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2373 void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2374 {
2375     setUniformGeneric<GLint, 3, &rx::ProgramImpl::setUniform3iv>(location, count, v);
2376 }
2377 
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2378 void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2379 {
2380     setUniformGeneric<GLint, 4, &rx::ProgramImpl::setUniform4iv>(location, count, v);
2381 }
2382 
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2383 void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2384 {
2385     setUniformGeneric<GLuint, 1, &rx::ProgramImpl::setUniform1uiv>(location, count, v);
2386 }
2387 
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2388 void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2389 {
2390     setUniformGeneric<GLuint, 2, &rx::ProgramImpl::setUniform2uiv>(location, count, v);
2391 }
2392 
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2393 void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2394 {
2395     setUniformGeneric<GLuint, 3, &rx::ProgramImpl::setUniform3uiv>(location, count, v);
2396 }
2397 
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2398 void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2399 {
2400     setUniformGeneric<GLuint, 4, &rx::ProgramImpl::setUniform4uiv>(location, count, v);
2401 }
2402 
2403 template <
2404     typename UniformT,
2405     GLint MatrixC,
2406     GLint MatrixR,
2407     void (rx::ProgramImpl::*SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
setUniformMatrixGeneric(UniformLocation location,GLsizei count,GLboolean transpose,const UniformT * v)2408 void Program::setUniformMatrixGeneric(UniformLocation location,
2409                                       GLsizei count,
2410                                       GLboolean transpose,
2411                                       const UniformT *v)
2412 {
2413     ASSERT(!mLinkingState);
2414     if (shouldIgnoreUniform(location))
2415     {
2416         return;
2417     }
2418 
2419     GLsizei clampedCount = clampMatrixUniformCount<MatrixC, MatrixR>(location, count, transpose, v);
2420     (mProgram->*SetUniformMatrixFunc)(location.value, clampedCount, transpose, v);
2421     onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
2422 }
2423 
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2424 void Program::setUniformMatrix2fv(UniformLocation location,
2425                                   GLsizei count,
2426                                   GLboolean transpose,
2427                                   const GLfloat *v)
2428 {
2429     setUniformMatrixGeneric<GLfloat, 2, 2, &rx::ProgramImpl::setUniformMatrix2fv>(location, count,
2430                                                                                   transpose, v);
2431 }
2432 
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2433 void Program::setUniformMatrix3fv(UniformLocation location,
2434                                   GLsizei count,
2435                                   GLboolean transpose,
2436                                   const GLfloat *v)
2437 {
2438     setUniformMatrixGeneric<GLfloat, 3, 3, &rx::ProgramImpl::setUniformMatrix3fv>(location, count,
2439                                                                                   transpose, v);
2440 }
2441 
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2442 void Program::setUniformMatrix4fv(UniformLocation location,
2443                                   GLsizei count,
2444                                   GLboolean transpose,
2445                                   const GLfloat *v)
2446 {
2447     setUniformMatrixGeneric<GLfloat, 4, 4, &rx::ProgramImpl::setUniformMatrix4fv>(location, count,
2448                                                                                   transpose, v);
2449 }
2450 
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2451 void Program::setUniformMatrix2x3fv(UniformLocation location,
2452                                     GLsizei count,
2453                                     GLboolean transpose,
2454                                     const GLfloat *v)
2455 {
2456     setUniformMatrixGeneric<GLfloat, 2, 3, &rx::ProgramImpl::setUniformMatrix2x3fv>(location, count,
2457                                                                                     transpose, v);
2458 }
2459 
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2460 void Program::setUniformMatrix2x4fv(UniformLocation location,
2461                                     GLsizei count,
2462                                     GLboolean transpose,
2463                                     const GLfloat *v)
2464 {
2465     setUniformMatrixGeneric<GLfloat, 2, 4, &rx::ProgramImpl::setUniformMatrix2x4fv>(location, count,
2466                                                                                     transpose, v);
2467 }
2468 
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2469 void Program::setUniformMatrix3x2fv(UniformLocation location,
2470                                     GLsizei count,
2471                                     GLboolean transpose,
2472                                     const GLfloat *v)
2473 {
2474     setUniformMatrixGeneric<GLfloat, 3, 2, &rx::ProgramImpl::setUniformMatrix3x2fv>(location, count,
2475                                                                                     transpose, v);
2476 }
2477 
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2478 void Program::setUniformMatrix3x4fv(UniformLocation location,
2479                                     GLsizei count,
2480                                     GLboolean transpose,
2481                                     const GLfloat *v)
2482 {
2483     setUniformMatrixGeneric<GLfloat, 3, 4, &rx::ProgramImpl::setUniformMatrix3x4fv>(location, count,
2484                                                                                     transpose, v);
2485 }
2486 
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2487 void Program::setUniformMatrix4x2fv(UniformLocation location,
2488                                     GLsizei count,
2489                                     GLboolean transpose,
2490                                     const GLfloat *v)
2491 {
2492     setUniformMatrixGeneric<GLfloat, 4, 2, &rx::ProgramImpl::setUniformMatrix4x2fv>(location, count,
2493                                                                                     transpose, v);
2494 }
2495 
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2496 void Program::setUniformMatrix4x3fv(UniformLocation location,
2497                                     GLsizei count,
2498                                     GLboolean transpose,
2499                                     const GLfloat *v)
2500 {
2501     setUniformMatrixGeneric<GLfloat, 4, 3, &rx::ProgramImpl::setUniformMatrix4x3fv>(location, count,
2502                                                                                     transpose, v);
2503 }
2504 
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2505 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2506 {
2507     ASSERT(!mLinkingState);
2508     GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2509     const std::vector<GLuint> &boundTextureUnits =
2510         mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
2511     return (uniformLocation.arrayIndex < boundTextureUnits.size())
2512                ? boundTextureUnits[uniformLocation.arrayIndex]
2513                : 0;
2514 }
2515 
getImageUniformBinding(const VariableLocation & uniformLocation) const2516 GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
2517 {
2518     ASSERT(!mLinkingState);
2519     GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
2520 
2521     const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings();
2522     const std::vector<GLuint> &boundImageUnits     = imageBindings[imageIndex].boundImageUnits;
2523     return boundImageUnits[uniformLocation.arrayIndex];
2524 }
2525 
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2526 void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const
2527 {
2528     ASSERT(!mLinkingState);
2529     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2530     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2531 
2532     if (uniform.isSampler())
2533     {
2534         *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2535         return;
2536     }
2537     else if (uniform.isImage())
2538     {
2539         *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2540         return;
2541     }
2542 
2543     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2544     if (nativeType == GL_FLOAT)
2545     {
2546         mProgram->getUniformfv(context, location.value, v);
2547     }
2548     else
2549     {
2550         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2551     }
2552 }
2553 
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2554 void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const
2555 {
2556     ASSERT(!mLinkingState);
2557     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2558     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2559 
2560     if (uniform.isSampler())
2561     {
2562         *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2563         return;
2564     }
2565     else if (uniform.isImage())
2566     {
2567         *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2568         return;
2569     }
2570 
2571     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2572     if (nativeType == GL_INT || nativeType == GL_BOOL)
2573     {
2574         mProgram->getUniformiv(context, location.value, v);
2575     }
2576     else
2577     {
2578         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2579     }
2580 }
2581 
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2582 void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const
2583 {
2584     ASSERT(!mLinkingState);
2585     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2586     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2587 
2588     if (uniform.isSampler())
2589     {
2590         *v = getSamplerUniformBinding(uniformLocation);
2591         return;
2592     }
2593     else if (uniform.isImage())
2594     {
2595         *v = getImageUniformBinding(uniformLocation);
2596         return;
2597     }
2598 
2599     const GLenum nativeType = VariableComponentType(uniform.type);
2600     if (nativeType == GL_UNSIGNED_INT)
2601     {
2602         mProgram->getUniformuiv(context, location.value, v);
2603     }
2604     else
2605     {
2606         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2607     }
2608 }
2609 
flagForDeletion()2610 void Program::flagForDeletion()
2611 {
2612     ASSERT(!mLinkingState);
2613     mDeleteStatus = true;
2614 }
2615 
isFlaggedForDeletion() const2616 bool Program::isFlaggedForDeletion() const
2617 {
2618     ASSERT(!mLinkingState);
2619     return mDeleteStatus;
2620 }
2621 
validate(const Caps & caps)2622 void Program::validate(const Caps &caps)
2623 {
2624     ASSERT(!mLinkingState);
2625     mState.mExecutable->resetInfoLog();
2626     InfoLog &infoLog = mState.mExecutable->getInfoLog();
2627 
2628     if (mLinked)
2629     {
2630         mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
2631     }
2632     else
2633     {
2634         infoLog << "Program has not been successfully linked.";
2635     }
2636 }
2637 
isValidated() const2638 bool Program::isValidated() const
2639 {
2640     ASSERT(!mLinkingState);
2641     return mValidated;
2642 }
2643 
getActiveUniformBlockName(const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2644 void Program::getActiveUniformBlockName(const UniformBlockIndex blockIndex,
2645                                         GLsizei bufSize,
2646                                         GLsizei *length,
2647                                         GLchar *blockName) const
2648 {
2649     ASSERT(!mLinkingState);
2650     GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
2651                           blockName);
2652 }
2653 
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2654 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
2655                                               GLsizei bufSize,
2656                                               GLsizei *length,
2657                                               GLchar *blockName) const
2658 {
2659     ASSERT(!mLinkingState);
2660     GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize,
2661                           length, blockName);
2662 }
2663 
2664 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const2665 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
2666 {
2667     int maxLength = 0;
2668 
2669     if (mLinked)
2670     {
2671         for (const T &resource : resources)
2672         {
2673             if (!resource.name.empty())
2674             {
2675                 int length = static_cast<int>(resource.nameWithArrayIndex().length());
2676                 maxLength  = std::max(length + 1, maxLength);
2677             }
2678         }
2679     }
2680 
2681     return maxLength;
2682 }
2683 
getActiveUniformBlockMaxNameLength() const2684 GLint Program::getActiveUniformBlockMaxNameLength() const
2685 {
2686     ASSERT(!mLinkingState);
2687     return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
2688 }
2689 
getActiveShaderStorageBlockMaxNameLength() const2690 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
2691 {
2692     ASSERT(!mLinkingState);
2693     return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
2694 }
2695 
getUniformBlockIndex(const std::string & name) const2696 GLuint Program::getUniformBlockIndex(const std::string &name) const
2697 {
2698     ASSERT(!mLinkingState);
2699     return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
2700 }
2701 
getShaderStorageBlockIndex(const std::string & name) const2702 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
2703 {
2704     ASSERT(!mLinkingState);
2705     return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
2706 }
2707 
getUniformBlockByIndex(GLuint index) const2708 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
2709 {
2710     ASSERT(!mLinkingState);
2711     ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
2712     return mState.mExecutable->getUniformBlocks()[index];
2713 }
2714 
getShaderStorageBlockByIndex(GLuint index) const2715 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
2716 {
2717     ASSERT(!mLinkingState);
2718     ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
2719     return mState.mExecutable->getShaderStorageBlocks()[index];
2720 }
2721 
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)2722 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
2723 {
2724     ASSERT(!mLinkingState);
2725     mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding;
2726     mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value,
2727                                                         uniformBlockBinding != 0);
2728     mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value);
2729 }
2730 
getUniformBlockBinding(GLuint uniformBlockIndex) const2731 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
2732 {
2733     ASSERT(!mLinkingState);
2734     return mState.getUniformBlockBinding(uniformBlockIndex);
2735 }
2736 
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const2737 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
2738 {
2739     ASSERT(!mLinkingState);
2740     return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
2741 }
2742 
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2743 void Program::setTransformFeedbackVaryings(GLsizei count,
2744                                            const GLchar *const *varyings,
2745                                            GLenum bufferMode)
2746 {
2747     ASSERT(!mLinkingState);
2748     mState.mTransformFeedbackVaryingNames.resize(count);
2749     for (GLsizei i = 0; i < count; i++)
2750     {
2751         mState.mTransformFeedbackVaryingNames[i] = varyings[i];
2752     }
2753 
2754     mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
2755 }
2756 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2757 void Program::getTransformFeedbackVarying(GLuint index,
2758                                           GLsizei bufSize,
2759                                           GLsizei *length,
2760                                           GLsizei *size,
2761                                           GLenum *type,
2762                                           GLchar *name) const
2763 {
2764     ASSERT(!mLinkingState);
2765     if (mLinked)
2766     {
2767         ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
2768         const auto &var     = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
2769         std::string varName = var.nameWithArrayIndex();
2770         GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
2771         if (length)
2772         {
2773             *length = lastNameIdx;
2774         }
2775         if (size)
2776         {
2777             *size = var.size();
2778         }
2779         if (type)
2780         {
2781             *type = var.type;
2782         }
2783         if (name)
2784         {
2785             memcpy(name, varName.c_str(), lastNameIdx);
2786             name[lastNameIdx] = '\0';
2787         }
2788     }
2789 }
2790 
getTransformFeedbackVaryingCount() const2791 GLsizei Program::getTransformFeedbackVaryingCount() const
2792 {
2793     ASSERT(!mLinkingState);
2794     if (mLinked)
2795     {
2796         return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
2797     }
2798     else
2799     {
2800         return 0;
2801     }
2802 }
2803 
getTransformFeedbackVaryingMaxLength() const2804 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
2805 {
2806     ASSERT(!mLinkingState);
2807     if (mLinked)
2808     {
2809         GLsizei maxSize = 0;
2810         for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
2811         {
2812             maxSize =
2813                 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
2814         }
2815 
2816         return maxSize;
2817     }
2818     else
2819     {
2820         return 0;
2821     }
2822 }
2823 
getTransformFeedbackBufferMode() const2824 GLenum Program::getTransformFeedbackBufferMode() const
2825 {
2826     ASSERT(!mLinkingState);
2827     return mState.mExecutable->getTransformFeedbackBufferMode();
2828 }
2829 
linkValidateShaders(InfoLog & infoLog)2830 bool Program::linkValidateShaders(InfoLog &infoLog)
2831 {
2832     const ShaderMap<Shader *> &shaders = mState.mAttachedShaders;
2833 
2834     bool isComputeShaderAttached  = shaders[ShaderType::Compute] != nullptr;
2835     bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] ||
2836                                     shaders[ShaderType::TessControl] ||
2837                                     shaders[ShaderType::TessEvaluation] ||
2838                                     shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment];
2839     // Check whether we both have a compute and non-compute shaders attached.
2840     // If there are of both types attached, then linking should fail.
2841     // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
2842     if (isComputeShaderAttached && isGraphicsShaderAttached)
2843     {
2844         infoLog << "Both compute and graphics shaders are attached to the same program.";
2845         return false;
2846     }
2847 
2848     Optional<int> version;
2849     for (ShaderType shaderType : kAllGraphicsShaderTypes)
2850     {
2851         Shader *shader = shaders[shaderType];
2852         ASSERT(!shader || shader->getType() == shaderType);
2853         if (!shader)
2854         {
2855             continue;
2856         }
2857 
2858         if (!shader->isCompiled())
2859         {
2860             infoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
2861             return false;
2862         }
2863 
2864         if (!version.valid())
2865         {
2866             version = shader->getShaderVersion();
2867         }
2868         else if (version != shader->getShaderVersion())
2869         {
2870             infoLog << ShaderTypeToString(shaderType)
2871                     << " shader version does not match other shader versions.";
2872             return false;
2873         }
2874     }
2875 
2876     if (isComputeShaderAttached)
2877     {
2878         ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute);
2879 
2880         mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize();
2881 
2882         // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
2883         // If the work group size is not specified, a link time error should occur.
2884         if (!mState.mComputeShaderLocalSize.isDeclared())
2885         {
2886             infoLog << "Work group size is not specified.";
2887             return false;
2888         }
2889     }
2890     else
2891     {
2892         if (!isGraphicsShaderAttached)
2893         {
2894             infoLog << "No compiled shaders.";
2895             return false;
2896         }
2897 
2898         bool hasVertex   = shaders[ShaderType::Vertex] != nullptr;
2899         bool hasFragment = shaders[ShaderType::Fragment] != nullptr;
2900         if (!isSeparable() && (!hasVertex || !hasFragment))
2901         {
2902             infoLog
2903                 << "The program must contain objects to form both a vertex and fragment shader.";
2904             return false;
2905         }
2906 
2907         bool hasTessControl    = shaders[ShaderType::TessControl] != nullptr;
2908         bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr;
2909         if (!isSeparable() && (hasTessControl != hasTessEvaluation))
2910         {
2911             infoLog << "Tessellation control and evaluation shaders must be specified together.";
2912             return false;
2913         }
2914 
2915         Shader *geometryShader = shaders[ShaderType::Geometry];
2916         if (shaders[ShaderType::Geometry])
2917         {
2918             // [GL_EXT_geometry_shader] Chapter 7
2919             // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
2920             // Language Specification, as well as any of the following reasons:
2921             // * One or more of the shader objects attached to <program> are not compiled
2922             //   successfully.
2923             // * The shaders do not use the same shader language version.
2924             // * <program> contains objects to form a geometry shader, and
2925             //   - <program> is not separable and contains no objects to form a vertex shader; or
2926             //   - the input primitive type, output primitive type, or maximum output vertex count
2927             //     is not specified in the compiled geometry shader object.
2928             ASSERT(geometryShader->getType() == ShaderType::Geometry);
2929 
2930             Optional<PrimitiveMode> inputPrimitive =
2931                 geometryShader->getGeometryShaderInputPrimitiveType();
2932             if (!inputPrimitive.valid())
2933             {
2934                 infoLog << "Input primitive type is not specified in the geometry shader.";
2935                 return false;
2936             }
2937 
2938             Optional<PrimitiveMode> outputPrimitive =
2939                 geometryShader->getGeometryShaderOutputPrimitiveType();
2940             if (!outputPrimitive.valid())
2941             {
2942                 infoLog << "Output primitive type is not specified in the geometry shader.";
2943                 return false;
2944             }
2945 
2946             Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
2947             if (!maxVertices.valid())
2948             {
2949                 infoLog << "'max_vertices' is not specified in the geometry shader.";
2950                 return false;
2951             }
2952 
2953             mState.mExecutable->mGeometryShaderInputPrimitiveType  = inputPrimitive.value();
2954             mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
2955             mState.mExecutable->mGeometryShaderMaxVertices         = maxVertices.value();
2956             mState.mExecutable->mGeometryShaderInvocations =
2957                 geometryShader->getGeometryShaderInvocations();
2958         }
2959 
2960         Shader *tessControlShader = shaders[ShaderType::TessControl];
2961         if (tessControlShader)
2962         {
2963             int tcsShaderVertices = tessControlShader->getTessControlShaderVertices();
2964             if (tcsShaderVertices == 0)
2965             {
2966                 // In tessellation control shader, output vertices should be specified at least
2967                 // once.
2968                 // > GLSL ES Version 3.20.6 spec:
2969                 // > 4.4.2. Output Layout Qualifiers
2970                 // > Tessellation Control Outputs
2971                 // > ...
2972                 // > There must be at least one layout qualifier specifying an output patch vertex
2973                 // > count in any program containing a tessellation control shader.
2974                 infoLog << "In Tessellation Control Shader, at least one layout qualifier "
2975                            "specifying an output patch vertex count must exist.";
2976                 return false;
2977             }
2978 
2979             mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
2980         }
2981 
2982         Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
2983         if (tessEvaluationShader)
2984         {
2985             GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode();
2986             if (tesPrimitiveMode == 0)
2987             {
2988                 // In tessellation evaluation shader, a primitive mode should be specified at least
2989                 // once.
2990                 // > GLSL ES Version 3.20.6 spec:
2991                 // > 4.4.1. Input Layout Qualifiers
2992                 // > Tessellation Evaluation Inputs
2993                 // > ...
2994                 // > The tessellation evaluation shader object in a program must declare a primitive
2995                 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
2996                 // > identifiers is optional.
2997                 infoLog << "The Tessellation Evaluation Shader object in a program must declare a "
2998                            "primitive mode in its input layout.";
2999                 return false;
3000             }
3001 
3002             mState.mExecutable->mTessGenMode        = tesPrimitiveMode;
3003             mState.mExecutable->mTessGenSpacing     = tessEvaluationShader->getTessGenSpacing();
3004             mState.mExecutable->mTessGenVertexOrder = tessEvaluationShader->getTessGenVertexOrder();
3005             mState.mExecutable->mTessGenPointMode   = tessEvaluationShader->getTessGenPointMode();
3006         }
3007     }
3008 
3009     return true;
3010 }
3011 
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const3012 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
3013 {
3014     ASSERT(!mLinkingState);
3015     for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
3016          ++tfIndex)
3017     {
3018         const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
3019         if (tf.nameWithArrayIndex() == name)
3020         {
3021             return tfIndex;
3022         }
3023     }
3024     return GL_INVALID_INDEX;
3025 }
3026 
getTransformFeedbackVaryingResource(GLuint index) const3027 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
3028 {
3029     ASSERT(!mLinkingState);
3030     ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3031     return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3032 }
3033 
hasDrawIDUniform() const3034 bool Program::hasDrawIDUniform() const
3035 {
3036     ASSERT(!mLinkingState);
3037     return mState.mDrawIDLocation >= 0;
3038 }
3039 
setDrawIDUniform(GLint drawid)3040 void Program::setDrawIDUniform(GLint drawid)
3041 {
3042     ASSERT(!mLinkingState);
3043     ASSERT(mState.mDrawIDLocation >= 0);
3044     mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
3045 }
3046 
hasBaseVertexUniform() const3047 bool Program::hasBaseVertexUniform() const
3048 {
3049     ASSERT(!mLinkingState);
3050     return mState.mBaseVertexLocation >= 0;
3051 }
3052 
setBaseVertexUniform(GLint baseVertex)3053 void Program::setBaseVertexUniform(GLint baseVertex)
3054 {
3055     ASSERT(!mLinkingState);
3056     ASSERT(mState.mBaseVertexLocation >= 0);
3057     if (baseVertex == mState.mCachedBaseVertex)
3058     {
3059         return;
3060     }
3061     mState.mCachedBaseVertex = baseVertex;
3062     mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
3063 }
3064 
hasBaseInstanceUniform() const3065 bool Program::hasBaseInstanceUniform() const
3066 {
3067     ASSERT(!mLinkingState);
3068     return mState.mBaseInstanceLocation >= 0;
3069 }
3070 
setBaseInstanceUniform(GLuint baseInstance)3071 void Program::setBaseInstanceUniform(GLuint baseInstance)
3072 {
3073     ASSERT(!mLinkingState);
3074     ASSERT(mState.mBaseInstanceLocation >= 0);
3075     if (baseInstance == mState.mCachedBaseInstance)
3076     {
3077         return;
3078     }
3079     mState.mCachedBaseInstance = baseInstance;
3080     GLint baseInstanceInt      = baseInstance;
3081     mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
3082 }
3083 
linkVaryings(InfoLog & infoLog) const3084 bool Program::linkVaryings(InfoLog &infoLog) const
3085 {
3086     ShaderType previousShaderType = ShaderType::InvalidEnum;
3087     for (ShaderType shaderType : kAllGraphicsShaderTypes)
3088     {
3089         Shader *currentShader = mState.mAttachedShaders[shaderType];
3090         if (!currentShader)
3091         {
3092             continue;
3093         }
3094 
3095         if (previousShaderType != ShaderType::InvalidEnum)
3096         {
3097             Shader *previousShader = mState.mAttachedShaders[previousShaderType];
3098             const std::vector<sh::ShaderVariable> &outputVaryings =
3099                 previousShader->getOutputVaryings();
3100 
3101             if (!LinkValidateShaderInterfaceMatching(
3102                     outputVaryings, currentShader->getInputVaryings(), previousShaderType,
3103                     currentShader->getType(), previousShader->getShaderVersion(),
3104                     currentShader->getShaderVersion(), isSeparable(), infoLog))
3105             {
3106                 return false;
3107             }
3108         }
3109         previousShaderType = currentShader->getType();
3110     }
3111 
3112     // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
3113     // Need to move logic of validating builtin varyings inside the for-loop above.
3114     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
3115     // can be redeclared in Geometry or Tessellation shaders as well.
3116     Shader *vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
3117     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
3118     if (vertexShader && fragmentShader &&
3119         !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
3120                                      fragmentShader->getInputVaryings(), vertexShader->getType(),
3121                                      fragmentShader->getType(), vertexShader->getShaderVersion(),
3122                                      fragmentShader->getShaderVersion(), infoLog))
3123     {
3124         return false;
3125     }
3126 
3127     return true;
3128 }
3129 
linkUniforms(const Context * context,std::vector<UnusedUniform> * unusedUniformsOutOrNull,GLuint * combinedImageUniformsOut,InfoLog & infoLog)3130 bool Program::linkUniforms(const Context *context,
3131                            std::vector<UnusedUniform> *unusedUniformsOutOrNull,
3132                            GLuint *combinedImageUniformsOut,
3133                            InfoLog &infoLog)
3134 {
3135     // Initialize executable shader map.
3136     ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
3137     for (Shader *shader : mState.mAttachedShaders)
3138     {
3139         if (shader)
3140         {
3141             shaderUniforms[shader->getType()] = shader->getUniforms();
3142         }
3143     }
3144 
3145     if (!mState.mExecutable->linkUniforms(context, shaderUniforms, infoLog,
3146                                           mState.mUniformLocationBindings, combinedImageUniformsOut,
3147                                           unusedUniformsOutOrNull, &mState.mUniformLocations))
3148     {
3149         return false;
3150     }
3151 
3152     if (context->getClientVersion() >= Version(3, 1))
3153     {
3154         GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size());
3155 
3156         if (locationSize > context->getCaps().maxUniformLocations)
3157         {
3158             infoLog << "Exceeded maximum uniform location size";
3159             return false;
3160         }
3161     }
3162 
3163     return true;
3164 }
3165 
3166 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3167 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3168 {
3169     const Caps &caps               = context->getCaps();
3170     const Limitations &limitations = context->getLimitations();
3171     bool webglCompatibility        = context->isWebGL();
3172     int shaderVersion              = -1;
3173     unsigned int usedLocations     = 0;
3174 
3175     Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
3176 
3177     if (!vertexShader)
3178     {
3179         // No vertex shader, so no attributes, so nothing to do
3180         return true;
3181     }
3182 
3183     shaderVersion = vertexShader->getShaderVersion();
3184     if (shaderVersion >= 300)
3185     {
3186         // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
3187         // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
3188         // aliasing checks.
3189         mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes();
3190     }
3191     else
3192     {
3193         // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3194         mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes();
3195     }
3196 
3197     GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
3198     std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
3199 
3200     // Assign locations to attributes that have a binding location and check for attribute aliasing.
3201     for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3202     {
3203         // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3204         // structures, so we don't need to worry about adjusting their names or generating entries
3205         // for each member/element (unlike uniforms for example).
3206         ASSERT(!attribute.isArray() && !attribute.isStruct());
3207 
3208         int bindingLocation = mAttributeBindings.getBinding(attribute);
3209         if (attribute.location == -1 && bindingLocation != -1)
3210         {
3211             attribute.location = bindingLocation;
3212         }
3213 
3214         if (attribute.location != -1)
3215         {
3216             // Location is set by glBindAttribLocation or by location layout qualifier
3217             const int regs = VariableRegisterCount(attribute.type);
3218 
3219             if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3220             {
3221                 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3222                         << " is too big to fit";
3223 
3224                 return false;
3225             }
3226 
3227             for (int reg = 0; reg < regs; reg++)
3228             {
3229                 const int regLocation               = attribute.location + reg;
3230                 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3231 
3232                 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3233                 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3234                 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3235                 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3236                 if (linkedAttribute)
3237                 {
3238                     if (shaderVersion >= 300 || webglCompatibility ||
3239                         limitations.noVertexAttributeAliasing)
3240                     {
3241                         infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3242                                 << linkedAttribute->name << "' at location " << regLocation;
3243                         return false;
3244                     }
3245                 }
3246                 else
3247                 {
3248                     usedAttribMap[regLocation] = &attribute;
3249                 }
3250 
3251                 usedLocations |= 1 << regLocation;
3252             }
3253         }
3254     }
3255 
3256     // Assign locations to attributes that don't have a binding location.
3257     for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3258     {
3259         // Not set by glBindAttribLocation or by location layout qualifier
3260         if (attribute.location == -1)
3261         {
3262             int regs           = VariableRegisterCount(attribute.type);
3263             int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3264 
3265             if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3266             {
3267                 infoLog << "Too many attributes (" << attribute.name << ")";
3268                 return false;
3269             }
3270 
3271             attribute.location = availableIndex;
3272         }
3273     }
3274 
3275     ASSERT(mState.mExecutable->mAttributesTypeMask.none());
3276     ASSERT(mState.mExecutable->mAttributesMask.none());
3277 
3278     // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3279     // shader versions we're only processing active attributes to begin with.
3280     if (shaderVersion >= 300)
3281     {
3282         for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
3283              attributeIter != mState.mExecutable->getProgramInputs().end();)
3284         {
3285             if (attributeIter->active)
3286             {
3287                 ++attributeIter;
3288             }
3289             else
3290             {
3291                 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
3292             }
3293         }
3294     }
3295 
3296     for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
3297     {
3298         ASSERT(attribute.active);
3299         ASSERT(attribute.location != -1);
3300         unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3301 
3302         unsigned int location = static_cast<unsigned int>(attribute.location);
3303         for (unsigned int r = 0; r < regs; r++)
3304         {
3305             // Built-in active program inputs don't have a bound attribute.
3306             if (!attribute.isBuiltIn())
3307             {
3308                 mState.mExecutable->mActiveAttribLocationsMask.set(location);
3309                 mState.mExecutable->mMaxActiveAttribLocation =
3310                     std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
3311 
3312                 ComponentType componentType =
3313                     GLenumToComponentType(VariableComponentType(attribute.type));
3314 
3315                 SetComponentTypeMask(componentType, location,
3316                                      &mState.mExecutable->mAttributesTypeMask);
3317                 mState.mExecutable->mAttributesMask.set(location);
3318 
3319                 location++;
3320             }
3321         }
3322     }
3323 
3324     return true;
3325 }
3326 
setUniformValuesFromBindingQualifiers()3327 void Program::setUniformValuesFromBindingQualifiers()
3328 {
3329     for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
3330     {
3331         const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
3332         if (samplerUniform.binding != -1)
3333         {
3334             UniformLocation location = getUniformLocation(samplerUniform.name);
3335             ASSERT(location.value != -1);
3336             std::vector<GLint> boundTextureUnits;
3337             for (unsigned int elementIndex = 0;
3338                  elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
3339             {
3340                 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
3341             }
3342 
3343             // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
3344             // We know it's safe not to notify the Context because this is only called after link.
3345             setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
3346                           boundTextureUnits.data());
3347         }
3348     }
3349 }
3350 
initInterfaceBlockBindings()3351 void Program::initInterfaceBlockBindings()
3352 {
3353     // Set initial bindings from shader.
3354     for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
3355          blockIndex++)
3356     {
3357         InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
3358         bindUniformBlock({blockIndex}, uniformBlock.binding);
3359     }
3360 }
3361 
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)3362 void Program::updateSamplerUniform(Context *context,
3363                                    const VariableLocation &locationInfo,
3364                                    GLsizei clampedCount,
3365                                    const GLint *v)
3366 {
3367     ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
3368     GLuint samplerIndex            = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
3369     SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
3370     std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
3371 
3372     if (locationInfo.arrayIndex >= boundTextureUnits.size())
3373     {
3374         return;
3375     }
3376     GLsizei safeUniformCount = std::min(
3377         clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
3378 
3379     // Update the sampler uniforms.
3380     for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
3381     {
3382         GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
3383         GLint newTextureUnit = v[arrayIndex];
3384 
3385         if (oldTextureUnit == newTextureUnit)
3386         {
3387             continue;
3388         }
3389 
3390         boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
3391 
3392         // Update the reference counts.
3393         uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
3394         uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit];
3395         ASSERT(oldRefCount > 0);
3396         ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
3397         oldRefCount--;
3398         newRefCount++;
3399 
3400         // Check for binding type change.
3401         TextureType &newSamplerType     = mState.mExecutable->mActiveSamplerTypes[newTextureUnit];
3402         TextureType &oldSamplerType     = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit];
3403         SamplerFormat &newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit];
3404         SamplerFormat &oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit];
3405 
3406         if (newRefCount == 1)
3407         {
3408             newSamplerType   = samplerBinding.textureType;
3409             newSamplerFormat = samplerBinding.format;
3410             mState.mExecutable->mActiveSamplersMask.set(newTextureUnit);
3411             mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] =
3412                 mState.mExecutable->getUniforms()[locationInfo.index].activeShaders();
3413         }
3414         else
3415         {
3416             if (newSamplerType != samplerBinding.textureType)
3417             {
3418                 // Conflict detected. Ensure we reset it properly.
3419                 newSamplerType = TextureType::InvalidEnum;
3420             }
3421             if (newSamplerFormat != samplerBinding.format)
3422             {
3423                 newSamplerFormat = SamplerFormat::InvalidEnum;
3424             }
3425         }
3426 
3427         // Unset previously active sampler.
3428         if (oldRefCount == 0)
3429         {
3430             oldSamplerType   = TextureType::InvalidEnum;
3431             oldSamplerFormat = SamplerFormat::InvalidEnum;
3432             mState.mExecutable->mActiveSamplersMask.reset(oldTextureUnit);
3433         }
3434         else
3435         {
3436             if (oldSamplerType == TextureType::InvalidEnum ||
3437                 oldSamplerFormat == SamplerFormat::InvalidEnum)
3438             {
3439                 // Previous conflict. Check if this new change fixed the conflict.
3440                 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
3441             }
3442         }
3443 
3444         // Update the observing PPO's executable, if any.
3445         // Do this before any of the Context work, since that uses the current ProgramExecutable,
3446         // which will be the PPO's if this Program is bound to it, rather than this Program's.
3447         if (isSeparable())
3448         {
3449             onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3450         }
3451 
3452         // Notify context.
3453         if (context)
3454         {
3455             context->onSamplerUniformChange(newTextureUnit);
3456             context->onSamplerUniformChange(oldTextureUnit);
3457         }
3458     }
3459 
3460     // Invalidate the validation cache.
3461     getExecutable().resetCachedValidateSamplersResult();
3462     // Inform any PPOs this Program may be bound to.
3463     onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
3464 }
3465 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)3466 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
3467 {
3468     mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
3469                                                        mExecutable->mSamplerBindings);
3470 }
3471 
3472 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)3473 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
3474                                    GLsizei count,
3475                                    int vectorSize,
3476                                    const T *v)
3477 {
3478     if (count == 1)
3479         return 1;
3480 
3481     const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
3482 
3483     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
3484     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
3485     unsigned int remainingElements =
3486         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
3487     GLsizei maxElementCount =
3488         static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
3489 
3490     if (count * vectorSize > maxElementCount)
3491     {
3492         return maxElementCount / vectorSize;
3493     }
3494 
3495     return count;
3496 }
3497 
3498 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)3499 GLsizei Program::clampMatrixUniformCount(UniformLocation location,
3500                                          GLsizei count,
3501                                          GLboolean transpose,
3502                                          const T *v)
3503 {
3504     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
3505 
3506     if (!transpose)
3507     {
3508         return clampUniformCount(locationInfo, count, cols * rows, v);
3509     }
3510 
3511     const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
3512 
3513     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
3514     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
3515     unsigned int remainingElements =
3516         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
3517     return std::min(count, static_cast<GLsizei>(remainingElements));
3518 }
3519 
3520 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
3521 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
3522 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const3523 void Program::getUniformInternal(const Context *context,
3524                                  DestT *dataOut,
3525                                  UniformLocation location,
3526                                  GLenum nativeType,
3527                                  int components) const
3528 {
3529     switch (nativeType)
3530     {
3531         case GL_BOOL:
3532         {
3533             GLint tempValue[16] = {0};
3534             mProgram->getUniformiv(context, location.value, tempValue);
3535             UniformStateQueryCastLoop<GLboolean>(
3536                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3537             break;
3538         }
3539         case GL_INT:
3540         {
3541             GLint tempValue[16] = {0};
3542             mProgram->getUniformiv(context, location.value, tempValue);
3543             UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3544                                              components);
3545             break;
3546         }
3547         case GL_UNSIGNED_INT:
3548         {
3549             GLuint tempValue[16] = {0};
3550             mProgram->getUniformuiv(context, location.value, tempValue);
3551             UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3552                                               components);
3553             break;
3554         }
3555         case GL_FLOAT:
3556         {
3557             GLfloat tempValue[16] = {0};
3558             mProgram->getUniformfv(context, location.value, tempValue);
3559             UniformStateQueryCastLoop<GLfloat>(
3560                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3561             break;
3562         }
3563         default:
3564             UNREACHABLE();
3565             break;
3566     }
3567 }
3568 
syncState(const Context * context)3569 angle::Result Program::syncState(const Context *context)
3570 {
3571     if (mDirtyBits.any())
3572     {
3573         ASSERT(!mLinkingState);
3574         ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
3575         mDirtyBits.reset();
3576     }
3577 
3578     return angle::Result::Continue;
3579 }
3580 
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const3581 angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
3582 {
3583     BinaryOutputStream stream;
3584 
3585     stream.writeBytes(reinterpret_cast<const unsigned char *>(angle::GetANGLECommitHash()),
3586                       angle::GetANGLECommitHashSize());
3587 
3588     // nullptr context is supported when computing binary length.
3589     if (context)
3590     {
3591         stream.writeInt(context->getClientVersion().major);
3592         stream.writeInt(context->getClientVersion().minor);
3593     }
3594     else
3595     {
3596         stream.writeInt(2);
3597         stream.writeInt(0);
3598     }
3599 
3600     // Must be before mExecutable->save(), since it uses the value.
3601     stream.writeBool(mState.mSeparable);
3602 
3603     mState.mExecutable->save(mState.mSeparable, &stream);
3604 
3605     const auto &computeLocalSize = mState.getComputeShaderLocalSize();
3606 
3607     stream.writeInt(computeLocalSize[0]);
3608     stream.writeInt(computeLocalSize[1]);
3609     stream.writeInt(computeLocalSize[2]);
3610 
3611     stream.writeInt(mState.mNumViews);
3612     stream.writeInt(mState.mSpecConstUsageBits.bits());
3613 
3614     stream.writeInt(mState.getUniformLocations().size());
3615     for (const auto &variable : mState.getUniformLocations())
3616     {
3617         stream.writeInt(variable.arrayIndex);
3618         stream.writeIntOrNegOne(variable.index);
3619         stream.writeBool(variable.ignored);
3620     }
3621 
3622     stream.writeInt(mState.getBufferVariables().size());
3623     for (const BufferVariable &bufferVariable : mState.getBufferVariables())
3624     {
3625         WriteBufferVariable(&stream, bufferVariable);
3626     }
3627 
3628     // Warn the app layer if saving a binary with unsupported transform feedback.
3629     if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
3630         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
3631     {
3632         WARN() << "Saving program binary with transform feedback, which is not supported on this "
3633                   "driver.";
3634     }
3635 
3636     if (context->getShareGroup()->getFrameCaptureShared()->enabled())
3637     {
3638         // Serialize the source for each stage for re-use during capture
3639         for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
3640         {
3641             gl::Shader *shader = getAttachedShader(shaderType);
3642             if (shader)
3643             {
3644                 stream.writeString(shader->getSourceString());
3645             }
3646             else
3647             {
3648                 // If we don't have an attached shader, which would occur if this program was
3649                 // created via glProgramBinary, pull from our cached copy
3650                 const angle::ProgramSources &cachedLinkedSources =
3651                     context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id());
3652                 const std::string &cachedSourceString = cachedLinkedSources[shaderType];
3653                 ASSERT(!cachedSourceString.empty());
3654                 stream.writeString(cachedSourceString.c_str());
3655             }
3656         }
3657     }
3658 
3659     mProgram->save(context, &stream);
3660 
3661     ASSERT(binaryOut);
3662     if (!binaryOut->resize(stream.length()))
3663     {
3664         WARN() << "Failed to allocate enough memory to serialize a program. (" << stream.length()
3665                << " bytes )";
3666         return angle::Result::Incomplete;
3667     }
3668     memcpy(binaryOut->data(), stream.data(), stream.length());
3669     return angle::Result::Continue;
3670 }
3671 
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)3672 angle::Result Program::deserialize(const Context *context,
3673                                    BinaryInputStream &stream,
3674                                    InfoLog &infoLog)
3675 {
3676     std::vector<uint8_t> commitString(angle::GetANGLECommitHashSize(), 0);
3677     stream.readBytes(commitString.data(), commitString.size());
3678     if (memcmp(commitString.data(), angle::GetANGLECommitHash(), commitString.size()) != 0)
3679     {
3680         infoLog << "Invalid program binary version.";
3681         return angle::Result::Stop;
3682     }
3683 
3684     int majorVersion = stream.readInt<int>();
3685     int minorVersion = stream.readInt<int>();
3686     if (majorVersion != context->getClientMajorVersion() ||
3687         minorVersion != context->getClientMinorVersion())
3688     {
3689         infoLog << "Cannot load program binaries across different ES context versions.";
3690         return angle::Result::Stop;
3691     }
3692 
3693     // Must be before mExecutable->load(), since it uses the value.
3694     mState.mSeparable = stream.readBool();
3695 
3696     mState.mExecutable->load(mState.mSeparable, &stream);
3697 
3698     mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
3699     mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
3700     mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
3701 
3702     mState.mNumViews = stream.readInt<int>();
3703 
3704     static_assert(sizeof(mState.mSpecConstUsageBits.bits()) == sizeof(uint32_t));
3705     mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
3706 
3707     const size_t uniformIndexCount = stream.readInt<size_t>();
3708     ASSERT(mState.mUniformLocations.empty());
3709     for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex)
3710     {
3711         VariableLocation variable;
3712         stream.readInt(&variable.arrayIndex);
3713         stream.readInt(&variable.index);
3714         stream.readBool(&variable.ignored);
3715 
3716         mState.mUniformLocations.push_back(variable);
3717     }
3718 
3719     size_t bufferVariableCount = stream.readInt<size_t>();
3720     ASSERT(mState.mBufferVariables.empty());
3721     for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
3722     {
3723         BufferVariable bufferVariable;
3724         LoadBufferVariable(&stream, &bufferVariable);
3725         mState.mBufferVariables.push_back(bufferVariable);
3726     }
3727 
3728     static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
3729                   "Too many shader types");
3730 
3731     // Reject programs that use transform feedback varyings if the hardware cannot support them.
3732     if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
3733         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
3734     {
3735         infoLog << "Current driver does not support transform feedback in binary programs.";
3736         return angle::Result::Stop;
3737     }
3738 
3739     if (!mState.mAttachedShaders[ShaderType::Compute])
3740     {
3741         mState.mExecutable->updateTransformFeedbackStrides();
3742     }
3743 
3744     postResolveLink(context);
3745     mState.mExecutable->updateCanDrawWith();
3746 
3747     if (context->getShareGroup()->getFrameCaptureShared()->enabled())
3748     {
3749         // Extract the source for each stage from the program binary
3750         angle::ProgramSources sources;
3751 
3752         for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
3753         {
3754             std::string shaderSource = stream.readString();
3755             ASSERT(shaderSource.length() > 0);
3756             sources[shaderType] = std::move(shaderSource);
3757         }
3758 
3759         // Store it for use during mid-execution capture
3760         context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(),
3761                                                                              std::move(sources));
3762     }
3763 
3764     return angle::Result::Continue;
3765 }
3766 
postResolveLink(const gl::Context * context)3767 void Program::postResolveLink(const gl::Context *context)
3768 {
3769     mState.updateActiveSamplers();
3770     mState.mExecutable->mActiveImageShaderBits.fill({});
3771     mState.mExecutable->updateActiveImages(getExecutable());
3772 
3773     setUniformValuesFromBindingQualifiers();
3774 
3775     if (context->getExtensions().multiDrawANGLE)
3776     {
3777         mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value;
3778     }
3779 
3780     if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE)
3781     {
3782         mState.mBaseVertexLocation   = getUniformLocation("gl_BaseVertex").value;
3783         mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value;
3784     }
3785 }
3786 }  // namespace gl
3787