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