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