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