• 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/bitset_utils.h"
16 #include "common/debug.h"
17 #include "common/platform.h"
18 #include "common/string_utils.h"
19 #include "common/utilities.h"
20 #include "common/version.h"
21 #include "compiler/translator/blocklayout.h"
22 #include "libANGLE/Context.h"
23 #include "libANGLE/MemoryProgramCache.h"
24 #include "libANGLE/ProgramLinkedResources.h"
25 #include "libANGLE/ResourceManager.h"
26 #include "libANGLE/Uniform.h"
27 #include "libANGLE/VaryingPacking.h"
28 #include "libANGLE/Version.h"
29 #include "libANGLE/features.h"
30 #include "libANGLE/histogram_macros.h"
31 #include "libANGLE/queryconversions.h"
32 #include "libANGLE/renderer/GLImplFactory.h"
33 #include "libANGLE/renderer/ProgramImpl.h"
34 #include "platform/FrontendFeatures.h"
35 #include "platform/Platform.h"
36 
37 namespace gl
38 {
39 
40 namespace
41 {
42 
43 // This simplified cast function doesn't need to worry about advanced concepts like
44 // depth range values, or casting to bool.
45 template <typename DestT, typename SrcT>
46 DestT UniformStateQueryCast(SrcT value);
47 
48 // From-Float-To-Integer Casts
49 template <>
UniformStateQueryCast(GLfloat value)50 GLint UniformStateQueryCast(GLfloat value)
51 {
52     return clampCast<GLint>(roundf(value));
53 }
54 
55 template <>
UniformStateQueryCast(GLfloat value)56 GLuint UniformStateQueryCast(GLfloat value)
57 {
58     return clampCast<GLuint>(roundf(value));
59 }
60 
61 // From-Integer-to-Integer Casts
62 template <>
UniformStateQueryCast(GLuint value)63 GLint UniformStateQueryCast(GLuint value)
64 {
65     return clampCast<GLint>(value);
66 }
67 
68 template <>
UniformStateQueryCast(GLint value)69 GLuint UniformStateQueryCast(GLint value)
70 {
71     return clampCast<GLuint>(value);
72 }
73 
74 // From-Boolean-to-Anything Casts
75 template <>
UniformStateQueryCast(GLboolean value)76 GLfloat UniformStateQueryCast(GLboolean value)
77 {
78     return (ConvertToBool(value) ? 1.0f : 0.0f);
79 }
80 
81 template <>
UniformStateQueryCast(GLboolean value)82 GLint UniformStateQueryCast(GLboolean value)
83 {
84     return (ConvertToBool(value) ? 1 : 0);
85 }
86 
87 template <>
UniformStateQueryCast(GLboolean value)88 GLuint UniformStateQueryCast(GLboolean value)
89 {
90     return (ConvertToBool(value) ? 1u : 0u);
91 }
92 
93 // Default to static_cast
94 template <typename DestT, typename SrcT>
UniformStateQueryCast(SrcT value)95 DestT UniformStateQueryCast(SrcT value)
96 {
97     return static_cast<DestT>(value);
98 }
99 
100 template <typename SrcT, typename DestT>
UniformStateQueryCastLoop(DestT * dataOut,const uint8_t * srcPointer,int components)101 void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
102 {
103     for (int comp = 0; comp < components; ++comp)
104     {
105         // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
106         // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
107         size_t offset               = comp * 4;
108         const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
109         dataOut[comp]               = UniformStateQueryCast<DestT>(*typedSrcPointer);
110     }
111 }
112 
113 template <typename VarT>
GetResourceIndexFromName(const std::vector<VarT> & list,const std::string & name)114 GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
115 {
116     std::string nameAsArrayName = name + "[0]";
117     for (size_t index = 0; index < list.size(); index++)
118     {
119         const VarT &resource = list[index];
120         if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
121         {
122             return static_cast<GLuint>(index);
123         }
124     }
125 
126     return GL_INVALID_INDEX;
127 }
128 
129 template <typename VarT>
GetVariableLocation(const std::vector<VarT> & list,const std::vector<VariableLocation> & locationList,const std::string & name)130 GLint GetVariableLocation(const std::vector<VarT> &list,
131                           const std::vector<VariableLocation> &locationList,
132                           const std::string &name)
133 {
134     size_t nameLengthWithoutArrayIndex;
135     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
136 
137     for (size_t location = 0u; location < locationList.size(); ++location)
138     {
139         const VariableLocation &variableLocation = locationList[location];
140         if (!variableLocation.used())
141         {
142             continue;
143         }
144 
145         const VarT &variable = list[variableLocation.index];
146 
147         // Array output variables may be bound out of order, so we need to ensure we only pick the
148         // first element if given the base name. Uniforms don't allow this behavior and some code
149         // seemingly depends on the opposite behavior, so only enable it for output variables.
150         if (angle::BeginsWith(variable.name, name) &&
151             (!std::is_base_of<sh::OutputVariable, VarT>::value || variableLocation.arrayIndex == 0))
152         {
153             if (name.length() == variable.name.length())
154             {
155                 ASSERT(name == variable.name);
156                 // GLES 3.1 November 2016 page 87.
157                 // The string exactly matches the name of the active variable.
158                 return static_cast<GLint>(location);
159             }
160             if (name.length() + 3u == variable.name.length() && variable.isArray())
161             {
162                 ASSERT(name + "[0]" == variable.name);
163                 // The string identifies the base name of an active array, where the string would
164                 // exactly match the name of the variable if the suffix "[0]" were appended to the
165                 // string.
166                 return static_cast<GLint>(location);
167             }
168         }
169         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
170             nameLengthWithoutArrayIndex + 3u == variable.name.length() &&
171             angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
172         {
173             ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name);
174             // The string identifies an active element of the array, where the string ends with the
175             // concatenation of the "[" character, an integer (with no "+" sign, extra leading
176             // zeroes, or whitespace) identifying an array element, and the "]" character, the
177             // integer is less than the number of active elements of the array variable, and where
178             // the string would exactly match the enumerated name of the array if the decimal
179             // integer were replaced with zero.
180             return static_cast<GLint>(location);
181         }
182     }
183 
184     return -1;
185 }
186 
CopyStringToBuffer(GLchar * buffer,const std::string & string,GLsizei bufSize,GLsizei * lengthOut)187 void CopyStringToBuffer(GLchar *buffer,
188                         const std::string &string,
189                         GLsizei bufSize,
190                         GLsizei *lengthOut)
191 {
192     ASSERT(bufSize > 0);
193     size_t length = std::min<size_t>(bufSize - 1, string.length());
194     memcpy(buffer, string.c_str(), length);
195     buffer[length] = '\0';
196 
197     if (lengthOut)
198     {
199         *lengthOut = static_cast<GLsizei>(length);
200     }
201 }
202 
IncludeSameArrayElement(const std::set<std::string> & nameSet,const std::string & name)203 bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
204 {
205     std::vector<unsigned int> subscripts;
206     std::string baseName = ParseResourceName(name, &subscripts);
207     for (const std::string &nameInSet : nameSet)
208     {
209         std::vector<unsigned int> arrayIndices;
210         std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
211         if (baseName == arrayName &&
212             (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
213         {
214             return true;
215         }
216     }
217     return false;
218 }
219 
GetInterfaceBlockLimitName(ShaderType shaderType,sh::BlockType blockType)220 std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
221 {
222     std::ostringstream stream;
223     stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
224 
225     switch (blockType)
226     {
227         case sh::BlockType::BLOCK_UNIFORM:
228             stream << "UNIFORM_BUFFERS";
229             break;
230         case sh::BlockType::BLOCK_BUFFER:
231             stream << "SHADER_STORAGE_BLOCKS";
232             break;
233         default:
234             UNREACHABLE();
235             return "";
236     }
237 
238     if (shaderType == ShaderType::Geometry)
239     {
240         stream << "_EXT";
241     }
242 
243     return stream.str();
244 }
245 
GetInterfaceBlockTypeString(sh::BlockType blockType)246 const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
247 {
248     switch (blockType)
249     {
250         case sh::BlockType::BLOCK_UNIFORM:
251             return "uniform block";
252         case sh::BlockType::BLOCK_BUFFER:
253             return "shader storage block";
254         default:
255             UNREACHABLE();
256             return "";
257     }
258 }
259 
LogInterfaceBlocksExceedLimit(InfoLog & infoLog,ShaderType shaderType,sh::BlockType blockType,GLuint limit)260 void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
261                                    ShaderType shaderType,
262                                    sh::BlockType blockType,
263                                    GLuint limit)
264 {
265     infoLog << GetShaderTypeString(shaderType) << " shader "
266             << GetInterfaceBlockTypeString(blockType) << " count exceeds "
267             << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
268 }
269 
ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,sh::BlockType blockType,GLuint * combinedInterfaceBlocksCount,InfoLog & infoLog)270 bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
271                                   const std::vector<sh::InterfaceBlock> &interfaceBlocks,
272                                   ShaderType shaderType,
273                                   sh::BlockType blockType,
274                                   GLuint *combinedInterfaceBlocksCount,
275                                   InfoLog &infoLog)
276 {
277     GLuint blockCount = 0;
278     for (const sh::InterfaceBlock &block : interfaceBlocks)
279     {
280         if (IsActiveInterfaceBlock(block))
281         {
282             blockCount += std::max(block.arraySize, 1u);
283             if (blockCount > maxInterfaceBlocks)
284             {
285                 LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
286                 return false;
287             }
288         }
289     }
290 
291     // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
292     // If a uniform block is used by multiple shader stages, each such use counts separately
293     // against this combined limit.
294     // [OpenGL ES 3.1] Chapter 7.8 Page 111:
295     // If a shader storage block in a program is referenced by multiple shaders, each such
296     // reference counts separately against this combined limit.
297     if (combinedInterfaceBlocksCount)
298     {
299         *combinedInterfaceBlocksCount += blockCount;
300     }
301 
302     return true;
303 }
304 
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)305 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
306 {
307     std::vector<unsigned int> subscripts;
308     std::string baseName = ParseResourceName(name, &subscripts);
309 
310     unsigned int numBlocks = static_cast<unsigned int>(list.size());
311     for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
312     {
313         const auto &block = list[blockIndex];
314         if (block.name == baseName)
315         {
316             const bool arrayElementZero =
317                 (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
318             const bool arrayElementMatches =
319                 (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
320             if (arrayElementMatches || arrayElementZero)
321             {
322                 return blockIndex;
323             }
324         }
325     }
326 
327     return GL_INVALID_INDEX;
328 }
329 
GetInterfaceBlockName(const GLuint index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)330 void GetInterfaceBlockName(const GLuint index,
331                            const std::vector<InterfaceBlock> &list,
332                            GLsizei bufSize,
333                            GLsizei *length,
334                            GLchar *name)
335 {
336     ASSERT(index < list.size());
337 
338     const auto &block = list[index];
339 
340     if (bufSize > 0)
341     {
342         std::string blockName = block.name;
343 
344         if (block.isArray)
345         {
346             blockName += ArrayString(block.arrayElement);
347         }
348         CopyStringToBuffer(name, blockName, bufSize, length);
349     }
350 }
351 
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)352 void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
353 {
354     for (ShaderType shaderType : AllShaderTypes())
355     {
356         Shader *shader = state.getAttachedShader(shaderType);
357         if (shader)
358         {
359             blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks());
360         }
361     }
362 }
363 
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)364 void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
365 {
366     for (ShaderType shaderType : AllShaderTypes())
367     {
368         Shader *shader = state.getAttachedShader(shaderType);
369         if (shader != nullptr)
370         {
371             blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks());
372         }
373     }
374 }
375 
376 // Find the matching varying or field by name.
FindVaryingOrField(const ProgramMergedVaryings & varyings,const std::string & name)377 const sh::ShaderVariable *FindVaryingOrField(const ProgramMergedVaryings &varyings,
378                                              const std::string &name)
379 {
380     const sh::ShaderVariable *var = nullptr;
381     for (const auto &ref : varyings)
382     {
383         const sh::Varying *varying = ref.second.get();
384         if (varying->name == name)
385         {
386             var = varying;
387             break;
388         }
389         GLuint fieldIndex = 0;
390         var               = FindShaderVarField(*varying, name, &fieldIndex);
391         if (var != nullptr)
392         {
393             break;
394         }
395     }
396     return var;
397 }
398 
AddParentPrefix(const std::string & parentName,std::string * mismatchedFieldName)399 void AddParentPrefix(const std::string &parentName, std::string *mismatchedFieldName)
400 {
401     ASSERT(mismatchedFieldName);
402     if (mismatchedFieldName->empty())
403     {
404         *mismatchedFieldName = parentName;
405     }
406     else
407     {
408         std::ostringstream stream;
409         stream << parentName << "." << *mismatchedFieldName;
410         *mismatchedFieldName = stream.str();
411     }
412 }
413 
GetLinkMismatchErrorString(LinkMismatchError linkError)414 const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
415 {
416     switch (linkError)
417     {
418         case LinkMismatchError::TYPE_MISMATCH:
419             return "Type";
420         case LinkMismatchError::ARRAY_SIZE_MISMATCH:
421             return "Array size";
422         case LinkMismatchError::PRECISION_MISMATCH:
423             return "Precision";
424         case LinkMismatchError::STRUCT_NAME_MISMATCH:
425             return "Structure name";
426         case LinkMismatchError::FIELD_NUMBER_MISMATCH:
427             return "Field number";
428         case LinkMismatchError::FIELD_NAME_MISMATCH:
429             return "Field name";
430 
431         case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
432             return "Interpolation type";
433         case LinkMismatchError::INVARIANCE_MISMATCH:
434             return "Invariance";
435 
436         case LinkMismatchError::BINDING_MISMATCH:
437             return "Binding layout qualifier";
438         case LinkMismatchError::LOCATION_MISMATCH:
439             return "Location layout qualifier";
440         case LinkMismatchError::OFFSET_MISMATCH:
441             return "Offset layout qualifier";
442         case LinkMismatchError::INSTANCE_NAME_MISMATCH:
443             return "Instance name qualifier";
444 
445         case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
446             return "Layout qualifier";
447         case LinkMismatchError::MATRIX_PACKING_MISMATCH:
448             return "Matrix Packing";
449         default:
450             UNREACHABLE();
451             return "";
452     }
453 }
454 
LinkValidateInterfaceBlockFields(const sh::InterfaceBlockField & blockField1,const sh::InterfaceBlockField & blockField2,bool webglCompatibility,std::string * mismatchedBlockFieldName)455 LinkMismatchError LinkValidateInterfaceBlockFields(const sh::InterfaceBlockField &blockField1,
456                                                    const sh::InterfaceBlockField &blockField2,
457                                                    bool webglCompatibility,
458                                                    std::string *mismatchedBlockFieldName)
459 {
460     if (blockField1.name != blockField2.name)
461     {
462         return LinkMismatchError::FIELD_NAME_MISMATCH;
463     }
464 
465     // If webgl, validate precision of UBO fields, otherwise don't.  See Khronos bug 10287.
466     LinkMismatchError linkError = Program::LinkValidateVariablesBase(
467         blockField1, blockField2, webglCompatibility, true, mismatchedBlockFieldName);
468     if (linkError != LinkMismatchError::NO_MISMATCH)
469     {
470         AddParentPrefix(blockField1.name, mismatchedBlockFieldName);
471         return linkError;
472     }
473 
474     if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout)
475     {
476         AddParentPrefix(blockField1.name, mismatchedBlockFieldName);
477         return LinkMismatchError::MATRIX_PACKING_MISMATCH;
478     }
479 
480     return LinkMismatchError::NO_MISMATCH;
481 }
482 
AreMatchingInterfaceBlocks(const sh::InterfaceBlock & interfaceBlock1,const sh::InterfaceBlock & interfaceBlock2,bool webglCompatibility,std::string * mismatchedBlockFieldName)483 LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1,
484                                              const sh::InterfaceBlock &interfaceBlock2,
485                                              bool webglCompatibility,
486                                              std::string *mismatchedBlockFieldName)
487 {
488     // validate blocks for the same member types
489     if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size())
490     {
491         return LinkMismatchError::FIELD_NUMBER_MISMATCH;
492     }
493     if (interfaceBlock1.arraySize != interfaceBlock2.arraySize)
494     {
495         return LinkMismatchError::ARRAY_SIZE_MISMATCH;
496     }
497     if (interfaceBlock1.layout != interfaceBlock2.layout ||
498         interfaceBlock1.binding != interfaceBlock2.binding)
499     {
500         return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH;
501     }
502     if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty())
503     {
504         return LinkMismatchError::INSTANCE_NAME_MISMATCH;
505     }
506     const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size());
507     for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
508     {
509         const sh::InterfaceBlockField &member1 = interfaceBlock1.fields[blockMemberIndex];
510         const sh::InterfaceBlockField &member2 = interfaceBlock2.fields[blockMemberIndex];
511 
512         LinkMismatchError linkError = LinkValidateInterfaceBlockFields(
513             member1, member2, webglCompatibility, mismatchedBlockFieldName);
514         if (linkError != LinkMismatchError::NO_MISMATCH)
515         {
516             return linkError;
517         }
518     }
519     return LinkMismatchError::NO_MISMATCH;
520 }
521 
522 using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>;
523 using InterfaceBlockMap    = std::map<std::string, ShaderInterfaceBlock>;
524 
InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * linkedInterfaceBlocks)525 void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
526                                  ShaderType shaderType,
527                                  InterfaceBlockMap *linkedInterfaceBlocks)
528 {
529     ASSERT(linkedInterfaceBlocks);
530 
531     for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
532     {
533         (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
534     }
535 }
536 
ValidateGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocksToLink,ShaderType shaderType,bool webglCompatibility,InterfaceBlockMap * linkedBlocks,InfoLog & infoLog)537 bool ValidateGraphicsInterfaceBlocksPerShader(
538     const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
539     ShaderType shaderType,
540     bool webglCompatibility,
541     InterfaceBlockMap *linkedBlocks,
542     InfoLog &infoLog)
543 {
544     ASSERT(linkedBlocks);
545 
546     for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
547     {
548         const auto &entry = linkedBlocks->find(block.name);
549         if (entry != linkedBlocks->end())
550         {
551             const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
552             std::string mismatchedStructFieldName;
553             LinkMismatchError linkError = AreMatchingInterfaceBlocks(
554                 block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
555             if (linkError != LinkMismatchError::NO_MISMATCH)
556             {
557                 LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
558                                 linkError, mismatchedStructFieldName, entry->second.first,
559                                 shaderType);
560                 return false;
561             }
562         }
563         else
564         {
565             (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
566         }
567     }
568 
569     return true;
570 }
571 
ValidateInterfaceBlocksMatch(GLuint numShadersHasInterfaceBlocks,const ShaderMap<const std::vector<sh::InterfaceBlock> * > & shaderInterfaceBlocks,InfoLog & infoLog,bool webglCompatibility)572 bool ValidateInterfaceBlocksMatch(
573     GLuint numShadersHasInterfaceBlocks,
574     const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
575     InfoLog &infoLog,
576     bool webglCompatibility)
577 {
578     if (numShadersHasInterfaceBlocks < 2u)
579     {
580         return true;
581     }
582 
583     ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]);
584 
585     // Check that interface blocks defined in the graphics shaders are identical
586 
587     InterfaceBlockMap linkedInterfaceBlocks;
588 
589     bool interfaceBlockMapInitialized = false;
590     for (ShaderType shaderType : kAllGraphicsShaderTypes)
591     {
592         if (!shaderInterfaceBlocks[shaderType])
593         {
594             continue;
595         }
596 
597         if (!interfaceBlockMapInitialized)
598         {
599             InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
600                                         &linkedInterfaceBlocks);
601             interfaceBlockMapInitialized = true;
602         }
603         else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType],
604                                                            shaderType, webglCompatibility,
605                                                            &linkedInterfaceBlocks, infoLog))
606         {
607             return false;
608         }
609     }
610 
611     return true;
612 }
613 
WriteShaderVar(BinaryOutputStream * stream,const sh::ShaderVariable & var)614 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
615 {
616     stream->writeInt(var.type);
617     stream->writeInt(var.precision);
618     stream->writeString(var.name);
619     stream->writeString(var.mappedName);
620     stream->writeIntVector(var.arraySizes);
621     stream->writeInt(var.staticUse);
622     stream->writeInt(var.active);
623     stream->writeString(var.structName);
624     stream->writeInt(var.hasParentArrayIndex() ? var.parentArrayIndex() : -1);
625     ASSERT(var.fields.empty());
626 }
627 
LoadShaderVar(BinaryInputStream * stream,sh::ShaderVariable * var)628 void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
629 {
630     var->type       = stream->readInt<GLenum>();
631     var->precision  = stream->readInt<GLenum>();
632     var->name       = stream->readString();
633     var->mappedName = stream->readString();
634     stream->readIntVector<unsigned int>(&var->arraySizes);
635     var->staticUse  = stream->readBool();
636     var->active     = stream->readBool();
637     var->structName = stream->readString();
638     var->setParentArrayIndex(stream->readInt<int>());
639 }
640 
WriteShaderVariableBuffer(BinaryOutputStream * stream,const ShaderVariableBuffer & var)641 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
642 {
643     stream->writeInt(var.binding);
644     stream->writeInt(var.dataSize);
645 
646     for (ShaderType shaderType : AllShaderTypes())
647     {
648         stream->writeInt(var.isActive(shaderType));
649     }
650 
651     stream->writeInt(var.memberIndexes.size());
652     for (unsigned int memberCounterIndex : var.memberIndexes)
653     {
654         stream->writeInt(memberCounterIndex);
655     }
656 }
657 
LoadShaderVariableBuffer(BinaryInputStream * stream,ShaderVariableBuffer * var)658 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
659 {
660     var->binding  = stream->readInt<int>();
661     var->dataSize = stream->readInt<unsigned int>();
662 
663     for (ShaderType shaderType : AllShaderTypes())
664     {
665         var->setActive(shaderType, stream->readBool());
666     }
667 
668     unsigned int numMembers = stream->readInt<unsigned int>();
669     for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
670     {
671         var->memberIndexes.push_back(stream->readInt<unsigned int>());
672     }
673 }
674 
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)675 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
676 {
677     WriteShaderVar(stream, var);
678 
679     stream->writeInt(var.bufferIndex);
680     WriteBlockMemberInfo(stream, var.blockInfo);
681     stream->writeInt(var.topLevelArraySize);
682 
683     for (ShaderType shaderType : AllShaderTypes())
684     {
685         stream->writeInt(var.isActive(shaderType));
686     }
687 }
688 
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)689 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
690 {
691     LoadShaderVar(stream, var);
692 
693     var->bufferIndex = stream->readInt<int>();
694     LoadBlockMemberInfo(stream, &var->blockInfo);
695     var->topLevelArraySize = stream->readInt<int>();
696 
697     for (ShaderType shaderType : AllShaderTypes())
698     {
699         var->setActive(shaderType, stream->readBool());
700     }
701 }
702 
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)703 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
704 {
705     stream->writeString(block.name);
706     stream->writeString(block.mappedName);
707     stream->writeInt(block.isArray);
708     stream->writeInt(block.arrayElement);
709 
710     WriteShaderVariableBuffer(stream, block);
711 }
712 
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)713 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
714 {
715     block->name         = stream->readString();
716     block->mappedName   = stream->readString();
717     block->isArray      = stream->readBool();
718     block->arrayElement = stream->readInt<unsigned int>();
719 
720     LoadShaderVariableBuffer(stream, block);
721 }
722 
CountUniqueBlocks(const std::vector<InterfaceBlock> & blocks)723 size_t CountUniqueBlocks(const std::vector<InterfaceBlock> &blocks)
724 {
725     size_t count = 0;
726     for (const InterfaceBlock &block : blocks)
727     {
728         if (!block.isArray || block.arrayElement == 0)
729         {
730             ++count;
731         }
732     }
733     return count;
734 }
735 }  // anonymous namespace
736 
737 // Saves the linking context for later use in resolveLink().
738 struct Program::LinkingState
739 {
740     const Context *context;
741     std::unique_ptr<ProgramLinkedResources> resources;
742     egl::BlobCache::Key programHash;
743     std::unique_ptr<rx::LinkEvent> linkEvent;
744     bool linkingFromBinary;
745 };
746 
747 const char *const g_fakepath = "C:\\fakepath";
748 
749 // InfoLog implementation.
InfoLog()750 InfoLog::InfoLog() {}
751 
~InfoLog()752 InfoLog::~InfoLog() {}
753 
getLength() const754 size_t InfoLog::getLength() const
755 {
756     if (!mLazyStream)
757     {
758         return 0;
759     }
760 
761     const std::string &logString = mLazyStream->str();
762     return logString.empty() ? 0 : logString.length() + 1;
763 }
764 
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const765 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
766 {
767     size_t index = 0;
768 
769     if (bufSize > 0)
770     {
771         const std::string logString(str());
772 
773         if (!logString.empty())
774         {
775             index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
776             memcpy(infoLog, logString.c_str(), index);
777         }
778 
779         infoLog[index] = '\0';
780     }
781 
782     if (length)
783     {
784         *length = static_cast<GLsizei>(index);
785     }
786 }
787 
788 // append a santized message to the program info log.
789 // The D3D compiler includes a fake file path in some of the warning or error
790 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)791 void InfoLog::appendSanitized(const char *message)
792 {
793     ensureInitialized();
794 
795     std::string msg(message);
796 
797     size_t found;
798     do
799     {
800         found = msg.find(g_fakepath);
801         if (found != std::string::npos)
802         {
803             msg.erase(found, strlen(g_fakepath));
804         }
805     } while (found != std::string::npos);
806 
807     *mLazyStream << message << std::endl;
808 }
809 
reset()810 void InfoLog::reset()
811 {
812     if (mLazyStream)
813     {
814         mLazyStream.reset(nullptr);
815     }
816 }
817 
empty() const818 bool InfoLog::empty() const
819 {
820     if (!mLazyStream)
821     {
822         return true;
823     }
824 
825     return mLazyStream->rdbuf()->in_avail() == 0;
826 }
827 
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)828 void LogLinkMismatch(InfoLog &infoLog,
829                      const std::string &variableName,
830                      const char *variableType,
831                      LinkMismatchError linkError,
832                      const std::string &mismatchedStructOrBlockFieldName,
833                      ShaderType shaderType1,
834                      ShaderType shaderType2)
835 {
836     std::ostringstream stream;
837     stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
838            << variableName;
839 
840     if (!mismatchedStructOrBlockFieldName.empty())
841     {
842         stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
843     }
844 
845     stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
846            << GetShaderTypeString(shaderType2) << " shaders.";
847 
848     infoLog << stream.str();
849 }
850 
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)851 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
852 {
853     // Only 'packed' blocks are allowed to be considered inactive.
854     return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
855 }
856 
WriteBlockMemberInfo(BinaryOutputStream * stream,const sh::BlockMemberInfo & var)857 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var)
858 {
859     stream->writeInt(var.arrayStride);
860     stream->writeInt(var.isRowMajorMatrix);
861     stream->writeInt(var.matrixStride);
862     stream->writeInt(var.offset);
863     stream->writeInt(var.topLevelArrayStride);
864 }
865 
LoadBlockMemberInfo(BinaryInputStream * stream,sh::BlockMemberInfo * var)866 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
867 {
868     var->arrayStride         = stream->readInt<int>();
869     var->isRowMajorMatrix    = stream->readBool();
870     var->matrixStride        = stream->readInt<int>();
871     var->offset              = stream->readInt<int>();
872     var->topLevelArrayStride = stream->readInt<int>();
873 }
874 
875 // VariableLocation implementation.
VariableLocation()876 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
877 
VariableLocation(unsigned int arrayIndex,unsigned int index)878 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
879     : arrayIndex(arrayIndex), index(index), ignored(false)
880 {
881     ASSERT(arrayIndex != GL_INVALID_INDEX);
882 }
883 
884 // SamplerBindings implementation.
SamplerBinding(TextureType textureTypeIn,SamplerFormat formatIn,size_t elementCount,bool unreferenced)885 SamplerBinding::SamplerBinding(TextureType textureTypeIn,
886                                SamplerFormat formatIn,
887                                size_t elementCount,
888                                bool unreferenced)
889     : textureType(textureTypeIn),
890       format(formatIn),
891       boundTextureUnits(elementCount, 0),
892       unreferenced(unreferenced)
893 {}
894 
895 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
896 
897 SamplerBinding::~SamplerBinding() = default;
898 
899 // ProgramBindings implementation.
ProgramBindings()900 ProgramBindings::ProgramBindings() {}
901 
~ProgramBindings()902 ProgramBindings::~ProgramBindings() {}
903 
bindLocation(GLuint index,const std::string & name)904 void ProgramBindings::bindLocation(GLuint index, const std::string &name)
905 {
906     mBindings[name] = ProgramBinding(index);
907 
908     // EXT_blend_func_extended spec: "If it specifies the base name of an array,
909     // it identifies the resources associated with the first element of the array."
910     //
911     // Normalize array bindings so that "name" and "name[0]" map to the same entry.
912     // If this binding is of the form "name[0]", then mark the "name" binding as
913     // aliased but do not update it yet in case "name" is not actually an array.
914     size_t nameLengthWithoutArrayIndex;
915     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
916     if (arrayIndex == 0)
917     {
918         std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
919         auto iter            = mBindings.find(baseName);
920         if (iter != mBindings.end())
921         {
922             iter->second.aliased = true;
923         }
924     }
925 }
926 
getBindingByName(const std::string & name) const927 int ProgramBindings::getBindingByName(const std::string &name) const
928 {
929     auto iter = mBindings.find(name);
930     return (iter != mBindings.end()) ? iter->second.location : -1;
931 }
932 
getBinding(const sh::VariableWithLocation & variable) const933 int ProgramBindings::getBinding(const sh::VariableWithLocation &variable) const
934 {
935     const std::string &name = variable.name;
936 
937     // Check with the normalized array name if applicable.
938     if (variable.isArray())
939     {
940         size_t nameLengthWithoutArrayIndex;
941         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
942         if (arrayIndex == 0)
943         {
944             std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
945             auto iter            = mBindings.find(baseName);
946             // If "name" exists and is not aliased, that means it was modified more
947             // recently than its "name[0]" form and should be used instead of that.
948             if (iter != mBindings.end() && !iter->second.aliased)
949             {
950                 return iter->second.location;
951             }
952         }
953     }
954 
955     return getBindingByName(name);
956 }
957 
begin() const958 ProgramBindings::const_iterator ProgramBindings::begin() const
959 {
960     return mBindings.begin();
961 }
962 
end() const963 ProgramBindings::const_iterator ProgramBindings::end() const
964 {
965     return mBindings.end();
966 }
967 
968 // ImageBinding implementation.
ImageBinding(size_t count)969 ImageBinding::ImageBinding(size_t count) : boundImageUnits(count, 0), unreferenced(false) {}
ImageBinding(GLuint imageUnit,size_t count,bool unreferenced)970 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, bool unreferenced)
971     : unreferenced(unreferenced)
972 {
973     for (size_t index = 0; index < count; ++index)
974     {
975         boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
976     }
977 }
978 
979 ImageBinding::ImageBinding(const ImageBinding &other) = default;
980 
981 ImageBinding::~ImageBinding() = default;
982 
983 // ProgramState implementation.
ProgramState()984 ProgramState::ProgramState()
985     : mLabel(),
986       mAttachedShaders{},
987       mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
988       mMaxActiveAttribLocation(0),
989       mSamplerUniformRange(0, 0),
990       mImageUniformRange(0, 0),
991       mAtomicCounterUniformRange(0, 0),
992       mBinaryRetrieveableHint(false),
993       mNumViews(-1),
994       // [GL_EXT_geometry_shader] Table 20.22
995       mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
996       mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
997       mGeometryShaderInvocations(1),
998       mGeometryShaderMaxVertices(0),
999       mDrawIDLocation(-1),
1000       mBaseVertexLocation(-1),
1001       mBaseInstanceLocation(-1),
1002       mActiveSamplerRefCounts{}
1003 {
1004     mComputeShaderLocalSize.fill(1);
1005     mActiveSamplerTypes.fill(TextureType::InvalidEnum);
1006 }
1007 
~ProgramState()1008 ProgramState::~ProgramState()
1009 {
1010     ASSERT(!hasAttachedShader());
1011 }
1012 
getLabel()1013 const std::string &ProgramState::getLabel()
1014 {
1015     return mLabel;
1016 }
1017 
getAttachedShader(ShaderType shaderType) const1018 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
1019 {
1020     ASSERT(shaderType != ShaderType::InvalidEnum);
1021     return mAttachedShaders[shaderType];
1022 }
1023 
getUniqueUniformBlockCount() const1024 size_t ProgramState::getUniqueUniformBlockCount() const
1025 {
1026     return CountUniqueBlocks(mUniformBlocks);
1027 }
1028 
getUniqueStorageBlockCount() const1029 size_t ProgramState::getUniqueStorageBlockCount() const
1030 {
1031     return CountUniqueBlocks(mShaderStorageBlocks);
1032 }
1033 
getUniformIndexFromName(const std::string & name) const1034 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
1035 {
1036     return GetResourceIndexFromName(mUniforms, name);
1037 }
1038 
getBufferVariableIndexFromName(const std::string & name) const1039 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
1040 {
1041     return GetResourceIndexFromName(mBufferVariables, name);
1042 }
1043 
getUniformIndexFromLocation(GLint location) const1044 GLuint ProgramState::getUniformIndexFromLocation(GLint location) const
1045 {
1046     ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformLocations.size());
1047     return mUniformLocations[location].index;
1048 }
1049 
getSamplerIndex(GLint location) const1050 Optional<GLuint> ProgramState::getSamplerIndex(GLint location) const
1051 {
1052     GLuint index = getUniformIndexFromLocation(location);
1053     if (!isSamplerUniformIndex(index))
1054     {
1055         return Optional<GLuint>::Invalid();
1056     }
1057 
1058     return getSamplerIndexFromUniformIndex(index);
1059 }
1060 
isSamplerUniformIndex(GLuint index) const1061 bool ProgramState::isSamplerUniformIndex(GLuint index) const
1062 {
1063     return mSamplerUniformRange.contains(index);
1064 }
1065 
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const1066 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
1067 {
1068     ASSERT(isSamplerUniformIndex(uniformIndex));
1069     return uniformIndex - mSamplerUniformRange.low();
1070 }
1071 
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const1072 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
1073 {
1074     ASSERT(samplerIndex < mSamplerUniformRange.length());
1075     return samplerIndex + mSamplerUniformRange.low();
1076 }
1077 
isImageUniformIndex(GLuint index) const1078 bool ProgramState::isImageUniformIndex(GLuint index) const
1079 {
1080     return mImageUniformRange.contains(index);
1081 }
1082 
getImageIndexFromUniformIndex(GLuint uniformIndex) const1083 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
1084 {
1085     ASSERT(isImageUniformIndex(uniformIndex));
1086     return uniformIndex - mImageUniformRange.low();
1087 }
1088 
getUniformIndexFromImageIndex(GLuint imageIndex) const1089 GLuint ProgramState::getUniformIndexFromImageIndex(GLuint imageIndex) const
1090 {
1091     ASSERT(imageIndex < mImageUniformRange.length());
1092     return imageIndex + mImageUniformRange.low();
1093 }
1094 
getAttributeLocation(const std::string & name) const1095 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1096 {
1097     for (const sh::Attribute &attribute : mAttributes)
1098     {
1099         if (attribute.name == name)
1100         {
1101             return attribute.location;
1102         }
1103     }
1104 
1105     return static_cast<GLuint>(-1);
1106 }
1107 
hasAttachedShader() const1108 bool ProgramState::hasAttachedShader() const
1109 {
1110     for (const Shader *shader : mAttachedShaders)
1111     {
1112         if (shader)
1113         {
1114             return true;
1115         }
1116     }
1117     return false;
1118 }
1119 
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,GLuint handle)1120 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle)
1121     : mProgram(factory->createProgram(mState)),
1122       mValidated(false),
1123       mLinked(false),
1124       mLinkResolved(true),
1125       mDeleteStatus(false),
1126       mRefCount(0),
1127       mResourceManager(manager),
1128       mHandle(handle)
1129 {
1130     ASSERT(mProgram);
1131 
1132     unlink();
1133 }
1134 
~Program()1135 Program::~Program()
1136 {
1137     ASSERT(!mProgram);
1138 }
1139 
onDestroy(const Context * context)1140 void Program::onDestroy(const Context *context)
1141 {
1142     resolveLink(context);
1143     for (ShaderType shaderType : AllShaderTypes())
1144     {
1145         if (mState.mAttachedShaders[shaderType])
1146         {
1147             mState.mAttachedShaders[shaderType]->release(context);
1148             mState.mAttachedShaders[shaderType] = nullptr;
1149         }
1150     }
1151 
1152     mProgram->destroy(context);
1153 
1154     ASSERT(!mState.hasAttachedShader());
1155     SafeDelete(mProgram);
1156 
1157     delete this;
1158 }
id() const1159 GLuint Program::id() const
1160 {
1161     ASSERT(mLinkResolved);
1162     return mHandle;
1163 }
1164 
setLabel(const Context * context,const std::string & label)1165 void Program::setLabel(const Context *context, const std::string &label)
1166 {
1167     ASSERT(mLinkResolved);
1168     mState.mLabel = label;
1169 }
1170 
getLabel() const1171 const std::string &Program::getLabel() const
1172 {
1173     ASSERT(mLinkResolved);
1174     return mState.mLabel;
1175 }
1176 
attachShader(Shader * shader)1177 void Program::attachShader(Shader *shader)
1178 {
1179     ASSERT(mLinkResolved);
1180     ShaderType shaderType = shader->getType();
1181     ASSERT(shaderType != ShaderType::InvalidEnum);
1182 
1183     mState.mAttachedShaders[shaderType] = shader;
1184     mState.mAttachedShaders[shaderType]->addRef();
1185 }
1186 
detachShader(const Context * context,Shader * shader)1187 void Program::detachShader(const Context *context, Shader *shader)
1188 {
1189     ASSERT(mLinkResolved);
1190     ShaderType shaderType = shader->getType();
1191     ASSERT(shaderType != ShaderType::InvalidEnum);
1192 
1193     ASSERT(mState.mAttachedShaders[shaderType] == shader);
1194     shader->release(context);
1195     mState.mAttachedShaders[shaderType] = nullptr;
1196 }
1197 
getAttachedShadersCount() const1198 int Program::getAttachedShadersCount() const
1199 {
1200     ASSERT(mLinkResolved);
1201     int numAttachedShaders = 0;
1202     for (const Shader *shader : mState.mAttachedShaders)
1203     {
1204         if (shader)
1205         {
1206             ++numAttachedShaders;
1207         }
1208     }
1209 
1210     return numAttachedShaders;
1211 }
1212 
getAttachedShader(ShaderType shaderType) const1213 const Shader *Program::getAttachedShader(ShaderType shaderType) const
1214 {
1215     ASSERT(mLinkResolved);
1216     return mState.getAttachedShader(shaderType);
1217 }
1218 
bindAttributeLocation(GLuint index,const char * name)1219 void Program::bindAttributeLocation(GLuint index, const char *name)
1220 {
1221     ASSERT(mLinkResolved);
1222     mAttributeBindings.bindLocation(index, name);
1223 }
1224 
bindUniformLocation(GLuint index,const char * name)1225 void Program::bindUniformLocation(GLuint index, const char *name)
1226 {
1227     ASSERT(mLinkResolved);
1228     mUniformLocationBindings.bindLocation(index, name);
1229 }
1230 
bindFragmentInputLocation(GLint index,const char * name)1231 void Program::bindFragmentInputLocation(GLint index, const char *name)
1232 {
1233     ASSERT(mLinkResolved);
1234     mFragmentInputBindings.bindLocation(index, name);
1235 }
1236 
bindFragmentOutputLocation(GLuint index,const char * name)1237 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1238 {
1239     mFragmentOutputLocations.bindLocation(index, name);
1240 }
1241 
bindFragmentOutputIndex(GLuint index,const char * name)1242 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1243 {
1244     mFragmentOutputIndexes.bindLocation(index, name);
1245 }
1246 
getFragmentInputBindingInfo(GLint index) const1247 BindingInfo Program::getFragmentInputBindingInfo(GLint index) const
1248 {
1249     ASSERT(mLinkResolved);
1250     BindingInfo ret;
1251     ret.type  = GL_NONE;
1252     ret.valid = false;
1253 
1254     Shader *fragmentShader = mState.getAttachedShader(ShaderType::Fragment);
1255     ASSERT(fragmentShader);
1256 
1257     // Find the actual fragment shader varying we're interested in
1258     const std::vector<sh::Varying> &inputs = fragmentShader->getInputVaryings();
1259 
1260     for (const auto &binding : mFragmentInputBindings)
1261     {
1262         if (binding.second.location != static_cast<GLuint>(index))
1263             continue;
1264 
1265         ret.valid = true;
1266 
1267         size_t nameLengthWithoutArrayIndex;
1268         unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
1269 
1270         for (const auto &in : inputs)
1271         {
1272             if (in.name.length() == nameLengthWithoutArrayIndex &&
1273                 angle::BeginsWith(in.name, binding.first, nameLengthWithoutArrayIndex))
1274             {
1275                 if (in.isArray())
1276                 {
1277                     // The client wants to bind either "name" or "name[0]".
1278                     // GL ES 3.1 spec refers to active array names with language such as:
1279                     // "if the string identifies the base name of an active array, where the
1280                     // string would exactly match the name of the variable if the suffix "[0]"
1281                     // were appended to the string".
1282                     if (arrayIndex == GL_INVALID_INDEX)
1283                         arrayIndex = 0;
1284 
1285                     ret.name = in.mappedName + "[" + ToString(arrayIndex) + "]";
1286                 }
1287                 else
1288                 {
1289                     ret.name = in.mappedName;
1290                 }
1291                 ret.type = in.type;
1292                 return ret;
1293             }
1294         }
1295     }
1296 
1297     return ret;
1298 }
1299 
pathFragmentInputGen(GLint index,GLenum genMode,GLint components,const GLfloat * coeffs)1300 void Program::pathFragmentInputGen(GLint index,
1301                                    GLenum genMode,
1302                                    GLint components,
1303                                    const GLfloat *coeffs)
1304 {
1305     ASSERT(mLinkResolved);
1306     // If the location is -1 then the command is silently ignored
1307     if (index == -1)
1308         return;
1309 
1310     const auto &binding = getFragmentInputBindingInfo(index);
1311 
1312     // If the input doesn't exist then then the command is silently ignored
1313     // This could happen through optimization for example, the shader translator
1314     // decides that a variable is not actually being used and optimizes it away.
1315     if (binding.name.empty())
1316         return;
1317 
1318     mProgram->setPathFragmentInputGen(binding.name, genMode, components, coeffs);
1319 }
1320 
1321 // The attached shaders are checked for linking errors by matching up their variables.
1322 // Uniform, input and output variables get collected.
1323 // The code gets compiled into binaries.
link(const Context * context)1324 angle::Result Program::link(const Context *context)
1325 {
1326     ASSERT(mLinkResolved);
1327     const auto &data = context->getState();
1328 
1329     auto *platform   = ANGLEPlatformCurrent();
1330     double startTime = platform->currentTime(platform);
1331 
1332     unlink();
1333     mInfoLog.reset();
1334 
1335     // Validate we have properly attached shaders before checking the cache.
1336     if (!linkValidateShaders(mInfoLog))
1337     {
1338         return angle::Result::Continue;
1339     }
1340 
1341     egl::BlobCache::Key programHash = {0};
1342     MemoryProgramCache *cache       = context->getMemoryProgramCache();
1343 
1344     if (cache)
1345     {
1346         angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1347         ANGLE_TRY(cacheResult);
1348 
1349         // Check explicitly for Continue, Incomplete means a cache miss
1350         if (cacheResult == angle::Result::Continue)
1351         {
1352             // Succeeded in loading the binaries in the front-end, back end may still be loading
1353             // asynchronously
1354             double delta = platform->currentTime(platform) - startTime;
1355             int us       = static_cast<int>(delta * 1000000.0);
1356             ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1357             return angle::Result::Continue;
1358         }
1359     }
1360 
1361     // Cache load failed, fall through to normal linking.
1362     unlink();
1363 
1364     // Re-link shaders after the unlink call.
1365     ASSERT(linkValidateShaders(mInfoLog));
1366 
1367     std::unique_ptr<ProgramLinkedResources> resources;
1368     if (mState.mAttachedShaders[ShaderType::Compute])
1369     {
1370         resources.reset(new ProgramLinkedResources(
1371             0, PackMode::ANGLE_RELAXED, &mState.mUniformBlocks, &mState.mUniforms,
1372             &mState.mShaderStorageBlocks, &mState.mBufferVariables, &mState.mAtomicCounterBuffers));
1373 
1374         GLuint combinedImageUniforms = 0u;
1375         if (!linkUniforms(context->getCaps(), mInfoLog, mUniformLocationBindings,
1376                           &combinedImageUniforms, &resources->unusedUniforms))
1377         {
1378             return angle::Result::Continue;
1379         }
1380 
1381         GLuint combinedShaderStorageBlocks = 0u;
1382         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1383                                  context->getExtensions().webglCompatibility, mInfoLog,
1384                                  &combinedShaderStorageBlocks))
1385         {
1386             return angle::Result::Continue;
1387         }
1388 
1389         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1390         // A link error will be generated if the sum of the number of active image uniforms used in
1391         // all shaders, the number of active shader storage blocks, and the number of active
1392         // fragment shader outputs exceeds the implementation-dependent value of
1393         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1394         if (combinedImageUniforms + combinedShaderStorageBlocks >
1395             context->getCaps().maxCombinedShaderOutputResources)
1396         {
1397             mInfoLog
1398                 << "The sum of the number of active image uniforms, active shader storage blocks "
1399                    "and active fragment shader outputs exceeds "
1400                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1401                 << context->getCaps().maxCombinedShaderOutputResources << ")";
1402             return angle::Result::Continue;
1403         }
1404 
1405         InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
1406         InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
1407     }
1408     else
1409     {
1410         // Map the varyings to the register file
1411         // In WebGL, we use a slightly different handling for packing variables.
1412         gl::PackMode packMode = PackMode::ANGLE_RELAXED;
1413         if (data.getLimitations().noFlexibleVaryingPacking)
1414         {
1415             // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
1416             packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
1417         }
1418         else if (data.getExtensions().webglCompatibility)
1419         {
1420             packMode = PackMode::WEBGL_STRICT;
1421         }
1422 
1423         resources.reset(new ProgramLinkedResources(
1424             data.getCaps().maxVaryingVectors, packMode, &mState.mUniformBlocks, &mState.mUniforms,
1425             &mState.mShaderStorageBlocks, &mState.mBufferVariables, &mState.mAtomicCounterBuffers));
1426 
1427         if (!linkAttributes(context, mInfoLog))
1428         {
1429             return angle::Result::Continue;
1430         }
1431 
1432         if (!linkVaryings(mInfoLog))
1433         {
1434             return angle::Result::Continue;
1435         }
1436 
1437         GLuint combinedImageUniforms = 0u;
1438         if (!linkUniforms(context->getCaps(), mInfoLog, mUniformLocationBindings,
1439                           &combinedImageUniforms, &resources->unusedUniforms))
1440         {
1441             return angle::Result::Continue;
1442         }
1443 
1444         GLuint combinedShaderStorageBlocks = 0u;
1445         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1446                                  context->getExtensions().webglCompatibility, mInfoLog,
1447                                  &combinedShaderStorageBlocks))
1448         {
1449             return angle::Result::Continue;
1450         }
1451 
1452         if (!linkValidateGlobalNames(mInfoLog))
1453         {
1454             return angle::Result::Continue;
1455         }
1456 
1457         if (!linkOutputVariables(context->getCaps(), context->getExtensions(),
1458                                  context->getClientVersion(), combinedImageUniforms,
1459                                  combinedShaderStorageBlocks))
1460         {
1461             return angle::Result::Continue;
1462         }
1463 
1464         const auto &mergedVaryings = getMergedVaryings();
1465 
1466         ASSERT(mState.mAttachedShaders[ShaderType::Vertex]);
1467         mState.mNumViews = mState.mAttachedShaders[ShaderType::Vertex]->getNumViews();
1468 
1469         InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
1470         InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
1471 
1472         if (!linkValidateTransformFeedback(context->getClientVersion(), mInfoLog, mergedVaryings,
1473                                            context->getCaps()))
1474         {
1475             return angle::Result::Continue;
1476         }
1477 
1478         if (!resources->varyingPacking.collectAndPackUserVaryings(
1479                 mInfoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames()))
1480         {
1481             return angle::Result::Continue;
1482         }
1483 
1484         gatherTransformFeedbackVaryings(mergedVaryings);
1485         mState.updateTransformFeedbackStrides();
1486     }
1487 
1488     updateLinkedShaderStages();
1489 
1490     mLinkingState.reset(new LinkingState());
1491     mLinkingState->context           = context;
1492     mLinkingState->linkingFromBinary = false;
1493     mLinkingState->programHash       = programHash;
1494     mLinkingState->linkEvent         = mProgram->link(context, *resources, mInfoLog);
1495     mLinkingState->resources         = std::move(resources);
1496     mLinkResolved                    = false;
1497 
1498     return angle::Result::Continue;
1499 }
1500 
isLinking() const1501 bool Program::isLinking() const
1502 {
1503     return (mLinkingState.get() && mLinkingState->linkEvent->isLinking());
1504 }
1505 
resolveLinkImpl(const Context * context)1506 void Program::resolveLinkImpl(const Context *context)
1507 {
1508     ASSERT(mLinkingState.get());
1509 
1510     angle::Result result = mLinkingState->linkEvent->wait(context);
1511 
1512     mLinked                                    = result == angle::Result::Continue;
1513     mLinkResolved                              = true;
1514     std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1515     if (!mLinked)
1516     {
1517         return;
1518     }
1519 
1520     if (linkingState->linkingFromBinary)
1521     {
1522         // All internal Program state is already loaded from the binary.
1523         return;
1524     }
1525 
1526     initInterfaceBlockBindings();
1527 
1528     // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1529     // Only successfully linked program can replace the executables.
1530     ASSERT(mLinked);
1531 
1532     // Mark implementation-specific unreferenced uniforms as ignored.
1533     mProgram->markUnusedUniformLocations(&mState.mUniformLocations, &mState.mSamplerBindings,
1534                                          &mState.mImageBindings);
1535 
1536     // Must be called after markUnusedUniformLocations.
1537     postResolveLink(context);
1538 
1539     // TODO(syoussefi): this might need to be moved to postResolveLink() so it will be called from
1540     // deserialize() as well.  http://anglebug.com/3089
1541     setUniformValuesFromBindingQualifiers();
1542 
1543     // Save to the program cache.
1544     auto *cache = linkingState->context->getMemoryProgramCache();
1545     if (cache && (mState.mLinkedTransformFeedbackVaryings.empty() ||
1546                   !linkingState->context->getFrontendFeatures()
1547                        .disableProgramCachingForTransformFeedback.enabled))
1548     {
1549         cache->putProgram(linkingState->programHash, linkingState->context, this);
1550     }
1551 }
1552 
updateLinkedShaderStages()1553 void Program::updateLinkedShaderStages()
1554 {
1555     mState.mLinkedShaderStages.reset();
1556 
1557     for (const Shader *shader : mState.mAttachedShaders)
1558     {
1559         if (shader)
1560         {
1561             mState.mLinkedShaderStages.set(shader->getType());
1562         }
1563     }
1564 }
1565 
updateTransformFeedbackStrides()1566 void ProgramState::updateTransformFeedbackStrides()
1567 {
1568     if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
1569     {
1570         mTransformFeedbackStrides.resize(1);
1571         size_t totalSize = 0;
1572         for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
1573         {
1574             totalSize += varying.size() * VariableExternalSize(varying.type);
1575         }
1576         mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
1577     }
1578     else
1579     {
1580         mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
1581         for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
1582         {
1583             TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
1584             mTransformFeedbackStrides[i] =
1585                 static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
1586         }
1587     }
1588 }
1589 
updateActiveSamplers()1590 void ProgramState::updateActiveSamplers()
1591 {
1592     mActiveSamplerRefCounts.fill(0);
1593 
1594     for (SamplerBinding &samplerBinding : mSamplerBindings)
1595     {
1596         if (samplerBinding.unreferenced)
1597             continue;
1598 
1599         for (GLint textureUnit : samplerBinding.boundTextureUnits)
1600         {
1601             if (++mActiveSamplerRefCounts[textureUnit] == 1)
1602             {
1603                 mActiveSamplerTypes[textureUnit]   = samplerBinding.textureType;
1604                 mActiveSamplerFormats[textureUnit] = samplerBinding.format;
1605             }
1606             else
1607             {
1608                 if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
1609                 {
1610                     mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
1611                 }
1612                 if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
1613                 {
1614                     mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
1615                 }
1616             }
1617             mActiveSamplersMask.set(textureUnit);
1618         }
1619     }
1620 }
1621 
updateActiveImages()1622 void ProgramState::updateActiveImages()
1623 {
1624     for (ImageBinding &imageBinding : mImageBindings)
1625     {
1626         if (imageBinding.unreferenced)
1627             continue;
1628 
1629         for (GLint imageUnit : imageBinding.boundImageUnits)
1630         {
1631             mActiveImagesMask.set(imageUnit);
1632         }
1633     }
1634 }
1635 
1636 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1637 void Program::unlink()
1638 {
1639     mState.mAttributes.clear();
1640     mState.mAttributesTypeMask.reset();
1641     mState.mAttributesMask.reset();
1642     mState.mActiveAttribLocationsMask.reset();
1643     mState.mMaxActiveAttribLocation = 0;
1644     mState.mLinkedTransformFeedbackVaryings.clear();
1645     mState.mUniforms.clear();
1646     mState.mUniformLocations.clear();
1647     mState.mUniformBlocks.clear();
1648     mState.mActiveUniformBlockBindings.reset();
1649     mState.mAtomicCounterBuffers.clear();
1650     mState.mOutputVariables.clear();
1651     mState.mOutputLocations.clear();
1652     mState.mSecondaryOutputLocations.clear();
1653     mState.mOutputVariableTypes.clear();
1654     mState.mDrawBufferTypeMask.reset();
1655     mState.mActiveOutputVariables.reset();
1656     mState.mComputeShaderLocalSize.fill(1);
1657     mState.mSamplerBindings.clear();
1658     mState.mImageBindings.clear();
1659     mState.mActiveImagesMask.reset();
1660     mState.mNumViews                          = -1;
1661     mState.mGeometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
1662     mState.mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
1663     mState.mGeometryShaderInvocations         = 1;
1664     mState.mGeometryShaderMaxVertices         = 0;
1665     mState.mDrawIDLocation                    = -1;
1666     mState.mBaseVertexLocation                = -1;
1667     mState.mBaseInstanceLocation              = -1;
1668 
1669     mValidated = false;
1670 
1671     mLinked = false;
1672     mInfoLog.reset();
1673 }
1674 
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1675 angle::Result Program::loadBinary(const Context *context,
1676                                   GLenum binaryFormat,
1677                                   const void *binary,
1678                                   GLsizei length)
1679 {
1680     ASSERT(mLinkResolved);
1681     unlink();
1682 
1683 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1684     return angle::Result::Continue;
1685 #else
1686     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1687     if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1688     {
1689         mInfoLog << "Invalid program binary format.";
1690         return angle::Result::Continue;
1691     }
1692 
1693     BinaryInputStream stream(binary, length);
1694     ANGLE_TRY(deserialize(context, stream, mInfoLog));
1695 
1696     // Currently we require the full shader text to compute the program hash.
1697     // We could also store the binary in the internal program cache.
1698 
1699     for (size_t uniformBlockIndex = 0; uniformBlockIndex < mState.mUniformBlocks.size();
1700          ++uniformBlockIndex)
1701     {
1702         mDirtyBits.set(uniformBlockIndex);
1703     }
1704 
1705     mLinkingState.reset(new LinkingState());
1706     mLinkingState->context           = context;
1707     mLinkingState->linkingFromBinary = true;
1708     mLinkingState->linkEvent         = mProgram->load(context, &stream, mInfoLog);
1709     mLinkResolved                    = false;
1710 
1711     return angle::Result::Continue;
1712 #endif  // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1713 }
1714 
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1715 angle::Result Program::saveBinary(Context *context,
1716                                   GLenum *binaryFormat,
1717                                   void *binary,
1718                                   GLsizei bufSize,
1719                                   GLsizei *length) const
1720 {
1721     ASSERT(mLinkResolved);
1722     if (binaryFormat)
1723     {
1724         *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1725     }
1726 
1727     angle::MemoryBuffer memoryBuf;
1728     serialize(context, &memoryBuf);
1729 
1730     GLsizei streamLength       = static_cast<GLsizei>(memoryBuf.size());
1731     const uint8_t *streamState = memoryBuf.data();
1732 
1733     if (streamLength > bufSize)
1734     {
1735         if (length)
1736         {
1737             *length = 0;
1738         }
1739 
1740         // TODO: This should be moved to the validation layer but computing the size of the binary
1741         // before saving it causes the save to happen twice.  It may be possible to write the binary
1742         // to a separate buffer, validate sizes and then copy it.
1743         ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1744     }
1745 
1746     if (binary)
1747     {
1748         char *ptr = reinterpret_cast<char *>(binary);
1749 
1750         memcpy(ptr, streamState, streamLength);
1751         ptr += streamLength;
1752 
1753         ASSERT(ptr - streamLength == binary);
1754     }
1755 
1756     if (length)
1757     {
1758         *length = streamLength;
1759     }
1760 
1761     return angle::Result::Continue;
1762 }
1763 
getBinaryLength(Context * context) const1764 GLint Program::getBinaryLength(Context *context) const
1765 {
1766     ASSERT(mLinkResolved);
1767     if (!mLinked)
1768     {
1769         return 0;
1770     }
1771 
1772     GLint length;
1773     angle::Result result =
1774         saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1775     if (result != angle::Result::Continue)
1776     {
1777         return 0;
1778     }
1779 
1780     return length;
1781 }
1782 
setBinaryRetrievableHint(bool retrievable)1783 void Program::setBinaryRetrievableHint(bool retrievable)
1784 {
1785     ASSERT(mLinkResolved);
1786     // TODO(jmadill) : replace with dirty bits
1787     mProgram->setBinaryRetrievableHint(retrievable);
1788     mState.mBinaryRetrieveableHint = retrievable;
1789 }
1790 
getBinaryRetrievableHint() const1791 bool Program::getBinaryRetrievableHint() const
1792 {
1793     ASSERT(mLinkResolved);
1794     return mState.mBinaryRetrieveableHint;
1795 }
1796 
setSeparable(bool separable)1797 void Program::setSeparable(bool separable)
1798 {
1799     ASSERT(mLinkResolved);
1800     // TODO(yunchao) : replace with dirty bits
1801     if (mState.mSeparable != separable)
1802     {
1803         mProgram->setSeparable(separable);
1804         mState.mSeparable = separable;
1805     }
1806 }
1807 
isSeparable() const1808 bool Program::isSeparable() const
1809 {
1810     ASSERT(mLinkResolved);
1811     return mState.mSeparable;
1812 }
1813 
deleteSelf(const Context * context)1814 void Program::deleteSelf(const Context *context)
1815 {
1816     ASSERT(mRefCount == 0 && mDeleteStatus);
1817     mResourceManager->deleteProgram(context, mHandle);
1818 }
1819 
getRefCount() const1820 unsigned int Program::getRefCount() const
1821 {
1822     return mRefCount;
1823 }
1824 
getInfoLogLength() const1825 int Program::getInfoLogLength() const
1826 {
1827     ASSERT(mLinkResolved);
1828     return static_cast<int>(mInfoLog.getLength());
1829 }
1830 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const1831 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
1832 {
1833     ASSERT(mLinkResolved);
1834     return mInfoLog.getLog(bufSize, length, infoLog);
1835 }
1836 
getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders) const1837 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const
1838 {
1839     ASSERT(mLinkResolved);
1840     int total = 0;
1841 
1842     for (const Shader *shader : mState.mAttachedShaders)
1843     {
1844         if (shader && (total < maxCount))
1845         {
1846             shaders[total] = shader->getHandle();
1847             ++total;
1848         }
1849     }
1850 
1851     if (count)
1852     {
1853         *count = total;
1854     }
1855 }
1856 
getAttributeLocation(const std::string & name) const1857 GLuint Program::getAttributeLocation(const std::string &name) const
1858 {
1859     ASSERT(mLinkResolved);
1860     return mState.getAttributeLocation(name);
1861 }
1862 
isAttribLocationActive(size_t attribLocation) const1863 bool Program::isAttribLocationActive(size_t attribLocation) const
1864 {
1865     ASSERT(mLinkResolved);
1866     ASSERT(attribLocation < mState.mActiveAttribLocationsMask.size());
1867     return mState.mActiveAttribLocationsMask[attribLocation];
1868 }
1869 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const1870 void Program::getActiveAttribute(GLuint index,
1871                                  GLsizei bufsize,
1872                                  GLsizei *length,
1873                                  GLint *size,
1874                                  GLenum *type,
1875                                  GLchar *name) const
1876 {
1877     ASSERT(mLinkResolved);
1878     if (!mLinked)
1879     {
1880         if (bufsize > 0)
1881         {
1882             name[0] = '\0';
1883         }
1884 
1885         if (length)
1886         {
1887             *length = 0;
1888         }
1889 
1890         *type = GL_NONE;
1891         *size = 1;
1892         return;
1893     }
1894 
1895     ASSERT(index < mState.mAttributes.size());
1896     const sh::Attribute &attrib = mState.mAttributes[index];
1897 
1898     if (bufsize > 0)
1899     {
1900         CopyStringToBuffer(name, attrib.name, bufsize, length);
1901     }
1902 
1903     // Always a single 'type' instance
1904     *size = 1;
1905     *type = attrib.type;
1906 }
1907 
getActiveAttributeCount() const1908 GLint Program::getActiveAttributeCount() const
1909 {
1910     ASSERT(mLinkResolved);
1911     if (!mLinked)
1912     {
1913         return 0;
1914     }
1915 
1916     return static_cast<GLint>(mState.mAttributes.size());
1917 }
1918 
getActiveAttributeMaxLength() const1919 GLint Program::getActiveAttributeMaxLength() const
1920 {
1921     ASSERT(mLinkResolved);
1922     if (!mLinked)
1923     {
1924         return 0;
1925     }
1926 
1927     size_t maxLength = 0;
1928 
1929     for (const sh::Attribute &attrib : mState.mAttributes)
1930     {
1931         maxLength = std::max(attrib.name.length() + 1, maxLength);
1932     }
1933 
1934     return static_cast<GLint>(maxLength);
1935 }
1936 
getAttributes() const1937 const std::vector<sh::Attribute> &Program::getAttributes() const
1938 {
1939     ASSERT(mLinkResolved);
1940     return mState.mAttributes;
1941 }
1942 
getSamplerBindings() const1943 const std::vector<SamplerBinding> &Program::getSamplerBindings() const
1944 {
1945     ASSERT(mLinkResolved);
1946     return mState.mSamplerBindings;
1947 }
1948 
getComputeShaderLocalSize() const1949 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
1950 {
1951     ASSERT(mLinkResolved);
1952     return mState.mComputeShaderLocalSize;
1953 }
1954 
getGeometryShaderInputPrimitiveType() const1955 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
1956 {
1957     ASSERT(mLinkResolved);
1958     return mState.mGeometryShaderInputPrimitiveType;
1959 }
getGeometryShaderOutputPrimitiveType() const1960 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
1961 {
1962     ASSERT(mLinkResolved);
1963     return mState.mGeometryShaderOutputPrimitiveType;
1964 }
getGeometryShaderInvocations() const1965 GLint Program::getGeometryShaderInvocations() const
1966 {
1967     ASSERT(mLinkResolved);
1968     return mState.mGeometryShaderInvocations;
1969 }
getGeometryShaderMaxVertices() const1970 GLint Program::getGeometryShaderMaxVertices() const
1971 {
1972     ASSERT(mLinkResolved);
1973     return mState.mGeometryShaderMaxVertices;
1974 }
1975 
getInputResourceIndex(const GLchar * name) const1976 GLuint Program::getInputResourceIndex(const GLchar *name) const
1977 {
1978     ASSERT(mLinkResolved);
1979     return GetResourceIndexFromName(mState.mAttributes, std::string(name));
1980 }
1981 
getOutputResourceIndex(const GLchar * name) const1982 GLuint Program::getOutputResourceIndex(const GLchar *name) const
1983 {
1984     ASSERT(mLinkResolved);
1985     return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
1986 }
1987 
getOutputResourceCount() const1988 size_t Program::getOutputResourceCount() const
1989 {
1990     ASSERT(mLinkResolved);
1991     return (mLinked ? mState.mOutputVariables.size() : 0);
1992 }
1993 
getOutputVariableTypes() const1994 const std::vector<GLenum> &Program::getOutputVariableTypes() const
1995 {
1996     ASSERT(mLinkResolved);
1997     return mState.mOutputVariableTypes;
1998 }
1999 
2000 template <typename T>
getResourceName(GLuint index,const std::vector<T> & resources,GLsizei bufSize,GLsizei * length,GLchar * name) const2001 void Program::getResourceName(GLuint index,
2002                               const std::vector<T> &resources,
2003                               GLsizei bufSize,
2004                               GLsizei *length,
2005                               GLchar *name) const
2006 {
2007     if (length)
2008     {
2009         *length = 0;
2010     }
2011 
2012     if (!mLinked)
2013     {
2014         if (bufSize > 0)
2015         {
2016             name[0] = '\0';
2017         }
2018         return;
2019     }
2020     ASSERT(index < resources.size());
2021     const auto &resource = resources[index];
2022 
2023     if (bufSize > 0)
2024     {
2025         CopyStringToBuffer(name, resource.name, bufSize, length);
2026     }
2027 }
2028 
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2029 void Program::getInputResourceName(GLuint index,
2030                                    GLsizei bufSize,
2031                                    GLsizei *length,
2032                                    GLchar *name) const
2033 {
2034     ASSERT(mLinkResolved);
2035     getResourceName(index, mState.mAttributes, bufSize, length, name);
2036 }
2037 
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2038 void Program::getOutputResourceName(GLuint index,
2039                                     GLsizei bufSize,
2040                                     GLsizei *length,
2041                                     GLchar *name) const
2042 {
2043     ASSERT(mLinkResolved);
2044     getResourceName(index, mState.mOutputVariables, bufSize, length, name);
2045 }
2046 
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2047 void Program::getUniformResourceName(GLuint index,
2048                                      GLsizei bufSize,
2049                                      GLsizei *length,
2050                                      GLchar *name) const
2051 {
2052     ASSERT(mLinkResolved);
2053     getResourceName(index, mState.mUniforms, bufSize, length, name);
2054 }
2055 
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2056 void Program::getBufferVariableResourceName(GLuint index,
2057                                             GLsizei bufSize,
2058                                             GLsizei *length,
2059                                             GLchar *name) const
2060 {
2061     ASSERT(mLinkResolved);
2062     getResourceName(index, mState.mBufferVariables, bufSize, length, name);
2063 }
2064 
getInputResource(GLuint index) const2065 const sh::Attribute &Program::getInputResource(GLuint index) const
2066 {
2067     ASSERT(mLinkResolved);
2068     ASSERT(index < mState.mAttributes.size());
2069     return mState.mAttributes[index];
2070 }
2071 
getOutputResource(GLuint index) const2072 const sh::OutputVariable &Program::getOutputResource(GLuint index) const
2073 {
2074     ASSERT(mLinkResolved);
2075     ASSERT(index < mState.mOutputVariables.size());
2076     return mState.mOutputVariables[index];
2077 }
2078 
getAttributeBindings() const2079 const ProgramBindings &Program::getAttributeBindings() const
2080 {
2081     ASSERT(mLinkResolved);
2082     return mAttributeBindings;
2083 }
getUniformLocationBindings() const2084 const ProgramBindings &Program::getUniformLocationBindings() const
2085 {
2086     ASSERT(mLinkResolved);
2087     return mUniformLocationBindings;
2088 }
getFragmentInputBindings() const2089 const ProgramBindings &Program::getFragmentInputBindings() const
2090 {
2091     ASSERT(mLinkResolved);
2092     return mFragmentInputBindings;
2093 }
2094 
getDrawBufferTypeMask() const2095 ComponentTypeMask Program::getDrawBufferTypeMask() const
2096 {
2097     ASSERT(mLinkResolved);
2098     return mState.mDrawBufferTypeMask;
2099 }
getAttributesTypeMask() const2100 ComponentTypeMask Program::getAttributesTypeMask() const
2101 {
2102     ASSERT(mLinkResolved);
2103     return mState.mAttributesTypeMask;
2104 }
getAttributesMask() const2105 AttributesMask Program::getAttributesMask() const
2106 {
2107     ASSERT(mLinkResolved);
2108     return mState.mAttributesMask;
2109 }
2110 
getTransformFeedbackStrides() const2111 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2112 {
2113     ASSERT(mLinkResolved);
2114     return mState.mTransformFeedbackStrides;
2115 }
2116 
getFragDataLocation(const std::string & name) const2117 GLint Program::getFragDataLocation(const std::string &name) const
2118 {
2119     ASSERT(mLinkResolved);
2120     GLint primaryLocation =
2121         GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name);
2122     if (primaryLocation != -1)
2123     {
2124         return primaryLocation;
2125     }
2126     return GetVariableLocation(mState.mOutputVariables, mState.mSecondaryOutputLocations, name);
2127 }
2128 
getFragDataIndex(const std::string & name) const2129 GLint Program::getFragDataIndex(const std::string &name) const
2130 {
2131     ASSERT(mLinkResolved);
2132     if (GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name) != -1)
2133     {
2134         return 0;
2135     }
2136     if (GetVariableLocation(mState.mOutputVariables, mState.mSecondaryOutputLocations, name) != -1)
2137     {
2138         return 1;
2139     }
2140     return -1;
2141 }
2142 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2143 void Program::getActiveUniform(GLuint index,
2144                                GLsizei bufsize,
2145                                GLsizei *length,
2146                                GLint *size,
2147                                GLenum *type,
2148                                GLchar *name) const
2149 {
2150     ASSERT(mLinkResolved);
2151     if (mLinked)
2152     {
2153         // index must be smaller than getActiveUniformCount()
2154         ASSERT(index < mState.mUniforms.size());
2155         const LinkedUniform &uniform = mState.mUniforms[index];
2156 
2157         if (bufsize > 0)
2158         {
2159             std::string string = uniform.name;
2160             CopyStringToBuffer(name, string, bufsize, length);
2161         }
2162 
2163         *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2164         *type = uniform.type;
2165     }
2166     else
2167     {
2168         if (bufsize > 0)
2169         {
2170             name[0] = '\0';
2171         }
2172 
2173         if (length)
2174         {
2175             *length = 0;
2176         }
2177 
2178         *size = 0;
2179         *type = GL_NONE;
2180     }
2181 }
2182 
getActiveUniformCount() const2183 GLint Program::getActiveUniformCount() const
2184 {
2185     ASSERT(mLinkResolved);
2186     if (mLinked)
2187     {
2188         return static_cast<GLint>(mState.mUniforms.size());
2189     }
2190     else
2191     {
2192         return 0;
2193     }
2194 }
2195 
getActiveBufferVariableCount() const2196 size_t Program::getActiveBufferVariableCount() const
2197 {
2198     ASSERT(mLinkResolved);
2199     return mLinked ? mState.mBufferVariables.size() : 0;
2200 }
2201 
getActiveUniformMaxLength() const2202 GLint Program::getActiveUniformMaxLength() const
2203 {
2204     ASSERT(mLinkResolved);
2205     size_t maxLength = 0;
2206 
2207     if (mLinked)
2208     {
2209         for (const LinkedUniform &uniform : mState.mUniforms)
2210         {
2211             if (!uniform.name.empty())
2212             {
2213                 size_t length = uniform.name.length() + 1u;
2214                 if (uniform.isArray())
2215                 {
2216                     length += 3;  // Counting in "[0]".
2217                 }
2218                 maxLength = std::max(length, maxLength);
2219             }
2220         }
2221     }
2222 
2223     return static_cast<GLint>(maxLength);
2224 }
2225 
isValidUniformLocation(GLint location) const2226 bool Program::isValidUniformLocation(GLint location) const
2227 {
2228     ASSERT(mLinkResolved);
2229     ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2230     return (location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size() &&
2231             mState.mUniformLocations[static_cast<size_t>(location)].used());
2232 }
2233 
getUniformByLocation(GLint location) const2234 const LinkedUniform &Program::getUniformByLocation(GLint location) const
2235 {
2236     ASSERT(mLinkResolved);
2237     ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
2238     return mState.mUniforms[mState.getUniformIndexFromLocation(location)];
2239 }
2240 
getUniformLocation(GLint location) const2241 const VariableLocation &Program::getUniformLocation(GLint location) const
2242 {
2243     ASSERT(mLinkResolved);
2244     ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
2245     return mState.mUniformLocations[location];
2246 }
2247 
getBufferVariableByIndex(GLuint index) const2248 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2249 {
2250     ASSERT(mLinkResolved);
2251     ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2252     return mState.mBufferVariables[index];
2253 }
2254 
getUniformLocation(const std::string & name) const2255 GLint Program::getUniformLocation(const std::string &name) const
2256 {
2257     ASSERT(mLinkResolved);
2258     return GetVariableLocation(mState.mUniforms, mState.mUniformLocations, name);
2259 }
2260 
getUniformIndex(const std::string & name) const2261 GLuint Program::getUniformIndex(const std::string &name) const
2262 {
2263     ASSERT(mLinkResolved);
2264     return mState.getUniformIndexFromName(name);
2265 }
2266 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)2267 void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2268 {
2269     ASSERT(mLinkResolved);
2270     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2271     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2272     mProgram->setUniform1fv(location, clampedCount, v);
2273 }
2274 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)2275 void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2276 {
2277     ASSERT(mLinkResolved);
2278     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2279     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2280     mProgram->setUniform2fv(location, clampedCount, v);
2281 }
2282 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)2283 void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2284 {
2285     ASSERT(mLinkResolved);
2286     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2287     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2288     mProgram->setUniform3fv(location, clampedCount, v);
2289 }
2290 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)2291 void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2292 {
2293     ASSERT(mLinkResolved);
2294     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2295     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2296     mProgram->setUniform4fv(location, clampedCount, v);
2297 }
2298 
setUniform1iv(Context * context,GLint location,GLsizei count,const GLint * v)2299 void Program::setUniform1iv(Context *context, GLint location, GLsizei count, const GLint *v)
2300 {
2301     ASSERT(mLinkResolved);
2302     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2303     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2304 
2305     mProgram->setUniform1iv(location, clampedCount, v);
2306 
2307     if (mState.isSamplerUniformIndex(locationInfo.index))
2308     {
2309         updateSamplerUniform(context, locationInfo, clampedCount, v);
2310     }
2311 }
2312 
setUniform2iv(GLint location,GLsizei count,const GLint * v)2313 void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2314 {
2315     ASSERT(mLinkResolved);
2316     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2317     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2318     mProgram->setUniform2iv(location, clampedCount, v);
2319 }
2320 
setUniform3iv(GLint location,GLsizei count,const GLint * v)2321 void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2322 {
2323     ASSERT(mLinkResolved);
2324     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2325     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2326     mProgram->setUniform3iv(location, clampedCount, v);
2327 }
2328 
setUniform4iv(GLint location,GLsizei count,const GLint * v)2329 void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2330 {
2331     ASSERT(mLinkResolved);
2332     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2333     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2334     mProgram->setUniform4iv(location, clampedCount, v);
2335 }
2336 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)2337 void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2338 {
2339     ASSERT(mLinkResolved);
2340     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2341     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2342     mProgram->setUniform1uiv(location, clampedCount, v);
2343 }
2344 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)2345 void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2346 {
2347     ASSERT(mLinkResolved);
2348     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2349     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2350     mProgram->setUniform2uiv(location, clampedCount, v);
2351 }
2352 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)2353 void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2354 {
2355     ASSERT(mLinkResolved);
2356     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2357     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2358     mProgram->setUniform3uiv(location, clampedCount, v);
2359 }
2360 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)2361 void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2362 {
2363     ASSERT(mLinkResolved);
2364     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2365     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2366     mProgram->setUniform4uiv(location, clampedCount, v);
2367 }
2368 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2369 void Program::setUniformMatrix2fv(GLint location,
2370                                   GLsizei count,
2371                                   GLboolean transpose,
2372                                   const GLfloat *v)
2373 {
2374     ASSERT(mLinkResolved);
2375     GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
2376     mProgram->setUniformMatrix2fv(location, clampedCount, transpose, v);
2377 }
2378 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2379 void Program::setUniformMatrix3fv(GLint location,
2380                                   GLsizei count,
2381                                   GLboolean transpose,
2382                                   const GLfloat *v)
2383 {
2384     ASSERT(mLinkResolved);
2385     GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
2386     mProgram->setUniformMatrix3fv(location, clampedCount, transpose, v);
2387 }
2388 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2389 void Program::setUniformMatrix4fv(GLint location,
2390                                   GLsizei count,
2391                                   GLboolean transpose,
2392                                   const GLfloat *v)
2393 {
2394     ASSERT(mLinkResolved);
2395     GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
2396     mProgram->setUniformMatrix4fv(location, clampedCount, transpose, v);
2397 }
2398 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2399 void Program::setUniformMatrix2x3fv(GLint location,
2400                                     GLsizei count,
2401                                     GLboolean transpose,
2402                                     const GLfloat *v)
2403 {
2404     ASSERT(mLinkResolved);
2405     GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
2406     mProgram->setUniformMatrix2x3fv(location, clampedCount, transpose, v);
2407 }
2408 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2409 void Program::setUniformMatrix2x4fv(GLint location,
2410                                     GLsizei count,
2411                                     GLboolean transpose,
2412                                     const GLfloat *v)
2413 {
2414     ASSERT(mLinkResolved);
2415     GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
2416     mProgram->setUniformMatrix2x4fv(location, clampedCount, transpose, v);
2417 }
2418 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2419 void Program::setUniformMatrix3x2fv(GLint location,
2420                                     GLsizei count,
2421                                     GLboolean transpose,
2422                                     const GLfloat *v)
2423 {
2424     ASSERT(mLinkResolved);
2425     GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
2426     mProgram->setUniformMatrix3x2fv(location, clampedCount, transpose, v);
2427 }
2428 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2429 void Program::setUniformMatrix3x4fv(GLint location,
2430                                     GLsizei count,
2431                                     GLboolean transpose,
2432                                     const GLfloat *v)
2433 {
2434     ASSERT(mLinkResolved);
2435     GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
2436     mProgram->setUniformMatrix3x4fv(location, clampedCount, transpose, v);
2437 }
2438 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2439 void Program::setUniformMatrix4x2fv(GLint location,
2440                                     GLsizei count,
2441                                     GLboolean transpose,
2442                                     const GLfloat *v)
2443 {
2444     ASSERT(mLinkResolved);
2445     GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
2446     mProgram->setUniformMatrix4x2fv(location, clampedCount, transpose, v);
2447 }
2448 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2449 void Program::setUniformMatrix4x3fv(GLint location,
2450                                     GLsizei count,
2451                                     GLboolean transpose,
2452                                     const GLfloat *v)
2453 {
2454     ASSERT(mLinkResolved);
2455     GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
2456     mProgram->setUniformMatrix4x3fv(location, clampedCount, transpose, v);
2457 }
2458 
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2459 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2460 {
2461     ASSERT(mLinkResolved);
2462     GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2463     const std::vector<GLuint> &boundTextureUnits =
2464         mState.mSamplerBindings[samplerIndex].boundTextureUnits;
2465     return boundTextureUnits[uniformLocation.arrayIndex];
2466 }
2467 
getUniformfv(const Context * context,GLint location,GLfloat * v) const2468 void Program::getUniformfv(const Context *context, GLint location, GLfloat *v) const
2469 {
2470     ASSERT(mLinkResolved);
2471     const VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2472     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2473 
2474     if (uniform.isSampler())
2475     {
2476         *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2477         return;
2478     }
2479 
2480     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2481     if (nativeType == GL_FLOAT)
2482     {
2483         mProgram->getUniformfv(context, location, v);
2484     }
2485     else
2486     {
2487         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2488     }
2489 }
2490 
getUniformiv(const Context * context,GLint location,GLint * v) const2491 void Program::getUniformiv(const Context *context, GLint location, GLint *v) const
2492 {
2493     ASSERT(mLinkResolved);
2494     const VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2495     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2496 
2497     if (uniform.isSampler())
2498     {
2499         *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2500         return;
2501     }
2502 
2503     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2504     if (nativeType == GL_INT || nativeType == GL_BOOL)
2505     {
2506         mProgram->getUniformiv(context, location, v);
2507     }
2508     else
2509     {
2510         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2511     }
2512 }
2513 
getUniformuiv(const Context * context,GLint location,GLuint * v) const2514 void Program::getUniformuiv(const Context *context, GLint location, GLuint *v) const
2515 {
2516     ASSERT(mLinkResolved);
2517     const VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2518     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2519 
2520     if (uniform.isSampler())
2521     {
2522         *v = getSamplerUniformBinding(uniformLocation);
2523         return;
2524     }
2525 
2526     const GLenum nativeType = VariableComponentType(uniform.type);
2527     if (nativeType == GL_UNSIGNED_INT)
2528     {
2529         mProgram->getUniformuiv(context, location, v);
2530     }
2531     else
2532     {
2533         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2534     }
2535 }
2536 
flagForDeletion()2537 void Program::flagForDeletion()
2538 {
2539     ASSERT(mLinkResolved);
2540     mDeleteStatus = true;
2541 }
2542 
isFlaggedForDeletion() const2543 bool Program::isFlaggedForDeletion() const
2544 {
2545     ASSERT(mLinkResolved);
2546     return mDeleteStatus;
2547 }
2548 
validate(const Caps & caps)2549 void Program::validate(const Caps &caps)
2550 {
2551     ASSERT(mLinkResolved);
2552     mInfoLog.reset();
2553 
2554     if (mLinked)
2555     {
2556         mValidated = ConvertToBool(mProgram->validate(caps, &mInfoLog));
2557     }
2558     else
2559     {
2560         mInfoLog << "Program has not been successfully linked.";
2561     }
2562 }
2563 
validateSamplersImpl(InfoLog * infoLog,const Caps & caps)2564 bool Program::validateSamplersImpl(InfoLog *infoLog, const Caps &caps)
2565 {
2566     ASSERT(mLinkResolved);
2567 
2568     // if any two active samplers in a program are of different types, but refer to the same
2569     // texture image unit, and this is the current program, then ValidateProgram will fail, and
2570     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
2571     for (size_t textureUnit : mState.mActiveSamplersMask)
2572     {
2573         if (mState.mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
2574         {
2575             if (infoLog)
2576             {
2577                 (*infoLog) << "Samplers of conflicting types refer to the same texture "
2578                               "image unit ("
2579                            << textureUnit << ").";
2580             }
2581 
2582             mCachedValidateSamplersResult = false;
2583             return false;
2584         }
2585     }
2586 
2587     mCachedValidateSamplersResult = true;
2588     return true;
2589 }
2590 
isValidated() const2591 bool Program::isValidated() const
2592 {
2593     ASSERT(mLinkResolved);
2594     return mValidated;
2595 }
2596 
getActiveUniformBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2597 void Program::getActiveUniformBlockName(const GLuint blockIndex,
2598                                         GLsizei bufSize,
2599                                         GLsizei *length,
2600                                         GLchar *blockName) const
2601 {
2602     ASSERT(mLinkResolved);
2603     GetInterfaceBlockName(blockIndex, mState.mUniformBlocks, bufSize, length, blockName);
2604 }
2605 
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2606 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
2607                                               GLsizei bufSize,
2608                                               GLsizei *length,
2609                                               GLchar *blockName) const
2610 {
2611     ASSERT(mLinkResolved);
2612     GetInterfaceBlockName(blockIndex, mState.mShaderStorageBlocks, bufSize, length, blockName);
2613 }
2614 
2615 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const2616 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
2617 {
2618     int maxLength = 0;
2619 
2620     if (mLinked)
2621     {
2622         for (const T &resource : resources)
2623         {
2624             if (!resource.name.empty())
2625             {
2626                 int length = static_cast<int>(resource.nameWithArrayIndex().length());
2627                 maxLength  = std::max(length + 1, maxLength);
2628             }
2629         }
2630     }
2631 
2632     return maxLength;
2633 }
2634 
getActiveUniformBlockMaxNameLength() const2635 GLint Program::getActiveUniformBlockMaxNameLength() const
2636 {
2637     ASSERT(mLinkResolved);
2638     return getActiveInterfaceBlockMaxNameLength(mState.mUniformBlocks);
2639 }
2640 
getActiveShaderStorageBlockMaxNameLength() const2641 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
2642 {
2643     ASSERT(mLinkResolved);
2644     return getActiveInterfaceBlockMaxNameLength(mState.mShaderStorageBlocks);
2645 }
2646 
getUniformBlockIndex(const std::string & name) const2647 GLuint Program::getUniformBlockIndex(const std::string &name) const
2648 {
2649     ASSERT(mLinkResolved);
2650     return GetInterfaceBlockIndex(mState.mUniformBlocks, name);
2651 }
2652 
getShaderStorageBlockIndex(const std::string & name) const2653 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
2654 {
2655     ASSERT(mLinkResolved);
2656     return GetInterfaceBlockIndex(mState.mShaderStorageBlocks, name);
2657 }
2658 
getUniformBlockByIndex(GLuint index) const2659 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
2660 {
2661     ASSERT(mLinkResolved);
2662     ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size()));
2663     return mState.mUniformBlocks[index];
2664 }
2665 
getShaderStorageBlockByIndex(GLuint index) const2666 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
2667 {
2668     ASSERT(mLinkResolved);
2669     ASSERT(index < static_cast<GLuint>(mState.mShaderStorageBlocks.size()));
2670     return mState.mShaderStorageBlocks[index];
2671 }
2672 
bindUniformBlock(GLuint uniformBlockIndex,GLuint uniformBlockBinding)2673 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
2674 {
2675     ASSERT(mLinkResolved);
2676     mState.mUniformBlocks[uniformBlockIndex].binding = uniformBlockBinding;
2677     mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlockBinding != 0);
2678     mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex);
2679 }
2680 
getUniformBlockBinding(GLuint uniformBlockIndex) const2681 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
2682 {
2683     ASSERT(mLinkResolved);
2684     return mState.getUniformBlockBinding(uniformBlockIndex);
2685 }
2686 
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const2687 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
2688 {
2689     ASSERT(mLinkResolved);
2690     return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
2691 }
2692 
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2693 void Program::setTransformFeedbackVaryings(GLsizei count,
2694                                            const GLchar *const *varyings,
2695                                            GLenum bufferMode)
2696 {
2697     ASSERT(mLinkResolved);
2698     mState.mTransformFeedbackVaryingNames.resize(count);
2699     for (GLsizei i = 0; i < count; i++)
2700     {
2701         mState.mTransformFeedbackVaryingNames[i] = varyings[i];
2702     }
2703 
2704     mState.mTransformFeedbackBufferMode = bufferMode;
2705 }
2706 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2707 void Program::getTransformFeedbackVarying(GLuint index,
2708                                           GLsizei bufSize,
2709                                           GLsizei *length,
2710                                           GLsizei *size,
2711                                           GLenum *type,
2712                                           GLchar *name) const
2713 {
2714     ASSERT(mLinkResolved);
2715     if (mLinked)
2716     {
2717         ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size());
2718         const auto &var     = mState.mLinkedTransformFeedbackVaryings[index];
2719         std::string varName = var.nameWithArrayIndex();
2720         GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
2721         if (length)
2722         {
2723             *length = lastNameIdx;
2724         }
2725         if (size)
2726         {
2727             *size = var.size();
2728         }
2729         if (type)
2730         {
2731             *type = var.type;
2732         }
2733         if (name)
2734         {
2735             memcpy(name, varName.c_str(), lastNameIdx);
2736             name[lastNameIdx] = '\0';
2737         }
2738     }
2739 }
2740 
getTransformFeedbackVaryingCount() const2741 GLsizei Program::getTransformFeedbackVaryingCount() const
2742 {
2743     ASSERT(mLinkResolved);
2744     if (mLinked)
2745     {
2746         return static_cast<GLsizei>(mState.mLinkedTransformFeedbackVaryings.size());
2747     }
2748     else
2749     {
2750         return 0;
2751     }
2752 }
2753 
getTransformFeedbackVaryingMaxLength() const2754 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
2755 {
2756     ASSERT(mLinkResolved);
2757     if (mLinked)
2758     {
2759         GLsizei maxSize = 0;
2760         for (const auto &var : mState.mLinkedTransformFeedbackVaryings)
2761         {
2762             maxSize =
2763                 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
2764         }
2765 
2766         return maxSize;
2767     }
2768     else
2769     {
2770         return 0;
2771     }
2772 }
2773 
getTransformFeedbackBufferMode() const2774 GLenum Program::getTransformFeedbackBufferMode() const
2775 {
2776     ASSERT(mLinkResolved);
2777     return mState.mTransformFeedbackBufferMode;
2778 }
2779 
linkValidateShaders(InfoLog & infoLog)2780 bool Program::linkValidateShaders(InfoLog &infoLog)
2781 {
2782     Shader *vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
2783     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
2784     Shader *computeShader  = mState.mAttachedShaders[ShaderType::Compute];
2785     Shader *geometryShader = mState.mAttachedShaders[ShaderType::Geometry];
2786 
2787     bool isComputeShaderAttached = (computeShader != nullptr);
2788     bool isGraphicsShaderAttached =
2789         (vertexShader != nullptr || fragmentShader != nullptr || geometryShader != nullptr);
2790     // Check whether we both have a compute and non-compute shaders attached.
2791     // If there are of both types attached, then linking should fail.
2792     // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
2793     if (isComputeShaderAttached == true && isGraphicsShaderAttached == true)
2794     {
2795         infoLog << "Both compute and graphics shaders are attached to the same program.";
2796         return false;
2797     }
2798 
2799     if (computeShader)
2800     {
2801         if (!computeShader->isCompiled())
2802         {
2803             infoLog << "Attached compute shader is not compiled.";
2804             return false;
2805         }
2806         ASSERT(computeShader->getType() == ShaderType::Compute);
2807 
2808         mState.mComputeShaderLocalSize = computeShader->getWorkGroupSize();
2809 
2810         // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
2811         // If the work group size is not specified, a link time error should occur.
2812         if (!mState.mComputeShaderLocalSize.isDeclared())
2813         {
2814             infoLog << "Work group size is not specified.";
2815             return false;
2816         }
2817     }
2818     else
2819     {
2820         if (!fragmentShader || !fragmentShader->isCompiled())
2821         {
2822             infoLog << "No compiled fragment shader when at least one graphics shader is attached.";
2823             return false;
2824         }
2825         ASSERT(fragmentShader->getType() == ShaderType::Fragment);
2826 
2827         if (!vertexShader || !vertexShader->isCompiled())
2828         {
2829             infoLog << "No compiled vertex shader when at least one graphics shader is attached.";
2830             return false;
2831         }
2832         ASSERT(vertexShader->getType() == ShaderType::Vertex);
2833 
2834         int vertexShaderVersion = vertexShader->getShaderVersion();
2835         if (fragmentShader->getShaderVersion() != vertexShaderVersion)
2836         {
2837             infoLog << "Fragment shader version does not match vertex shader version.";
2838             return false;
2839         }
2840 
2841         if (geometryShader)
2842         {
2843             // [GL_EXT_geometry_shader] Chapter 7
2844             // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
2845             // Language Specification, as well as any of the following reasons:
2846             // * One or more of the shader objects attached to <program> are not compiled
2847             //   successfully.
2848             // * The shaders do not use the same shader language version.
2849             // * <program> contains objects to form a geometry shader, and
2850             //   - <program> is not separable and contains no objects to form a vertex shader; or
2851             //   - the input primitive type, output primitive type, or maximum output vertex count
2852             //     is not specified in the compiled geometry shader object.
2853             if (!geometryShader->isCompiled())
2854             {
2855                 infoLog << "The attached geometry shader isn't compiled.";
2856                 return false;
2857             }
2858 
2859             if (geometryShader->getShaderVersion() != vertexShaderVersion)
2860             {
2861                 mInfoLog << "Geometry shader version does not match vertex shader version.";
2862                 return false;
2863             }
2864             ASSERT(geometryShader->getType() == ShaderType::Geometry);
2865 
2866             Optional<PrimitiveMode> inputPrimitive =
2867                 geometryShader->getGeometryShaderInputPrimitiveType();
2868             if (!inputPrimitive.valid())
2869             {
2870                 mInfoLog << "Input primitive type is not specified in the geometry shader.";
2871                 return false;
2872             }
2873 
2874             Optional<PrimitiveMode> outputPrimitive =
2875                 geometryShader->getGeometryShaderOutputPrimitiveType();
2876             if (!outputPrimitive.valid())
2877             {
2878                 mInfoLog << "Output primitive type is not specified in the geometry shader.";
2879                 return false;
2880             }
2881 
2882             Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
2883             if (!maxVertices.valid())
2884             {
2885                 mInfoLog << "'max_vertices' is not specified in the geometry shader.";
2886                 return false;
2887             }
2888 
2889             mState.mGeometryShaderInputPrimitiveType  = inputPrimitive.value();
2890             mState.mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
2891             mState.mGeometryShaderMaxVertices         = maxVertices.value();
2892             mState.mGeometryShaderInvocations = geometryShader->getGeometryShaderInvocations();
2893         }
2894     }
2895 
2896     return true;
2897 }
2898 
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const2899 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
2900 {
2901     ASSERT(mLinkResolved);
2902     for (GLuint tfIndex = 0; tfIndex < mState.mLinkedTransformFeedbackVaryings.size(); ++tfIndex)
2903     {
2904         const auto &tf = mState.mLinkedTransformFeedbackVaryings[tfIndex];
2905         if (tf.nameWithArrayIndex() == name)
2906         {
2907             return tfIndex;
2908         }
2909     }
2910     return GL_INVALID_INDEX;
2911 }
2912 
getTransformFeedbackVaryingResource(GLuint index) const2913 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
2914 {
2915     ASSERT(mLinkResolved);
2916     ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size());
2917     return mState.mLinkedTransformFeedbackVaryings[index];
2918 }
2919 
hasDrawIDUniform() const2920 bool Program::hasDrawIDUniform() const
2921 {
2922     ASSERT(mLinkResolved);
2923     return mState.mDrawIDLocation >= 0;
2924 }
2925 
setDrawIDUniform(GLint drawid)2926 void Program::setDrawIDUniform(GLint drawid)
2927 {
2928     ASSERT(mLinkResolved);
2929     ASSERT(mState.mDrawIDLocation >= 0);
2930     mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
2931 }
2932 
hasBaseVertexUniform() const2933 bool Program::hasBaseVertexUniform() const
2934 {
2935     ASSERT(mLinkResolved);
2936     return mState.mBaseVertexLocation >= 0;
2937 }
2938 
setBaseVertexUniform(GLint baseVertex)2939 void Program::setBaseVertexUniform(GLint baseVertex)
2940 {
2941     ASSERT(mLinkResolved);
2942     ASSERT(mState.mBaseVertexLocation >= 0);
2943     mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
2944 }
2945 
hasBaseInstanceUniform() const2946 bool Program::hasBaseInstanceUniform() const
2947 {
2948     ASSERT(mLinkResolved);
2949     return mState.mBaseInstanceLocation >= 0;
2950 }
2951 
setBaseInstanceUniform(GLuint baseInstance)2952 void Program::setBaseInstanceUniform(GLuint baseInstance)
2953 {
2954     ASSERT(mLinkResolved);
2955     ASSERT(mState.mBaseInstanceLocation >= 0);
2956     GLint baseInstanceInt = baseInstance;
2957     mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
2958 }
2959 
linkVaryings(InfoLog & infoLog) const2960 bool Program::linkVaryings(InfoLog &infoLog) const
2961 {
2962     Shader *previousShader = nullptr;
2963     for (ShaderType shaderType : kAllGraphicsShaderTypes)
2964     {
2965         Shader *currentShader = mState.mAttachedShaders[shaderType];
2966         if (!currentShader)
2967         {
2968             continue;
2969         }
2970 
2971         if (previousShader)
2972         {
2973             if (!linkValidateShaderInterfaceMatching(previousShader, currentShader, infoLog))
2974             {
2975                 return false;
2976             }
2977         }
2978         previousShader = currentShader;
2979     }
2980 
2981     if (!linkValidateBuiltInVaryings(infoLog))
2982     {
2983         return false;
2984     }
2985 
2986     if (!linkValidateFragmentInputBindings(infoLog))
2987     {
2988         return false;
2989     }
2990 
2991     return true;
2992 }
2993 
2994 // [OpenGL ES 3.1] Chapter 7.4.1 "Shader Interface Matching" Page 91
2995 // TODO(jiawei.shao@intel.com): add validation on input/output blocks matching
linkValidateShaderInterfaceMatching(gl::Shader * generatingShader,gl::Shader * consumingShader,gl::InfoLog & infoLog) const2996 bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader,
2997                                                   gl::Shader *consumingShader,
2998                                                   gl::InfoLog &infoLog) const
2999 {
3000     ASSERT(generatingShader->getShaderVersion() == consumingShader->getShaderVersion());
3001 
3002     const std::vector<sh::Varying> &outputVaryings = generatingShader->getOutputVaryings();
3003     const std::vector<sh::Varying> &inputVaryings  = consumingShader->getInputVaryings();
3004 
3005     bool validateGeometryShaderInputs = consumingShader->getType() == ShaderType::Geometry;
3006 
3007     for (const sh::Varying &input : inputVaryings)
3008     {
3009         bool matched = false;
3010 
3011         // Built-in varyings obey special rules
3012         if (input.isBuiltIn())
3013         {
3014             continue;
3015         }
3016 
3017         // An output variable is considered to match an input variable in the subsequent
3018         // shader if:
3019         // - the two variables match in name, type, and qualification; or
3020         // - the two variables are declared with the same location qualifier and
3021         //   match in type and qualification.
3022         for (const sh::Varying &output : outputVaryings)
3023         {
3024             bool namesMatch     = input.name == output.name;
3025             bool locationsMatch = (input.location != -1) && (input.location == output.location);
3026 
3027             if (namesMatch || locationsMatch)
3028             {
3029                 ASSERT(!output.isBuiltIn());
3030 
3031                 std::string mismatchedStructFieldName;
3032                 LinkMismatchError linkError =
3033                     LinkValidateVaryings(output, input, generatingShader->getShaderVersion(),
3034                                          validateGeometryShaderInputs, &mismatchedStructFieldName);
3035                 if (linkError != LinkMismatchError::NO_MISMATCH)
3036                 {
3037                     LogLinkMismatch(infoLog, input.name, "varying", linkError,
3038                                     mismatchedStructFieldName, generatingShader->getType(),
3039                                     consumingShader->getType());
3040                     return false;
3041                 }
3042 
3043                 matched = true;
3044                 break;
3045             }
3046         }
3047 
3048         // We permit unmatched, unreferenced varyings. Note that this specifically depends on
3049         // whether the input is statically used - a statically used input should fail this test even
3050         // if it is not active. GLSL ES 3.00.6 section 4.3.10.
3051         if (!matched && input.staticUse)
3052         {
3053             infoLog << GetShaderTypeString(consumingShader->getType()) << " varying " << input.name
3054                     << " does not match any " << GetShaderTypeString(generatingShader->getType())
3055                     << " varying";
3056             return false;
3057         }
3058     }
3059 
3060     // TODO(jmadill): verify no unmatched output varyings?
3061 
3062     return true;
3063 }
3064 
linkValidateFragmentInputBindings(gl::InfoLog & infoLog) const3065 bool Program::linkValidateFragmentInputBindings(gl::InfoLog &infoLog) const
3066 {
3067     ASSERT(mState.mAttachedShaders[ShaderType::Fragment]);
3068 
3069     std::map<GLuint, std::string> staticFragmentInputLocations;
3070 
3071     const std::vector<sh::Varying> &fragmentInputVaryings =
3072         mState.mAttachedShaders[ShaderType::Fragment]->getInputVaryings();
3073     for (const sh::Varying &input : fragmentInputVaryings)
3074     {
3075         if (input.isBuiltIn() || !input.staticUse)
3076         {
3077             continue;
3078         }
3079 
3080         const auto inputBinding = mFragmentInputBindings.getBinding(input);
3081         if (inputBinding == -1)
3082             continue;
3083 
3084         const auto it = staticFragmentInputLocations.find(inputBinding);
3085         if (it == std::end(staticFragmentInputLocations))
3086         {
3087             staticFragmentInputLocations.insert(std::make_pair(inputBinding, input.name));
3088         }
3089         else
3090         {
3091             infoLog << "Binding for fragment input " << input.name << " conflicts with "
3092                     << it->second;
3093             return false;
3094         }
3095     }
3096 
3097     return true;
3098 }
3099 
linkUniforms(const Caps & caps,InfoLog & infoLog,const ProgramBindings & uniformLocationBindings,GLuint * combinedImageUniformsCount,std::vector<UnusedUniform> * unusedUniforms)3100 bool Program::linkUniforms(const Caps &caps,
3101                            InfoLog &infoLog,
3102                            const ProgramBindings &uniformLocationBindings,
3103                            GLuint *combinedImageUniformsCount,
3104                            std::vector<UnusedUniform> *unusedUniforms)
3105 {
3106     UniformLinker linker(mState);
3107     if (!linker.link(caps, infoLog, uniformLocationBindings))
3108     {
3109         return false;
3110     }
3111 
3112     linker.getResults(&mState.mUniforms, unusedUniforms, &mState.mUniformLocations);
3113 
3114     linkSamplerAndImageBindings(combinedImageUniformsCount);
3115 
3116     if (!linkAtomicCounterBuffers())
3117     {
3118         return false;
3119     }
3120 
3121     return true;
3122 }
3123 
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)3124 void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
3125 {
3126     ASSERT(combinedImageUniforms);
3127 
3128     unsigned int high = static_cast<unsigned int>(mState.mUniforms.size());
3129     unsigned int low  = high;
3130 
3131     for (auto counterIter = mState.mUniforms.rbegin();
3132          counterIter != mState.mUniforms.rend() && counterIter->isAtomicCounter(); ++counterIter)
3133     {
3134         --low;
3135     }
3136 
3137     mState.mAtomicCounterUniformRange = RangeUI(low, high);
3138 
3139     high = low;
3140 
3141     for (auto imageIter = mState.mUniforms.rbegin();
3142          imageIter != mState.mUniforms.rend() && imageIter->isImage(); ++imageIter)
3143     {
3144         --low;
3145     }
3146 
3147     mState.mImageUniformRange = RangeUI(low, high);
3148     *combinedImageUniforms    = 0u;
3149     // If uniform is a image type, insert it into the mImageBindings array.
3150     for (unsigned int imageIndex : mState.mImageUniformRange)
3151     {
3152         // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
3153         // cannot load values into a uniform defined as an image. if declare without a
3154         // binding qualifier, any uniform image variable (include all elements of
3155         // unbound image array) shoud be bound to unit zero.
3156         auto &imageUniform = mState.mUniforms[imageIndex];
3157         if (imageUniform.binding == -1)
3158         {
3159             mState.mImageBindings.emplace_back(
3160                 ImageBinding(imageUniform.getBasicTypeElementCount()));
3161         }
3162         else
3163         {
3164             mState.mImageBindings.emplace_back(
3165                 ImageBinding(imageUniform.binding, imageUniform.getBasicTypeElementCount(), false));
3166         }
3167 
3168         GLuint arraySize = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
3169         *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
3170     }
3171 
3172     high = low;
3173 
3174     for (auto samplerIter = mState.mUniforms.rbegin() + mState.mImageUniformRange.length();
3175          samplerIter != mState.mUniforms.rend() && samplerIter->isSampler(); ++samplerIter)
3176     {
3177         --low;
3178     }
3179 
3180     mState.mSamplerUniformRange = RangeUI(low, high);
3181 
3182     // If uniform is a sampler type, insert it into the mSamplerBindings array.
3183     for (unsigned int samplerIndex : mState.mSamplerUniformRange)
3184     {
3185         const auto &samplerUniform = mState.mUniforms[samplerIndex];
3186         TextureType textureType    = SamplerTypeToTextureType(samplerUniform.type);
3187         unsigned int elementCount  = samplerUniform.getBasicTypeElementCount();
3188         SamplerFormat format       = samplerUniform.typeInfo->samplerFormat;
3189         mState.mSamplerBindings.emplace_back(textureType, format, elementCount, false);
3190     }
3191 }
3192 
linkAtomicCounterBuffers()3193 bool Program::linkAtomicCounterBuffers()
3194 {
3195     for (unsigned int index : mState.mAtomicCounterUniformRange)
3196     {
3197         auto &uniform                      = mState.mUniforms[index];
3198         uniform.blockInfo.offset           = uniform.offset;
3199         uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
3200         uniform.blockInfo.matrixStride     = 0;
3201         uniform.blockInfo.isRowMajorMatrix = false;
3202 
3203         bool found = false;
3204         for (unsigned int bufferIndex = 0; bufferIndex < mState.mAtomicCounterBuffers.size();
3205              ++bufferIndex)
3206         {
3207             auto &buffer = mState.mAtomicCounterBuffers[bufferIndex];
3208             if (buffer.binding == uniform.binding)
3209             {
3210                 buffer.memberIndexes.push_back(index);
3211                 uniform.bufferIndex = bufferIndex;
3212                 found               = true;
3213                 buffer.unionReferencesWith(uniform);
3214                 break;
3215             }
3216         }
3217         if (!found)
3218         {
3219             AtomicCounterBuffer atomicCounterBuffer;
3220             atomicCounterBuffer.binding = uniform.binding;
3221             atomicCounterBuffer.memberIndexes.push_back(index);
3222             atomicCounterBuffer.unionReferencesWith(uniform);
3223             mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer);
3224             uniform.bufferIndex = static_cast<int>(mState.mAtomicCounterBuffers.size() - 1);
3225         }
3226     }
3227     // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
3228     // gl_Max[Vertex|Fragment|Compute|Geometry|Combined]AtomicCounterBuffers.
3229 
3230     return true;
3231 }
3232 
3233 // Assigns locations to all attributes from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3234 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3235 {
3236     const Caps &caps               = context->getCaps();
3237     const Limitations &limitations = context->getLimitations();
3238     bool webglCompatibility        = context->getExtensions().webglCompatibility;
3239 
3240     Shader *vertexShader = mState.getAttachedShader(ShaderType::Vertex);
3241 
3242     int shaderVersion = vertexShader->getShaderVersion();
3243 
3244     unsigned int usedLocations = 0;
3245     if (shaderVersion >= 300)
3246     {
3247         // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes - see GLSL
3248         // ES 3.00.6 section 12.46. Inactive attributes will be pruned after aliasing checks.
3249         mState.mAttributes = vertexShader->getAllAttributes();
3250     }
3251     else
3252     {
3253         // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3254         mState.mAttributes = vertexShader->getActiveAttributes();
3255     }
3256     GLuint maxAttribs = caps.maxVertexAttributes;
3257 
3258     std::vector<sh::Attribute *> usedAttribMap(maxAttribs, nullptr);
3259 
3260     // Assign locations to attributes that have a binding location and check for attribute aliasing.
3261     for (sh::Attribute &attribute : mState.mAttributes)
3262     {
3263         // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3264         // structures, so we don't need to worry about adjusting their names or generating entries
3265         // for each member/element (unlike uniforms for example).
3266         ASSERT(!attribute.isArray() && !attribute.isStruct());
3267 
3268         int bindingLocation = mAttributeBindings.getBinding(attribute);
3269         if (attribute.location == -1 && bindingLocation != -1)
3270         {
3271             attribute.location = bindingLocation;
3272         }
3273 
3274         if (attribute.location != -1)
3275         {
3276             // Location is set by glBindAttribLocation or by location layout qualifier
3277             const int regs = VariableRegisterCount(attribute.type);
3278 
3279             if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3280             {
3281                 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3282                         << " is too big to fit";
3283 
3284                 return false;
3285             }
3286 
3287             for (int reg = 0; reg < regs; reg++)
3288             {
3289                 const int regLocation               = attribute.location + reg;
3290                 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3291 
3292                 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3293                 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3294                 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3295                 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3296                 if (linkedAttribute)
3297                 {
3298                     if (shaderVersion >= 300 || webglCompatibility ||
3299                         limitations.noVertexAttributeAliasing)
3300                     {
3301                         infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3302                                 << linkedAttribute->name << "' at location " << regLocation;
3303                         return false;
3304                     }
3305                 }
3306                 else
3307                 {
3308                     usedAttribMap[regLocation] = &attribute;
3309                 }
3310 
3311                 usedLocations |= 1 << regLocation;
3312             }
3313         }
3314     }
3315 
3316     // Assign locations to attributes that don't have a binding location.
3317     for (sh::Attribute &attribute : mState.mAttributes)
3318     {
3319         // Not set by glBindAttribLocation or by location layout qualifier
3320         if (attribute.location == -1)
3321         {
3322             int regs           = VariableRegisterCount(attribute.type);
3323             int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3324 
3325             if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3326             {
3327                 infoLog << "Too many attributes (" << attribute.name << ")";
3328                 return false;
3329             }
3330 
3331             attribute.location = availableIndex;
3332         }
3333     }
3334 
3335     ASSERT(mState.mAttributesTypeMask.none());
3336     ASSERT(mState.mAttributesMask.none());
3337 
3338     // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3339     // shader versions we're only processing active attributes to begin with.
3340     if (shaderVersion >= 300)
3341     {
3342         for (auto attributeIter = mState.mAttributes.begin();
3343              attributeIter != mState.mAttributes.end();)
3344         {
3345             if (attributeIter->active)
3346             {
3347                 ++attributeIter;
3348             }
3349             else
3350             {
3351                 attributeIter = mState.mAttributes.erase(attributeIter);
3352             }
3353         }
3354     }
3355 
3356     for (const sh::Attribute &attribute : mState.mAttributes)
3357     {
3358         ASSERT(attribute.active);
3359         ASSERT(attribute.location != -1);
3360         unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3361 
3362         for (unsigned int r = 0; r < regs; r++)
3363         {
3364             unsigned int location = static_cast<unsigned int>(attribute.location) + r;
3365             mState.mActiveAttribLocationsMask.set(location);
3366             mState.mMaxActiveAttribLocation =
3367                 std::max(mState.mMaxActiveAttribLocation, location + 1);
3368 
3369             // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
3370             if (!attribute.isBuiltIn())
3371             {
3372                 ComponentType componentType =
3373                     GLenumToComponentType(VariableComponentType(attribute.type));
3374 
3375                 SetComponentTypeMask(componentType, location, &mState.mAttributesTypeMask);
3376                 mState.mAttributesMask.set(location);
3377             }
3378         }
3379     }
3380 
3381     return true;
3382 }
3383 
linkInterfaceBlocks(const Caps & caps,const Version & version,bool webglCompatibility,InfoLog & infoLog,GLuint * combinedShaderStorageBlocksCount)3384 bool Program::linkInterfaceBlocks(const Caps &caps,
3385                                   const Version &version,
3386                                   bool webglCompatibility,
3387                                   InfoLog &infoLog,
3388                                   GLuint *combinedShaderStorageBlocksCount)
3389 {
3390     ASSERT(combinedShaderStorageBlocksCount);
3391 
3392     GLuint combinedUniformBlocksCount                                         = 0u;
3393     GLuint numShadersHasUniformBlocks                                         = 0u;
3394     ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
3395     for (ShaderType shaderType : AllShaderTypes())
3396     {
3397         Shader *shader = mState.mAttachedShaders[shaderType];
3398         if (!shader)
3399         {
3400             continue;
3401         }
3402 
3403         const auto &uniformBlocks = shader->getUniformBlocks();
3404         if (!uniformBlocks.empty())
3405         {
3406             if (!ValidateInterfaceBlocksCount(
3407                     caps.maxShaderUniformBlocks[shaderType], uniformBlocks, shaderType,
3408                     sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
3409             {
3410                 return false;
3411             }
3412 
3413             allShaderUniformBlocks[shaderType] = &uniformBlocks;
3414             ++numShadersHasUniformBlocks;
3415         }
3416     }
3417 
3418     if (combinedUniformBlocksCount > caps.maxCombinedUniformBlocks)
3419     {
3420         infoLog << "The sum of the number of active uniform blocks exceeds "
3421                    "MAX_COMBINED_UNIFORM_BLOCKS ("
3422                 << caps.maxCombinedUniformBlocks << ").";
3423         return false;
3424     }
3425 
3426     if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
3427                                       webglCompatibility))
3428     {
3429         return false;
3430     }
3431 
3432     if (version >= Version(3, 1))
3433     {
3434         *combinedShaderStorageBlocksCount                                         = 0u;
3435         GLuint numShadersHasShaderStorageBlocks                                   = 0u;
3436         ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
3437         for (ShaderType shaderType : AllShaderTypes())
3438         {
3439             Shader *shader = mState.mAttachedShaders[shaderType];
3440             if (!shader)
3441             {
3442                 continue;
3443             }
3444 
3445             const auto &shaderStorageBlocks = shader->getShaderStorageBlocks();
3446             if (!shaderStorageBlocks.empty())
3447             {
3448                 if (!ValidateInterfaceBlocksCount(
3449                         caps.maxShaderStorageBlocks[shaderType], shaderStorageBlocks, shaderType,
3450                         sh::BlockType::BLOCK_BUFFER, combinedShaderStorageBlocksCount, infoLog))
3451                 {
3452                     return false;
3453                 }
3454 
3455                 allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
3456                 ++numShadersHasShaderStorageBlocks;
3457             }
3458         }
3459 
3460         if (*combinedShaderStorageBlocksCount > caps.maxCombinedShaderStorageBlocks)
3461         {
3462             infoLog << "The sum of the number of active shader storage blocks exceeds "
3463                        "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
3464                     << caps.maxCombinedShaderStorageBlocks << ").";
3465             return false;
3466         }
3467 
3468         if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
3469                                           infoLog, webglCompatibility))
3470         {
3471             return false;
3472         }
3473     }
3474 
3475     return true;
3476 }
3477 
LinkValidateVariablesBase(const sh::ShaderVariable & variable1,const sh::ShaderVariable & variable2,bool validatePrecision,bool validateArraySize,std::string * mismatchedStructOrBlockMemberName)3478 LinkMismatchError Program::LinkValidateVariablesBase(const sh::ShaderVariable &variable1,
3479                                                      const sh::ShaderVariable &variable2,
3480                                                      bool validatePrecision,
3481                                                      bool validateArraySize,
3482                                                      std::string *mismatchedStructOrBlockMemberName)
3483 {
3484     if (variable1.type != variable2.type)
3485     {
3486         return LinkMismatchError::TYPE_MISMATCH;
3487     }
3488     if (validateArraySize && variable1.arraySizes != variable2.arraySizes)
3489     {
3490         return LinkMismatchError::ARRAY_SIZE_MISMATCH;
3491     }
3492     if (validatePrecision && variable1.precision != variable2.precision)
3493     {
3494         return LinkMismatchError::PRECISION_MISMATCH;
3495     }
3496     if (variable1.structName != variable2.structName)
3497     {
3498         return LinkMismatchError::STRUCT_NAME_MISMATCH;
3499     }
3500 
3501     if (variable1.fields.size() != variable2.fields.size())
3502     {
3503         return LinkMismatchError::FIELD_NUMBER_MISMATCH;
3504     }
3505     const unsigned int numMembers = static_cast<unsigned int>(variable1.fields.size());
3506     for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
3507     {
3508         const sh::ShaderVariable &member1 = variable1.fields[memberIndex];
3509         const sh::ShaderVariable &member2 = variable2.fields[memberIndex];
3510 
3511         if (member1.name != member2.name)
3512         {
3513             return LinkMismatchError::FIELD_NAME_MISMATCH;
3514         }
3515 
3516         LinkMismatchError linkErrorOnField = LinkValidateVariablesBase(
3517             member1, member2, validatePrecision, true, mismatchedStructOrBlockMemberName);
3518         if (linkErrorOnField != LinkMismatchError::NO_MISMATCH)
3519         {
3520             AddParentPrefix(member1.name, mismatchedStructOrBlockMemberName);
3521             return linkErrorOnField;
3522         }
3523     }
3524 
3525     return LinkMismatchError::NO_MISMATCH;
3526 }
3527 
LinkValidateVaryings(const sh::Varying & outputVarying,const sh::Varying & inputVarying,int shaderVersion,bool validateGeometryShaderInputVarying,std::string * mismatchedStructFieldName)3528 LinkMismatchError Program::LinkValidateVaryings(const sh::Varying &outputVarying,
3529                                                 const sh::Varying &inputVarying,
3530                                                 int shaderVersion,
3531                                                 bool validateGeometryShaderInputVarying,
3532                                                 std::string *mismatchedStructFieldName)
3533 {
3534     if (validateGeometryShaderInputVarying)
3535     {
3536         // [GL_EXT_geometry_shader] Section 11.1gs.4.3:
3537         // The OpenGL ES Shading Language doesn't support multi-dimensional arrays as shader inputs
3538         // or outputs.
3539         ASSERT(inputVarying.arraySizes.size() == 1u);
3540 
3541         // Geometry shader input varyings are not treated as arrays, so a vertex array output
3542         // varying cannot match a geometry shader input varying.
3543         // [GL_EXT_geometry_shader] Section 7.4.1:
3544         // Geometry shader per-vertex input variables and blocks are required to be declared as
3545         // arrays, with each element representing input or output values for a single vertex of a
3546         // multi-vertex primitive. For the purposes of interface matching, such variables and blocks
3547         // are treated as though they were not declared as arrays.
3548         if (outputVarying.isArray())
3549         {
3550             return LinkMismatchError::ARRAY_SIZE_MISMATCH;
3551         }
3552     }
3553 
3554     // Skip the validation on the array sizes between a vertex output varying and a geometry input
3555     // varying as it has been done before.
3556     LinkMismatchError linkError =
3557         LinkValidateVariablesBase(outputVarying, inputVarying, false,
3558                                   !validateGeometryShaderInputVarying, mismatchedStructFieldName);
3559     if (linkError != LinkMismatchError::NO_MISMATCH)
3560     {
3561         return linkError;
3562     }
3563 
3564     if (!sh::InterpolationTypesMatch(outputVarying.interpolation, inputVarying.interpolation))
3565     {
3566         return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
3567     }
3568 
3569     if (shaderVersion == 100 && outputVarying.isInvariant != inputVarying.isInvariant)
3570     {
3571         return LinkMismatchError::INVARIANCE_MISMATCH;
3572     }
3573 
3574     return LinkMismatchError::NO_MISMATCH;
3575 }
3576 
linkValidateBuiltInVaryings(InfoLog & infoLog) const3577 bool Program::linkValidateBuiltInVaryings(InfoLog &infoLog) const
3578 {
3579     Shader *vertexShader         = mState.mAttachedShaders[ShaderType::Vertex];
3580     Shader *fragmentShader       = mState.mAttachedShaders[ShaderType::Fragment];
3581     const auto &vertexVaryings   = vertexShader->getOutputVaryings();
3582     const auto &fragmentVaryings = fragmentShader->getInputVaryings();
3583     int shaderVersion            = vertexShader->getShaderVersion();
3584 
3585     if (shaderVersion != 100)
3586     {
3587         // Only ESSL 1.0 has restrictions on matching input and output invariance
3588         return true;
3589     }
3590 
3591     bool glPositionIsInvariant   = false;
3592     bool glPointSizeIsInvariant  = false;
3593     bool glFragCoordIsInvariant  = false;
3594     bool glPointCoordIsInvariant = false;
3595 
3596     for (const sh::Varying &varying : vertexVaryings)
3597     {
3598         if (!varying.isBuiltIn())
3599         {
3600             continue;
3601         }
3602         if (varying.name.compare("gl_Position") == 0)
3603         {
3604             glPositionIsInvariant = varying.isInvariant;
3605         }
3606         else if (varying.name.compare("gl_PointSize") == 0)
3607         {
3608             glPointSizeIsInvariant = varying.isInvariant;
3609         }
3610     }
3611 
3612     for (const sh::Varying &varying : fragmentVaryings)
3613     {
3614         if (!varying.isBuiltIn())
3615         {
3616             continue;
3617         }
3618         if (varying.name.compare("gl_FragCoord") == 0)
3619         {
3620             glFragCoordIsInvariant = varying.isInvariant;
3621         }
3622         else if (varying.name.compare("gl_PointCoord") == 0)
3623         {
3624             glPointCoordIsInvariant = varying.isInvariant;
3625         }
3626     }
3627 
3628     // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
3629     // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
3630     // Not requiring invariance to match is supported by:
3631     // dEQP, WebGL CTS, Nexus 5X GLES
3632     if (glFragCoordIsInvariant && !glPositionIsInvariant)
3633     {
3634         infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
3635                    "declared invariant.";
3636         return false;
3637     }
3638     if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
3639     {
3640         infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
3641                    "declared invariant.";
3642         return false;
3643     }
3644 
3645     return true;
3646 }
3647 
linkValidateTransformFeedback(const Version & version,InfoLog & infoLog,const ProgramMergedVaryings & varyings,const Caps & caps) const3648 bool Program::linkValidateTransformFeedback(const Version &version,
3649                                             InfoLog &infoLog,
3650                                             const ProgramMergedVaryings &varyings,
3651                                             const Caps &caps) const
3652 {
3653 
3654     // Validate the tf names regardless of the actual program varyings.
3655     std::set<std::string> uniqueNames;
3656     for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
3657     {
3658         if (version < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
3659         {
3660             infoLog << "Capture of array elements is undefined and not supported.";
3661             return false;
3662         }
3663         if (version >= Version(3, 1))
3664         {
3665             if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
3666             {
3667                 infoLog << "Two transform feedback varyings include the same array element ("
3668                         << tfVaryingName << ").";
3669                 return false;
3670             }
3671         }
3672         else
3673         {
3674             if (uniqueNames.count(tfVaryingName) > 0)
3675             {
3676                 infoLog << "Two transform feedback varyings specify the same output variable ("
3677                         << tfVaryingName << ").";
3678                 return false;
3679             }
3680         }
3681         uniqueNames.insert(tfVaryingName);
3682     }
3683 
3684     // Validate against program varyings.
3685     size_t totalComponents = 0;
3686     for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
3687     {
3688         std::vector<unsigned int> subscripts;
3689         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
3690 
3691         const sh::ShaderVariable *var = FindVaryingOrField(varyings, baseName);
3692         if (var == nullptr)
3693         {
3694             infoLog << "Transform feedback varying " << tfVaryingName
3695                     << " does not exist in the vertex shader.";
3696             return false;
3697         }
3698 
3699         // Validate the matching variable.
3700         if (var->isStruct())
3701         {
3702             infoLog << "Struct cannot be captured directly (" << baseName << ").";
3703             return false;
3704         }
3705 
3706         size_t elementCount   = 0;
3707         size_t componentCount = 0;
3708 
3709         if (var->isArray())
3710         {
3711             if (version < Version(3, 1))
3712             {
3713                 infoLog << "Capture of arrays is undefined and not supported.";
3714                 return false;
3715             }
3716 
3717             // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
3718             ASSERT(!var->isArrayOfArrays());
3719 
3720             if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
3721             {
3722                 infoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
3723                 return false;
3724             }
3725             elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
3726         }
3727         else
3728         {
3729             if (!subscripts.empty())
3730             {
3731                 infoLog << "Varying '" << baseName
3732                         << "' is not an array to be captured by element.";
3733                 return false;
3734             }
3735             elementCount = 1;
3736         }
3737 
3738         // TODO(jmadill): Investigate implementation limits on D3D11
3739         componentCount = VariableComponentCount(var->type) * elementCount;
3740         if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
3741             componentCount > caps.maxTransformFeedbackSeparateComponents)
3742         {
3743             infoLog << "Transform feedback varying " << tfVaryingName << " components ("
3744                     << componentCount << ") exceed the maximum separate components ("
3745                     << caps.maxTransformFeedbackSeparateComponents << ").";
3746             return false;
3747         }
3748 
3749         totalComponents += componentCount;
3750         if (mState.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
3751             totalComponents > caps.maxTransformFeedbackInterleavedComponents)
3752         {
3753             infoLog << "Transform feedback varying total components (" << totalComponents
3754                     << ") exceed the maximum interleaved components ("
3755                     << caps.maxTransformFeedbackInterleavedComponents << ").";
3756             return false;
3757         }
3758     }
3759     return true;
3760 }
3761 
linkValidateGlobalNames(InfoLog & infoLog) const3762 bool Program::linkValidateGlobalNames(InfoLog &infoLog) const
3763 {
3764     const std::vector<sh::Attribute> &attributes =
3765         mState.mAttachedShaders[ShaderType::Vertex]->getActiveAttributes();
3766     std::unordered_map<std::string, const sh::Uniform *> uniformMap;
3767     using BlockAndFieldPair =
3768         std::pair<const sh::InterfaceBlock *, const sh::InterfaceBlockField *>;
3769     std::unordered_map<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap;
3770 
3771     for (ShaderType shaderType : kAllGraphicsShaderTypes)
3772     {
3773         Shader *shader = mState.mAttachedShaders[shaderType];
3774         if (!shader)
3775         {
3776             continue;
3777         }
3778 
3779         // Build a map of Uniforms
3780         const std::vector<sh::Uniform> uniforms = shader->getUniforms();
3781         for (const auto &uniform : uniforms)
3782         {
3783             uniformMap[uniform.name] = &uniform;
3784         }
3785 
3786         // Build a map of Uniform Blocks
3787         // This will also detect any field name conflicts between Uniform Blocks without instance
3788         // names
3789         const std::vector<sh::InterfaceBlock> &uniformBlocks = shader->getUniformBlocks();
3790         for (const auto &uniformBlock : uniformBlocks)
3791         {
3792             // Only uniform blocks without an instance name can create a conflict with their field
3793             // names
3794             if (!uniformBlock.instanceName.empty())
3795             {
3796                 continue;
3797             }
3798 
3799             for (const auto &field : uniformBlock.fields)
3800             {
3801                 if (!uniformBlockFieldMap.count(field.name))
3802                 {
3803                     // First time we've seen this uniform block field name, so add the
3804                     // (Uniform Block, Field) pair immediately since there can't be a conflict yet
3805                     BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
3806                     std::vector<BlockAndFieldPair> newUniformBlockList;
3807                     newUniformBlockList.push_back(blockAndFieldPair);
3808                     uniformBlockFieldMap[field.name] = newUniformBlockList;
3809                     continue;
3810                 }
3811 
3812                 // We've seen this name before.
3813                 // We need to check each of the uniform blocks that contain a field with this name
3814                 // to see if there's a conflict or not.
3815                 std::vector<BlockAndFieldPair> prevBlockFieldPairs =
3816                     uniformBlockFieldMap[field.name];
3817                 for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
3818                 {
3819                     const sh::InterfaceBlock *prevUniformBlock = prevBlockFieldPair.first;
3820                     const sh::InterfaceBlockField *prevUniformBlockField =
3821                         prevBlockFieldPair.second;
3822 
3823                     if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
3824                     {
3825                         // The same uniform block should, by definition, contain the same field name
3826                         continue;
3827                     }
3828 
3829                     // The uniform blocks don't match, so check if the necessary field properties
3830                     // also match
3831                     if ((field.name == prevUniformBlockField->name) &&
3832                         (field.type == prevUniformBlockField->type) &&
3833                         (field.precision == prevUniformBlockField->precision))
3834                     {
3835                         infoLog << "Name conflicts between uniform block field names: "
3836                                 << field.name;
3837                         return false;
3838                     }
3839                 }
3840 
3841                 // No conflict, so record this pair
3842                 BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
3843                 uniformBlockFieldMap[field.name].push_back(blockAndFieldPair);
3844             }
3845         }
3846     }
3847 
3848     // Validate no uniform names conflict with attribute names
3849     for (const auto &attrib : attributes)
3850     {
3851         if (uniformMap.count(attrib.name))
3852         {
3853             infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
3854             return false;
3855         }
3856     }
3857 
3858     // Validate no Uniform Block fields conflict with other Uniforms
3859     for (const auto &uniformBlockField : uniformBlockFieldMap)
3860     {
3861         const std::string &fieldName = uniformBlockField.first;
3862         if (uniformMap.count(fieldName))
3863         {
3864             infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName;
3865             return false;
3866         }
3867     }
3868 
3869     return true;
3870 }
3871 
gatherTransformFeedbackVaryings(const ProgramMergedVaryings & varyings)3872 void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings)
3873 {
3874     // Gather the linked varyings that are used for transform feedback, they should all exist.
3875     mState.mLinkedTransformFeedbackVaryings.clear();
3876     for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
3877     {
3878         std::vector<unsigned int> subscripts;
3879         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
3880         size_t subscript     = GL_INVALID_INDEX;
3881         if (!subscripts.empty())
3882         {
3883             subscript = subscripts.back();
3884         }
3885         for (const auto &ref : varyings)
3886         {
3887             const sh::Varying *varying = ref.second.get();
3888             if (baseName == varying->name)
3889             {
3890                 mState.mLinkedTransformFeedbackVaryings.emplace_back(
3891                     *varying, static_cast<GLuint>(subscript));
3892                 break;
3893             }
3894             else if (varying->isStruct())
3895             {
3896                 GLuint fieldIndex = 0;
3897                 const auto *field = FindShaderVarField(*varying, tfVaryingName, &fieldIndex);
3898                 if (field != nullptr)
3899                 {
3900                     mState.mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
3901                     break;
3902                 }
3903             }
3904         }
3905     }
3906 }
3907 
getMergedVaryings() const3908 ProgramMergedVaryings Program::getMergedVaryings() const
3909 {
3910     ProgramMergedVaryings merged;
3911 
3912     for (const sh::Varying &varying :
3913          mState.mAttachedShaders[ShaderType::Vertex]->getOutputVaryings())
3914     {
3915         merged[varying.name].vertex = &varying;
3916     }
3917 
3918     for (const sh::Varying &varying :
3919          mState.mAttachedShaders[ShaderType::Fragment]->getInputVaryings())
3920     {
3921         merged[varying.name].fragment = &varying;
3922     }
3923 
3924     return merged;
3925 }
3926 
CompareOutputVariable(const sh::OutputVariable & a,const sh::OutputVariable & b)3927 bool CompareOutputVariable(const sh::OutputVariable &a, const sh::OutputVariable &b)
3928 {
3929     return a.getArraySizeProduct() > b.getArraySizeProduct();
3930 }
3931 
getOutputLocationForLink(const sh::OutputVariable & outputVariable) const3932 int Program::getOutputLocationForLink(const sh::OutputVariable &outputVariable) const
3933 {
3934     if (outputVariable.location != -1)
3935     {
3936         return outputVariable.location;
3937     }
3938     int apiLocation = mFragmentOutputLocations.getBinding(outputVariable);
3939     if (apiLocation != -1)
3940     {
3941         return apiLocation;
3942     }
3943     return -1;
3944 }
3945 
isOutputSecondaryForLink(const sh::OutputVariable & outputVariable) const3946 bool Program::isOutputSecondaryForLink(const sh::OutputVariable &outputVariable) const
3947 {
3948     if (outputVariable.index != -1)
3949     {
3950         ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
3951         return (outputVariable.index == 1);
3952     }
3953     int apiIndex = mFragmentOutputIndexes.getBinding(outputVariable);
3954     if (apiIndex != -1)
3955     {
3956         // Index layout qualifier from the shader takes precedence, so the index from the API is
3957         // checked only if the index was not set in the shader. This is not specified in the EXT
3958         // spec, but is specified in desktop OpenGL specs.
3959         return (apiIndex == 1);
3960     }
3961     // EXT_blend_func_extended: Outputs get index 0 by default.
3962     return false;
3963 }
3964 
3965 namespace
3966 {
3967 
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)3968 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
3969                             unsigned int baseLocation,
3970                             unsigned int elementCount,
3971                             const std::vector<VariableLocation> &reservedLocations,
3972                             unsigned int variableIndex)
3973 {
3974     if (baseLocation + elementCount > outputLocations.size())
3975     {
3976         elementCount = baseLocation < outputLocations.size()
3977                            ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
3978                            : 0;
3979     }
3980     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
3981     {
3982         const unsigned int location = baseLocation + elementIndex;
3983         if (outputLocations[location].used())
3984         {
3985             VariableLocation locationInfo(elementIndex, variableIndex);
3986             if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
3987                 reservedLocations.end())
3988             {
3989                 return true;
3990             }
3991         }
3992     }
3993     return false;
3994 }
3995 
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)3996 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
3997                            unsigned int baseLocation,
3998                            unsigned int elementCount,
3999                            const std::vector<VariableLocation> &reservedLocations,
4000                            unsigned int variableIndex)
4001 {
4002     if (baseLocation + elementCount > outputLocations.size())
4003     {
4004         outputLocations.resize(baseLocation + elementCount);
4005     }
4006     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4007     {
4008         VariableLocation locationInfo(elementIndex, variableIndex);
4009         if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4010             reservedLocations.end())
4011         {
4012             const unsigned int location = baseLocation + elementIndex;
4013             outputLocations[location]   = locationInfo;
4014         }
4015     }
4016 }
4017 
4018 }  // anonymous namespace
4019 
linkOutputVariables(const Caps & caps,const Extensions & extensions,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount)4020 bool Program::linkOutputVariables(const Caps &caps,
4021                                   const Extensions &extensions,
4022                                   const Version &version,
4023                                   GLuint combinedImageUniformsCount,
4024                                   GLuint combinedShaderStorageBlocksCount)
4025 {
4026     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
4027     ASSERT(fragmentShader != nullptr);
4028 
4029     ASSERT(mState.mOutputVariableTypes.empty());
4030     ASSERT(mState.mActiveOutputVariables.none());
4031     ASSERT(mState.mDrawBufferTypeMask.none());
4032 
4033     const auto &outputVariables = fragmentShader->getActiveOutputVariables();
4034     // Gather output variable types
4035     for (const auto &outputVariable : outputVariables)
4036     {
4037         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
4038             outputVariable.name != "gl_FragData")
4039         {
4040             continue;
4041         }
4042 
4043         unsigned int baseLocation =
4044             (outputVariable.location == -1 ? 0u
4045                                            : static_cast<unsigned int>(outputVariable.location));
4046 
4047         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4048         // structures, so we may use getBasicTypeElementCount().
4049         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4050         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4051         {
4052             const unsigned int location = baseLocation + elementIndex;
4053             if (location >= mState.mOutputVariableTypes.size())
4054             {
4055                 mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
4056             }
4057             ASSERT(location < mState.mActiveOutputVariables.size());
4058             mState.mActiveOutputVariables.set(location);
4059             mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
4060             ComponentType componentType =
4061                 GLenumToComponentType(mState.mOutputVariableTypes[location]);
4062             SetComponentTypeMask(componentType, location, &mState.mDrawBufferTypeMask);
4063         }
4064     }
4065 
4066     if (version >= ES_3_1)
4067     {
4068         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
4069         // A link error will be generated if the sum of the number of active image uniforms used in
4070         // all shaders, the number of active shader storage blocks, and the number of active
4071         // fragment shader outputs exceeds the implementation-dependent value of
4072         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
4073         if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
4074                 mState.mActiveOutputVariables.count() >
4075             caps.maxCombinedShaderOutputResources)
4076         {
4077             mInfoLog
4078                 << "The sum of the number of active image uniforms, active shader storage blocks "
4079                    "and active fragment shader outputs exceeds "
4080                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
4081                 << caps.maxCombinedShaderOutputResources << ")";
4082             return false;
4083         }
4084     }
4085 
4086     // Skip this step for GLES2 shaders.
4087     if (fragmentShader->getShaderVersion() == 100)
4088         return true;
4089 
4090     mState.mOutputVariables = outputVariables;
4091     // TODO(jmadill): any caps validation here?
4092 
4093     for (sh::OutputVariable &outputVariable : mState.mOutputVariables)
4094     {
4095         if (outputVariable.isArray())
4096         {
4097             // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active
4098             // Resources and including [0] at the end of array variable names.
4099             outputVariable.name += "[0]";
4100             outputVariable.mappedName += "[0]";
4101         }
4102     }
4103 
4104     // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
4105     // output array in explicit terms.
4106     //
4107     // Assuming fragData is an output array, you can defend the position that:
4108     // P1) you must support binding "fragData" because it's specified
4109     // P2) you must support querying "fragData[x]" because it's specified
4110     // P3) you must support binding "fragData[0]" because it's a frequently used pattern
4111     //
4112     // Then you can make the leap of faith:
4113     // P4) you must support binding "fragData[x]" because you support "fragData[0]"
4114     // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
4115     //
4116     // The spec brings in the "world of arrays" when it mentions binding the arrays and the
4117     // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
4118     // must infer the only possible interpretation (?). Note again: this need of interpretation
4119     // might be completely off of what GL spec logic is.
4120     //
4121     // The other complexity is that unless you implement this feature, it's hard to understand what
4122     // should happen when the client invokes the feature. You cannot add an additional error as it
4123     // is not specified. One can ignore it, but obviously it creates the discrepancies...
4124 
4125     std::vector<VariableLocation> reservedLocations;
4126 
4127     // Process any output API bindings for arrays that don't alias to the first element.
4128     for (const auto &binding : mFragmentOutputLocations)
4129     {
4130         size_t nameLengthWithoutArrayIndex;
4131         unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
4132         if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
4133         {
4134             continue;
4135         }
4136         for (unsigned int outputVariableIndex = 0;
4137              outputVariableIndex < mState.mOutputVariables.size(); outputVariableIndex++)
4138         {
4139             const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
4140             // Check that the binding corresponds to an output array and its array index fits.
4141             if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
4142                 !angle::BeginsWith(outputVariable.name, binding.first,
4143                                    nameLengthWithoutArrayIndex) ||
4144                 arrayIndex >= outputVariable.getOutermostArraySize())
4145             {
4146                 continue;
4147             }
4148 
4149             // Get the API index that corresponds to this exact binding.
4150             // This index may differ from the index used for the array's base.
4151             auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1
4152                                         ? mState.mSecondaryOutputLocations
4153                                         : mState.mOutputLocations;
4154             unsigned int location = binding.second.location;
4155             VariableLocation locationInfo(arrayIndex, outputVariableIndex);
4156             if (location >= outputLocations.size())
4157             {
4158                 outputLocations.resize(location + 1);
4159             }
4160             if (outputLocations[location].used())
4161             {
4162                 mInfoLog << "Location of variable " << outputVariable.name
4163                          << " conflicts with another variable.";
4164                 return false;
4165             }
4166             outputLocations[location] = locationInfo;
4167 
4168             // Note the array binding location so that it can be skipped later.
4169             reservedLocations.push_back(locationInfo);
4170         }
4171     }
4172 
4173     // Reserve locations for output variables whose location is fixed in the shader or through the
4174     // API. Otherwise, the remaining unallocated outputs will be processed later.
4175     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
4176          outputVariableIndex++)
4177     {
4178         const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
4179 
4180         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4181         if (outputVariable.isBuiltIn())
4182             continue;
4183 
4184         int fixedLocation = getOutputLocationForLink(outputVariable);
4185         if (fixedLocation == -1)
4186         {
4187             // Here we're only reserving locations for variables whose location is fixed.
4188             continue;
4189         }
4190         unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
4191 
4192         auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4193                                     ? mState.mSecondaryOutputLocations
4194                                     : mState.mOutputLocations;
4195 
4196         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4197         // structures, so we may use getBasicTypeElementCount().
4198         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4199         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
4200                                    outputVariableIndex))
4201         {
4202             mInfoLog << "Location of variable " << outputVariable.name
4203                      << " conflicts with another variable.";
4204             return false;
4205         }
4206         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4207                               outputVariableIndex);
4208     }
4209 
4210     // Here we assign locations for the output variables that don't yet have them. Note that we're
4211     // not necessarily able to fit the variables optimally, since then we might have to try
4212     // different arrangements of output arrays. Now we just assign the locations in the order that
4213     // we got the output variables. The spec isn't clear on what kind of algorithm is required for
4214     // finding locations for the output variables, so this should be acceptable at least for now.
4215     GLuint maxLocation = caps.maxDrawBuffers;
4216     if (!mState.mSecondaryOutputLocations.empty())
4217     {
4218         // EXT_blend_func_extended: Program outputs will be validated against
4219         // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
4220         maxLocation = extensions.maxDualSourceDrawBuffers;
4221     }
4222 
4223     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
4224          outputVariableIndex++)
4225     {
4226         const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
4227 
4228         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4229         if (outputVariable.isBuiltIn())
4230             continue;
4231 
4232         int fixedLocation     = getOutputLocationForLink(outputVariable);
4233         auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4234                                     ? mState.mSecondaryOutputLocations
4235                                     : mState.mOutputLocations;
4236         unsigned int baseLocation = 0;
4237         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4238         if (fixedLocation != -1)
4239         {
4240             // Secondary inputs might have caused the max location to drop below what has already
4241             // been explicitly assigned locations. Check for any fixed locations above the max
4242             // that should cause linking to fail.
4243             baseLocation = static_cast<unsigned int>(fixedLocation);
4244         }
4245         else
4246         {
4247             // No fixed location, so try to fit the output in unassigned locations.
4248             // Try baseLocations starting from 0 one at a time and see if the variable fits.
4249             while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
4250                                           reservedLocations, outputVariableIndex))
4251             {
4252                 baseLocation++;
4253             }
4254             AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4255                                   outputVariableIndex);
4256         }
4257 
4258         // Check for any elements assigned above the max location that are actually used.
4259         if (baseLocation + elementCount > maxLocation &&
4260             (baseLocation >= maxLocation ||
4261              FindUsedOutputLocation(outputLocations, maxLocation,
4262                                     baseLocation + elementCount - maxLocation, reservedLocations,
4263                                     outputVariableIndex)))
4264         {
4265             // EXT_blend_func_extended: Linking can fail:
4266             // "if the explicit binding assignments do not leave enough space for the linker to
4267             // automatically assign a location for a varying out array, which requires multiple
4268             // contiguous locations."
4269             mInfoLog << "Could not fit output variable into available locations: "
4270                      << outputVariable.name;
4271             return false;
4272         }
4273     }
4274 
4275     return true;
4276 }
4277 
setUniformValuesFromBindingQualifiers()4278 void Program::setUniformValuesFromBindingQualifiers()
4279 {
4280     for (unsigned int samplerIndex : mState.mSamplerUniformRange)
4281     {
4282         const auto &samplerUniform = mState.mUniforms[samplerIndex];
4283         if (samplerUniform.binding != -1)
4284         {
4285             GLint location = getUniformLocation(samplerUniform.name);
4286             ASSERT(location != -1);
4287             std::vector<GLint> boundTextureUnits;
4288             for (unsigned int elementIndex = 0;
4289                  elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
4290             {
4291                 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
4292             }
4293 
4294             // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
4295             // We know it's safe not to notify the Context because this is only called after link.
4296             setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
4297                           boundTextureUnits.data());
4298         }
4299     }
4300 }
4301 
initInterfaceBlockBindings()4302 void Program::initInterfaceBlockBindings()
4303 {
4304     // Set initial bindings from shader.
4305     for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++)
4306     {
4307         InterfaceBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
4308         bindUniformBlock(blockIndex, uniformBlock.binding);
4309     }
4310 }
4311 
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)4312 void Program::updateSamplerUniform(Context *context,
4313                                    const VariableLocation &locationInfo,
4314                                    GLsizei clampedCount,
4315                                    const GLint *v)
4316 {
4317     ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
4318     GLuint samplerIndex            = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
4319     SamplerBinding &samplerBinding = mState.mSamplerBindings[samplerIndex];
4320     std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
4321 
4322     if (samplerBinding.unreferenced)
4323         return;
4324 
4325     // Update the sampler uniforms.
4326     for (GLsizei arrayIndex = 0; arrayIndex < clampedCount; ++arrayIndex)
4327     {
4328         GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
4329         GLint newTextureUnit = v[arrayIndex];
4330 
4331         if (oldTextureUnit == newTextureUnit)
4332             continue;
4333 
4334         boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
4335 
4336         // Update the reference counts.
4337         uint32_t &oldRefCount = mState.mActiveSamplerRefCounts[oldTextureUnit];
4338         uint32_t &newRefCount = mState.mActiveSamplerRefCounts[newTextureUnit];
4339         ASSERT(oldRefCount > 0);
4340         ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
4341         oldRefCount--;
4342         newRefCount++;
4343 
4344         // Check for binding type change.
4345         TextureType &newSamplerType     = mState.mActiveSamplerTypes[newTextureUnit];
4346         TextureType &oldSamplerType     = mState.mActiveSamplerTypes[oldTextureUnit];
4347         SamplerFormat &newSamplerFormat = mState.mActiveSamplerFormats[newTextureUnit];
4348         SamplerFormat &oldSamplerFormat = mState.mActiveSamplerFormats[oldTextureUnit];
4349 
4350         if (newRefCount == 1)
4351         {
4352             newSamplerType   = samplerBinding.textureType;
4353             newSamplerFormat = samplerBinding.format;
4354             mState.mActiveSamplersMask.set(newTextureUnit);
4355         }
4356         else
4357         {
4358             if (newSamplerType != samplerBinding.textureType)
4359             {
4360                 // Conflict detected. Ensure we reset it properly.
4361                 newSamplerType = TextureType::InvalidEnum;
4362             }
4363             if (newSamplerFormat != samplerBinding.format)
4364             {
4365                 newSamplerFormat = SamplerFormat::InvalidEnum;
4366             }
4367         }
4368 
4369         // Unset previously active sampler.
4370         if (oldRefCount == 0)
4371         {
4372             oldSamplerType   = TextureType::InvalidEnum;
4373             oldSamplerFormat = SamplerFormat::InvalidEnum;
4374             mState.mActiveSamplersMask.reset(oldTextureUnit);
4375         }
4376         else
4377         {
4378             if (oldSamplerType == TextureType::InvalidEnum ||
4379                 oldSamplerFormat == SamplerFormat::InvalidEnum)
4380             {
4381                 // Previous conflict. Check if this new change fixed the conflict.
4382                 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
4383             }
4384         }
4385 
4386         // Notify context.
4387         if (context)
4388         {
4389             context->onSamplerUniformChange(newTextureUnit);
4390             context->onSamplerUniformChange(oldTextureUnit);
4391         }
4392     }
4393 
4394     // Invalidate the validation cache.
4395     mCachedValidateSamplersResult.reset();
4396 }
4397 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)4398 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
4399 {
4400     bool foundBinding         = false;
4401     TextureType foundType     = TextureType::InvalidEnum;
4402     SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
4403 
4404     for (const SamplerBinding &binding : mSamplerBindings)
4405     {
4406         if (binding.unreferenced)
4407             continue;
4408 
4409         // A conflict exists if samplers of different types are sourced by the same texture unit.
4410         // We need to check all bound textures to detect this error case.
4411         for (GLuint textureUnit : binding.boundTextureUnits)
4412         {
4413             if (textureUnit == textureUnitIndex)
4414             {
4415                 if (!foundBinding)
4416                 {
4417                     foundBinding = true;
4418                     foundType    = binding.textureType;
4419                     foundFormat  = binding.format;
4420                 }
4421                 else
4422                 {
4423                     if (foundType != binding.textureType)
4424                     {
4425                         foundType = TextureType::InvalidEnum;
4426                     }
4427                     if (foundFormat != binding.format)
4428                     {
4429                         foundFormat = SamplerFormat::InvalidEnum;
4430                     }
4431                 }
4432             }
4433         }
4434     }
4435 
4436     mActiveSamplerTypes[textureUnitIndex]   = foundType;
4437     mActiveSamplerFormats[textureUnitIndex] = foundFormat;
4438 }
4439 
4440 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)4441 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
4442                                    GLsizei count,
4443                                    int vectorSize,
4444                                    const T *v)
4445 {
4446     if (count == 1)
4447         return 1;
4448 
4449     const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
4450 
4451     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4452     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4453     unsigned int remainingElements =
4454         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4455     GLsizei maxElementCount =
4456         static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
4457 
4458     if (count * vectorSize > maxElementCount)
4459     {
4460         return maxElementCount / vectorSize;
4461     }
4462 
4463     return count;
4464 }
4465 
4466 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(GLint location,GLsizei count,GLboolean transpose,const T * v)4467 GLsizei Program::clampMatrixUniformCount(GLint location,
4468                                          GLsizei count,
4469                                          GLboolean transpose,
4470                                          const T *v)
4471 {
4472     const VariableLocation &locationInfo = mState.mUniformLocations[location];
4473 
4474     if (!transpose)
4475     {
4476         return clampUniformCount(locationInfo, count, cols * rows, v);
4477     }
4478 
4479     const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
4480 
4481     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4482     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4483     unsigned int remainingElements =
4484         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4485     return std::min(count, static_cast<GLsizei>(remainingElements));
4486 }
4487 
4488 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
4489 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
4490 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,GLint location,GLenum nativeType,int components) const4491 void Program::getUniformInternal(const Context *context,
4492                                  DestT *dataOut,
4493                                  GLint location,
4494                                  GLenum nativeType,
4495                                  int components) const
4496 {
4497     switch (nativeType)
4498     {
4499         case GL_BOOL:
4500         {
4501             GLint tempValue[16] = {0};
4502             mProgram->getUniformiv(context, location, tempValue);
4503             UniformStateQueryCastLoop<GLboolean>(
4504                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4505             break;
4506         }
4507         case GL_INT:
4508         {
4509             GLint tempValue[16] = {0};
4510             mProgram->getUniformiv(context, location, tempValue);
4511             UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4512                                              components);
4513             break;
4514         }
4515         case GL_UNSIGNED_INT:
4516         {
4517             GLuint tempValue[16] = {0};
4518             mProgram->getUniformuiv(context, location, tempValue);
4519             UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4520                                               components);
4521             break;
4522         }
4523         case GL_FLOAT:
4524         {
4525             GLfloat tempValue[16] = {0};
4526             mProgram->getUniformfv(context, location, tempValue);
4527             UniformStateQueryCastLoop<GLfloat>(
4528                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4529             break;
4530         }
4531         default:
4532             UNREACHABLE();
4533             break;
4534     }
4535 }
4536 
syncState(const Context * context)4537 angle::Result Program::syncState(const Context *context)
4538 {
4539     if (mDirtyBits.any())
4540     {
4541         ASSERT(mLinkResolved);
4542         ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
4543         mDirtyBits.reset();
4544     }
4545 
4546     return angle::Result::Continue;
4547 }
4548 
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const4549 void Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
4550 {
4551     BinaryOutputStream stream;
4552 
4553     stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
4554                       ANGLE_COMMIT_HASH_SIZE);
4555 
4556     // nullptr context is supported when computing binary length.
4557     if (context)
4558     {
4559         stream.writeInt(context->getClientVersion().major);
4560         stream.writeInt(context->getClientVersion().minor);
4561     }
4562     else
4563     {
4564         stream.writeInt(2);
4565         stream.writeInt(0);
4566     }
4567 
4568     const auto &computeLocalSize = mState.getComputeShaderLocalSize();
4569 
4570     stream.writeInt(computeLocalSize[0]);
4571     stream.writeInt(computeLocalSize[1]);
4572     stream.writeInt(computeLocalSize[2]);
4573 
4574     ASSERT(mState.mGeometryShaderInvocations >= 1 && mState.mGeometryShaderMaxVertices >= 0);
4575     stream.writeEnum(mState.mGeometryShaderInputPrimitiveType);
4576     stream.writeEnum(mState.mGeometryShaderOutputPrimitiveType);
4577     stream.writeInt(mState.mGeometryShaderInvocations);
4578     stream.writeInt(mState.mGeometryShaderMaxVertices);
4579 
4580     stream.writeInt(mState.mNumViews);
4581 
4582     stream.writeInt(mState.mMaxActiveAttribLocation);
4583 
4584     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
4585                   "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
4586     stream.writeInt(static_cast<int>(mState.mAttributesTypeMask.to_ulong()));
4587     stream.writeInt(static_cast<int>(mState.mAttributesMask.to_ulong()));
4588 
4589     stream.writeInt(mState.getActiveAttribLocationsMask().to_ulong());
4590 
4591     stream.writeInt(mState.getAttributes().size());
4592     for (const sh::Attribute &attrib : mState.getAttributes())
4593     {
4594         WriteShaderVar(&stream, attrib);
4595         stream.writeInt(attrib.location);
4596     }
4597 
4598     stream.writeInt(mState.getUniforms().size());
4599     for (const LinkedUniform &uniform : mState.getUniforms())
4600     {
4601         WriteShaderVar(&stream, uniform);
4602 
4603         // FIXME: referenced
4604 
4605         stream.writeInt(uniform.bufferIndex);
4606         WriteBlockMemberInfo(&stream, uniform.blockInfo);
4607 
4608         // Active shader info
4609         for (ShaderType shaderType : gl::AllShaderTypes())
4610         {
4611             stream.writeInt(uniform.isActive(shaderType));
4612         }
4613     }
4614 
4615     stream.writeInt(mState.getUniformLocations().size());
4616     for (const auto &variable : mState.getUniformLocations())
4617     {
4618         stream.writeInt(variable.arrayIndex);
4619         stream.writeIntOrNegOne(variable.index);
4620         stream.writeInt(variable.ignored);
4621     }
4622 
4623     stream.writeInt(mState.getUniformBlocks().size());
4624     for (const InterfaceBlock &uniformBlock : mState.getUniformBlocks())
4625     {
4626         WriteInterfaceBlock(&stream, uniformBlock);
4627     }
4628 
4629     stream.writeInt(mState.getBufferVariables().size());
4630     for (const BufferVariable &bufferVariable : mState.getBufferVariables())
4631     {
4632         WriteBufferVariable(&stream, bufferVariable);
4633     }
4634 
4635     stream.writeInt(mState.getShaderStorageBlocks().size());
4636     for (const InterfaceBlock &shaderStorageBlock : mState.getShaderStorageBlocks())
4637     {
4638         WriteInterfaceBlock(&stream, shaderStorageBlock);
4639     }
4640 
4641     stream.writeInt(mState.mAtomicCounterBuffers.size());
4642     for (const auto &atomicCounterBuffer : mState.mAtomicCounterBuffers)
4643     {
4644         WriteShaderVariableBuffer(&stream, atomicCounterBuffer);
4645     }
4646 
4647     // Warn the app layer if saving a binary with unsupported transform feedback.
4648     if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
4649         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4650     {
4651         WARN() << "Saving program binary with transform feedback, which is not supported on this "
4652                   "driver.";
4653     }
4654 
4655     stream.writeInt(mState.getLinkedTransformFeedbackVaryings().size());
4656     for (const auto &var : mState.getLinkedTransformFeedbackVaryings())
4657     {
4658         stream.writeIntVector(var.arraySizes);
4659         stream.writeInt(var.type);
4660         stream.writeString(var.name);
4661 
4662         stream.writeIntOrNegOne(var.arrayIndex);
4663     }
4664 
4665     stream.writeInt(mState.getTransformFeedbackBufferMode());
4666 
4667     stream.writeInt(mState.getOutputVariables().size());
4668     for (const sh::OutputVariable &output : mState.getOutputVariables())
4669     {
4670         WriteShaderVar(&stream, output);
4671         stream.writeInt(output.location);
4672         stream.writeInt(output.index);
4673     }
4674 
4675     stream.writeInt(mState.getOutputLocations().size());
4676     for (const auto &outputVar : mState.getOutputLocations())
4677     {
4678         stream.writeInt(outputVar.arrayIndex);
4679         stream.writeIntOrNegOne(outputVar.index);
4680         stream.writeInt(outputVar.ignored);
4681     }
4682 
4683     stream.writeInt(mState.getSecondaryOutputLocations().size());
4684     for (const auto &outputVar : mState.getSecondaryOutputLocations())
4685     {
4686         stream.writeInt(outputVar.arrayIndex);
4687         stream.writeIntOrNegOne(outputVar.index);
4688         stream.writeInt(outputVar.ignored);
4689     }
4690 
4691     stream.writeInt(mState.mOutputVariableTypes.size());
4692     for (const auto &outputVariableType : mState.mOutputVariableTypes)
4693     {
4694         stream.writeInt(outputVariableType);
4695     }
4696 
4697     static_assert(
4698         IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4699         "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
4700     stream.writeInt(static_cast<int>(mState.mDrawBufferTypeMask.to_ulong()));
4701     stream.writeInt(static_cast<int>(mState.mActiveOutputVariables.to_ulong()));
4702 
4703     stream.writeInt(mState.getSamplerUniformRange().low());
4704     stream.writeInt(mState.getSamplerUniformRange().high());
4705 
4706     stream.writeInt(mState.getSamplerBindings().size());
4707     for (const auto &samplerBinding : mState.getSamplerBindings())
4708     {
4709         stream.writeEnum(samplerBinding.textureType);
4710         stream.writeEnum(samplerBinding.format);
4711         stream.writeInt(samplerBinding.boundTextureUnits.size());
4712         stream.writeInt(samplerBinding.unreferenced);
4713     }
4714 
4715     stream.writeInt(mState.getImageUniformRange().low());
4716     stream.writeInt(mState.getImageUniformRange().high());
4717 
4718     stream.writeInt(mState.getImageBindings().size());
4719     for (const auto &imageBinding : mState.getImageBindings())
4720     {
4721         stream.writeInt(imageBinding.boundImageUnits.size());
4722         for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
4723         {
4724             stream.writeInt(imageBinding.boundImageUnits[i]);
4725         }
4726     }
4727 
4728     stream.writeInt(mState.getAtomicCounterUniformRange().low());
4729     stream.writeInt(mState.getAtomicCounterUniformRange().high());
4730 
4731     stream.writeInt(mState.getLinkedShaderStages().to_ulong());
4732 
4733     mProgram->save(context, &stream);
4734 
4735     ASSERT(binaryOut);
4736     binaryOut->resize(stream.length());
4737     memcpy(binaryOut->data(), stream.data(), stream.length());
4738 }
4739 
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)4740 angle::Result Program::deserialize(const Context *context,
4741                                    BinaryInputStream &stream,
4742                                    InfoLog &infoLog)
4743 {
4744     unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
4745     stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
4746     if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
4747         0)
4748     {
4749         infoLog << "Invalid program binary version.";
4750         return angle::Result::Incomplete;
4751     }
4752 
4753     int majorVersion = stream.readInt<int>();
4754     int minorVersion = stream.readInt<int>();
4755     if (majorVersion != context->getClientMajorVersion() ||
4756         minorVersion != context->getClientMinorVersion())
4757     {
4758         infoLog << "Cannot load program binaries across different ES context versions.";
4759         return angle::Result::Incomplete;
4760     }
4761 
4762     mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
4763     mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
4764     mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
4765 
4766     mState.mGeometryShaderInputPrimitiveType  = stream.readEnum<PrimitiveMode>();
4767     mState.mGeometryShaderOutputPrimitiveType = stream.readEnum<PrimitiveMode>();
4768     mState.mGeometryShaderInvocations         = stream.readInt<int>();
4769     mState.mGeometryShaderMaxVertices         = stream.readInt<int>();
4770 
4771     mState.mNumViews = stream.readInt<int>();
4772 
4773     mState.mMaxActiveAttribLocation = stream.readInt<unsigned int>();
4774 
4775     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
4776                   "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
4777     mState.mAttributesTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4778     mState.mAttributesMask     = stream.readInt<gl::AttributesMask>();
4779 
4780     static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
4781                   "Too many vertex attribs for mask");
4782     mState.mActiveAttribLocationsMask = stream.readInt<gl::AttributesMask>();
4783 
4784     unsigned int attribCount = stream.readInt<unsigned int>();
4785     ASSERT(mState.mAttributes.empty());
4786     for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
4787     {
4788         sh::Attribute attrib;
4789         LoadShaderVar(&stream, &attrib);
4790         attrib.location = stream.readInt<int>();
4791         mState.mAttributes.push_back(attrib);
4792     }
4793 
4794     unsigned int uniformCount = stream.readInt<unsigned int>();
4795     ASSERT(mState.mUniforms.empty());
4796     for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
4797     {
4798         LinkedUniform uniform;
4799         LoadShaderVar(&stream, &uniform);
4800 
4801         uniform.bufferIndex = stream.readInt<int>();
4802         LoadBlockMemberInfo(&stream, &uniform.blockInfo);
4803 
4804         uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
4805 
4806         // Active shader info
4807         for (ShaderType shaderType : gl::AllShaderTypes())
4808         {
4809             uniform.setActive(shaderType, stream.readBool());
4810         }
4811 
4812         mState.mUniforms.push_back(uniform);
4813     }
4814 
4815     const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
4816     ASSERT(mState.mUniformLocations.empty());
4817     for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
4818          uniformIndexIndex++)
4819     {
4820         VariableLocation variable;
4821         stream.readInt(&variable.arrayIndex);
4822         stream.readInt(&variable.index);
4823         stream.readBool(&variable.ignored);
4824 
4825         mState.mUniformLocations.push_back(variable);
4826     }
4827 
4828     unsigned int uniformBlockCount = stream.readInt<unsigned int>();
4829     ASSERT(mState.mUniformBlocks.empty());
4830     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
4831          ++uniformBlockIndex)
4832     {
4833         InterfaceBlock uniformBlock;
4834         LoadInterfaceBlock(&stream, &uniformBlock);
4835         mState.mUniformBlocks.push_back(uniformBlock);
4836 
4837         mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
4838     }
4839 
4840     unsigned int bufferVariableCount = stream.readInt<unsigned int>();
4841     ASSERT(mState.mBufferVariables.empty());
4842     for (unsigned int index = 0; index < bufferVariableCount; ++index)
4843     {
4844         BufferVariable bufferVariable;
4845         LoadBufferVariable(&stream, &bufferVariable);
4846         mState.mBufferVariables.push_back(bufferVariable);
4847     }
4848 
4849     unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>();
4850     ASSERT(mState.mShaderStorageBlocks.empty());
4851     for (unsigned int shaderStorageBlockIndex = 0;
4852          shaderStorageBlockIndex < shaderStorageBlockCount; ++shaderStorageBlockIndex)
4853     {
4854         InterfaceBlock shaderStorageBlock;
4855         LoadInterfaceBlock(&stream, &shaderStorageBlock);
4856         mState.mShaderStorageBlocks.push_back(shaderStorageBlock);
4857     }
4858 
4859     unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>();
4860     ASSERT(mState.mAtomicCounterBuffers.empty());
4861     for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
4862     {
4863         AtomicCounterBuffer atomicCounterBuffer;
4864         LoadShaderVariableBuffer(&stream, &atomicCounterBuffer);
4865 
4866         mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer);
4867     }
4868 
4869     unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
4870 
4871     // Reject programs that use transform feedback varyings if the hardware cannot support them.
4872     if (transformFeedbackVaryingCount > 0 &&
4873         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4874     {
4875         infoLog << "Current driver does not support transform feedback in binary programs.";
4876         return angle::Result::Incomplete;
4877     }
4878 
4879     ASSERT(mState.mLinkedTransformFeedbackVaryings.empty());
4880     for (unsigned int transformFeedbackVaryingIndex = 0;
4881          transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
4882          ++transformFeedbackVaryingIndex)
4883     {
4884         sh::Varying varying;
4885         stream.readIntVector<unsigned int>(&varying.arraySizes);
4886         stream.readInt(&varying.type);
4887         stream.readString(&varying.name);
4888 
4889         GLuint arrayIndex = stream.readInt<GLuint>();
4890 
4891         mState.mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
4892     }
4893 
4894     stream.readInt(&mState.mTransformFeedbackBufferMode);
4895 
4896     unsigned int outputCount = stream.readInt<unsigned int>();
4897     ASSERT(mState.mOutputVariables.empty());
4898     for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
4899     {
4900         sh::OutputVariable output;
4901         LoadShaderVar(&stream, &output);
4902         output.location = stream.readInt<int>();
4903         output.index    = stream.readInt<int>();
4904         mState.mOutputVariables.push_back(output);
4905     }
4906 
4907     unsigned int outputVarCount = stream.readInt<unsigned int>();
4908     ASSERT(mState.mOutputLocations.empty());
4909     for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
4910     {
4911         VariableLocation locationData;
4912         stream.readInt(&locationData.arrayIndex);
4913         stream.readInt(&locationData.index);
4914         stream.readBool(&locationData.ignored);
4915         mState.mOutputLocations.push_back(locationData);
4916     }
4917 
4918     unsigned int secondaryOutputVarCount = stream.readInt<unsigned int>();
4919     ASSERT(mState.mSecondaryOutputLocations.empty());
4920     for (unsigned int outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex)
4921     {
4922         VariableLocation locationData;
4923         stream.readInt(&locationData.arrayIndex);
4924         stream.readInt(&locationData.index);
4925         stream.readBool(&locationData.ignored);
4926         mState.mSecondaryOutputLocations.push_back(locationData);
4927     }
4928 
4929     unsigned int outputTypeCount = stream.readInt<unsigned int>();
4930     for (unsigned int outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
4931     {
4932         mState.mOutputVariableTypes.push_back(stream.readInt<GLenum>());
4933     }
4934 
4935     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4936                   "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
4937                   "into 32 bits each");
4938     mState.mDrawBufferTypeMask    = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4939     mState.mActiveOutputVariables = stream.readInt<gl::DrawBufferMask>();
4940 
4941     unsigned int samplerRangeLow  = stream.readInt<unsigned int>();
4942     unsigned int samplerRangeHigh = stream.readInt<unsigned int>();
4943     mState.mSamplerUniformRange   = RangeUI(samplerRangeLow, samplerRangeHigh);
4944     unsigned int samplerCount     = stream.readInt<unsigned int>();
4945     for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
4946     {
4947         TextureType textureType = stream.readEnum<TextureType>();
4948         SamplerFormat format    = stream.readEnum<SamplerFormat>();
4949         size_t bindingCount     = stream.readInt<size_t>();
4950         bool unreferenced       = stream.readBool();
4951         mState.mSamplerBindings.emplace_back(textureType, format, bindingCount, unreferenced);
4952     }
4953 
4954     unsigned int imageRangeLow     = stream.readInt<unsigned int>();
4955     unsigned int imageRangeHigh    = stream.readInt<unsigned int>();
4956     mState.mImageUniformRange      = RangeUI(imageRangeLow, imageRangeHigh);
4957     unsigned int imageBindingCount = stream.readInt<unsigned int>();
4958     for (unsigned int imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
4959     {
4960         unsigned int elementCount = stream.readInt<unsigned int>();
4961         ImageBinding imageBinding(elementCount);
4962         for (unsigned int i = 0; i < elementCount; ++i)
4963         {
4964             imageBinding.boundImageUnits[i] = stream.readInt<unsigned int>();
4965         }
4966         mState.mImageBindings.emplace_back(imageBinding);
4967     }
4968 
4969     unsigned int atomicCounterRangeLow  = stream.readInt<unsigned int>();
4970     unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
4971     mState.mAtomicCounterUniformRange   = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
4972 
4973     static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
4974                   "Too many shader types");
4975     mState.mLinkedShaderStages = ShaderBitSet(stream.readInt<uint8_t>());
4976 
4977     if (!mState.mAttachedShaders[ShaderType::Compute])
4978     {
4979         mState.updateTransformFeedbackStrides();
4980     }
4981 
4982     postResolveLink(context);
4983 
4984     return angle::Result::Continue;
4985 }
4986 
postResolveLink(const gl::Context * context)4987 void Program::postResolveLink(const gl::Context *context)
4988 {
4989     mState.updateActiveSamplers();
4990     mState.updateActiveImages();
4991 
4992     if (context->getExtensions().multiDraw)
4993     {
4994         mState.mDrawIDLocation = getUniformLocation("gl_DrawID");
4995     }
4996 
4997     if (context->getExtensions().baseVertexBaseInstance)
4998     {
4999         mState.mBaseVertexLocation   = getUniformLocation("gl_BaseVertex");
5000         mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance");
5001     }
5002 }
5003 
5004 }  // namespace gl
5005