• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Program.cpp: Implements the gl::Program class. Implements GL program objects
8 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9 
10 #include "libANGLE/Program.h"
11 
12 #include <algorithm>
13 #include <utility>
14 
15 #include "common/angle_version.h"
16 #include "common/bitset_utils.h"
17 #include "common/debug.h"
18 #include "common/platform.h"
19 #include "common/string_utils.h"
20 #include "common/utilities.h"
21 #include "compiler/translator/blocklayout.h"
22 #include "libANGLE/Context.h"
23 #include "libANGLE/ErrorStrings.h"
24 #include "libANGLE/MemoryProgramCache.h"
25 #include "libANGLE/ProgramLinkedResources.h"
26 #include "libANGLE/ResourceManager.h"
27 #include "libANGLE/Uniform.h"
28 #include "libANGLE/VaryingPacking.h"
29 #include "libANGLE/Version.h"
30 #include "libANGLE/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 
GetInterfaceBlockLimitName(ShaderType shaderType,sh::BlockType blockType)235 std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
236 {
237     std::ostringstream stream;
238     stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
239 
240     switch (blockType)
241     {
242         case sh::BlockType::BLOCK_UNIFORM:
243             stream << "UNIFORM_BUFFERS";
244             break;
245         case sh::BlockType::BLOCK_BUFFER:
246             stream << "SHADER_STORAGE_BLOCKS";
247             break;
248         default:
249             UNREACHABLE();
250             return "";
251     }
252 
253     if (shaderType == ShaderType::Geometry)
254     {
255         stream << "_EXT";
256     }
257 
258     return stream.str();
259 }
260 
GetInterfaceBlockTypeString(sh::BlockType blockType)261 const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
262 {
263     switch (blockType)
264     {
265         case sh::BlockType::BLOCK_UNIFORM:
266             return "uniform block";
267         case sh::BlockType::BLOCK_BUFFER:
268             return "shader storage block";
269         default:
270             UNREACHABLE();
271             return "";
272     }
273 }
274 
LogInterfaceBlocksExceedLimit(InfoLog & infoLog,ShaderType shaderType,sh::BlockType blockType,GLuint limit)275 void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
276                                    ShaderType shaderType,
277                                    sh::BlockType blockType,
278                                    GLuint limit)
279 {
280     infoLog << GetShaderTypeString(shaderType) << " shader "
281             << GetInterfaceBlockTypeString(blockType) << " count exceeds "
282             << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
283 }
284 
ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,sh::BlockType blockType,GLuint * combinedInterfaceBlocksCount,InfoLog & infoLog)285 bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
286                                   const std::vector<sh::InterfaceBlock> &interfaceBlocks,
287                                   ShaderType shaderType,
288                                   sh::BlockType blockType,
289                                   GLuint *combinedInterfaceBlocksCount,
290                                   InfoLog &infoLog)
291 {
292     GLuint blockCount = 0;
293     for (const sh::InterfaceBlock &block : interfaceBlocks)
294     {
295         if (IsActiveInterfaceBlock(block))
296         {
297             blockCount += std::max(block.arraySize, 1u);
298             if (blockCount > maxInterfaceBlocks)
299             {
300                 LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
301                 return false;
302             }
303         }
304     }
305 
306     // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
307     // If a uniform block is used by multiple shader stages, each such use counts separately
308     // against this combined limit.
309     // [OpenGL ES 3.1] Chapter 7.8 Page 111:
310     // If a shader storage block in a program is referenced by multiple shaders, each such
311     // reference counts separately against this combined limit.
312     if (combinedInterfaceBlocksCount)
313     {
314         *combinedInterfaceBlocksCount += blockCount;
315     }
316 
317     return true;
318 }
319 
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)320 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
321 {
322     std::vector<unsigned int> subscripts;
323     std::string baseName = ParseResourceName(name, &subscripts);
324 
325     unsigned int numBlocks = static_cast<unsigned int>(list.size());
326     for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
327     {
328         const auto &block = list[blockIndex];
329         if (block.name == baseName)
330         {
331             const bool arrayElementZero =
332                 (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
333             const bool arrayElementMatches =
334                 (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
335             if (arrayElementMatches || arrayElementZero)
336             {
337                 return blockIndex;
338             }
339         }
340     }
341 
342     return GL_INVALID_INDEX;
343 }
344 
GetInterfaceBlockName(const UniformBlockIndex index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)345 void GetInterfaceBlockName(const UniformBlockIndex index,
346                            const std::vector<InterfaceBlock> &list,
347                            GLsizei bufSize,
348                            GLsizei *length,
349                            GLchar *name)
350 {
351     ASSERT(index.value < list.size());
352 
353     const auto &block = list[index.value];
354 
355     if (bufSize > 0)
356     {
357         std::string blockName = block.name;
358 
359         if (block.isArray)
360         {
361             blockName += ArrayString(block.arrayElement);
362         }
363         CopyStringToBuffer(name, blockName, bufSize, length);
364     }
365 }
366 
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)367 void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
368 {
369     for (ShaderType shaderType : AllShaderTypes())
370     {
371         Shader *shader = state.getAttachedShader(shaderType);
372         if (shader)
373         {
374             blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks());
375         }
376     }
377 }
378 
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)379 void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
380 {
381     for (ShaderType shaderType : AllShaderTypes())
382     {
383         Shader *shader = state.getAttachedShader(shaderType);
384         if (shader != nullptr)
385         {
386             blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks());
387         }
388     }
389 }
390 }  // anonymous namespace
391 
GetLinkMismatchErrorString(LinkMismatchError linkError)392 const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
393 {
394     switch (linkError)
395     {
396         case LinkMismatchError::TYPE_MISMATCH:
397             return "Type";
398         case LinkMismatchError::ARRAYNESS_MISMATCH:
399             return "Array-ness";
400         case LinkMismatchError::ARRAY_SIZE_MISMATCH:
401             return "Array size";
402         case LinkMismatchError::PRECISION_MISMATCH:
403             return "Precision";
404         case LinkMismatchError::STRUCT_NAME_MISMATCH:
405             return "Structure name";
406         case LinkMismatchError::FIELD_NUMBER_MISMATCH:
407             return "Field number";
408         case LinkMismatchError::FIELD_NAME_MISMATCH:
409             return "Field name";
410 
411         case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
412             return "Interpolation type";
413         case LinkMismatchError::INVARIANCE_MISMATCH:
414             return "Invariance";
415 
416         case LinkMismatchError::BINDING_MISMATCH:
417             return "Binding layout qualifier";
418         case LinkMismatchError::LOCATION_MISMATCH:
419             return "Location layout qualifier";
420         case LinkMismatchError::OFFSET_MISMATCH:
421             return "Offset layout qualifier";
422         case LinkMismatchError::INSTANCE_NAME_MISMATCH:
423             return "Instance name qualifier";
424         case LinkMismatchError::FORMAT_MISMATCH:
425             return "Format qualifier";
426 
427         case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
428             return "Layout qualifier";
429         case LinkMismatchError::MATRIX_PACKING_MISMATCH:
430             return "Matrix Packing";
431 
432         case LinkMismatchError::FIELD_LOCATION_MISMATCH:
433             return "Field location";
434         case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
435             return "Field structure name";
436         default:
437             UNREACHABLE();
438             return "";
439     }
440 }
441 
LinkValidateInterfaceBlockFields(const sh::ShaderVariable & blockField1,const sh::ShaderVariable & blockField2,bool webglCompatibility,std::string * mismatchedBlockFieldName)442 LinkMismatchError LinkValidateInterfaceBlockFields(const sh::ShaderVariable &blockField1,
443                                                    const sh::ShaderVariable &blockField2,
444                                                    bool webglCompatibility,
445                                                    std::string *mismatchedBlockFieldName)
446 {
447     if (blockField1.name != blockField2.name)
448     {
449         return LinkMismatchError::FIELD_NAME_MISMATCH;
450     }
451 
452     // If webgl, validate precision of UBO fields, otherwise don't.  See Khronos bug 10287.
453     LinkMismatchError linkError = LinkValidateProgramVariables(
454         blockField1, blockField2, webglCompatibility, false, false, mismatchedBlockFieldName);
455     if (linkError != LinkMismatchError::NO_MISMATCH)
456     {
457         AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
458         return linkError;
459     }
460 
461     if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout)
462     {
463         AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
464         return LinkMismatchError::MATRIX_PACKING_MISMATCH;
465     }
466 
467     return LinkMismatchError::NO_MISMATCH;
468 }
469 
AreMatchingInterfaceBlocks(const sh::InterfaceBlock & interfaceBlock1,const sh::InterfaceBlock & interfaceBlock2,bool webglCompatibility,std::string * mismatchedBlockFieldName)470 LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1,
471                                              const sh::InterfaceBlock &interfaceBlock2,
472                                              bool webglCompatibility,
473                                              std::string *mismatchedBlockFieldName)
474 {
475     // validate blocks for the same member types
476     if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size())
477     {
478         return LinkMismatchError::FIELD_NUMBER_MISMATCH;
479     }
480     if (interfaceBlock1.arraySize != interfaceBlock2.arraySize)
481     {
482         return LinkMismatchError::ARRAY_SIZE_MISMATCH;
483     }
484     if (interfaceBlock1.layout != interfaceBlock2.layout ||
485         interfaceBlock1.binding != interfaceBlock2.binding)
486     {
487         return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH;
488     }
489     if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty())
490     {
491         return LinkMismatchError::INSTANCE_NAME_MISMATCH;
492     }
493     const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size());
494     for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
495     {
496         const sh::ShaderVariable &member1 = interfaceBlock1.fields[blockMemberIndex];
497         const sh::ShaderVariable &member2 = interfaceBlock2.fields[blockMemberIndex];
498 
499         LinkMismatchError linkError = LinkValidateInterfaceBlockFields(
500             member1, member2, webglCompatibility, mismatchedBlockFieldName);
501         if (linkError != LinkMismatchError::NO_MISMATCH)
502         {
503             return linkError;
504         }
505     }
506     return LinkMismatchError::NO_MISMATCH;
507 }
508 
509 using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>;
510 using InterfaceBlockMap    = std::map<std::string, ShaderInterfaceBlock>;
511 
InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * linkedInterfaceBlocks)512 void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
513                                  ShaderType shaderType,
514                                  InterfaceBlockMap *linkedInterfaceBlocks)
515 {
516     ASSERT(linkedInterfaceBlocks);
517 
518     for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
519     {
520         (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
521     }
522 }
523 
ValidateGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocksToLink,ShaderType shaderType,bool webglCompatibility,InterfaceBlockMap * linkedBlocks,InfoLog & infoLog)524 bool ValidateGraphicsInterfaceBlocksPerShader(
525     const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
526     ShaderType shaderType,
527     bool webglCompatibility,
528     InterfaceBlockMap *linkedBlocks,
529     InfoLog &infoLog)
530 {
531     ASSERT(linkedBlocks);
532 
533     for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
534     {
535         const auto &entry = linkedBlocks->find(block.name);
536         if (entry != linkedBlocks->end())
537         {
538             const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
539             std::string mismatchedStructFieldName;
540             LinkMismatchError linkError = AreMatchingInterfaceBlocks(
541                 block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
542             if (linkError != LinkMismatchError::NO_MISMATCH)
543             {
544                 LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
545                                 linkError, mismatchedStructFieldName, entry->second.first,
546                                 shaderType);
547                 return false;
548             }
549         }
550         else
551         {
552             (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
553         }
554     }
555 
556     return true;
557 }
558 
LogAmbiguousFieldLinkMismatch(InfoLog & infoLog,const std::string & blockName1,const std::string & blockName2,const std::string & fieldName,ShaderType shaderType1,ShaderType shaderType2)559 void LogAmbiguousFieldLinkMismatch(InfoLog &infoLog,
560                                    const std::string &blockName1,
561                                    const std::string &blockName2,
562                                    const std::string &fieldName,
563                                    ShaderType shaderType1,
564                                    ShaderType shaderType2)
565 {
566     infoLog << "Ambiguous field '" << fieldName << "' in blocks '" << blockName1 << "' ("
567             << GetShaderTypeString(shaderType1) << " shader) and '" << blockName2 << "' ("
568             << GetShaderTypeString(shaderType2) << " shader) which don't have instance names.";
569 }
570 
ValidateInstancelessGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * instancelessBlocksFields,InfoLog & infoLog)571 bool ValidateInstancelessGraphicsInterfaceBlocksPerShader(
572     const std::vector<sh::InterfaceBlock> &interfaceBlocks,
573     ShaderType shaderType,
574     InterfaceBlockMap *instancelessBlocksFields,
575     InfoLog &infoLog)
576 {
577     ASSERT(instancelessBlocksFields);
578 
579     for (const sh::InterfaceBlock &block : interfaceBlocks)
580     {
581         if (!block.instanceName.empty())
582         {
583             continue;
584         }
585 
586         for (const sh::ShaderVariable &field : block.fields)
587         {
588             const auto &entry = instancelessBlocksFields->find(field.name);
589             if (entry != instancelessBlocksFields->end())
590             {
591                 const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
592                 if (block.name != linkedBlock.name)
593                 {
594                     LogAmbiguousFieldLinkMismatch(infoLog, block.name, linkedBlock.name, field.name,
595                                                   entry->second.first, shaderType);
596                     return false;
597                 }
598             }
599             else
600             {
601                 (*instancelessBlocksFields)[field.name] = std::make_pair(shaderType, &block);
602             }
603         }
604     }
605 
606     return true;
607 }
608 
ValidateInterfaceBlocksMatch(GLuint numShadersHasInterfaceBlocks,const ShaderMap<const std::vector<sh::InterfaceBlock> * > & shaderInterfaceBlocks,InfoLog & infoLog,bool webglCompatibility,InterfaceBlockMap * instancelessInterfaceBlocksFields)609 bool ValidateInterfaceBlocksMatch(
610     GLuint numShadersHasInterfaceBlocks,
611     const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
612     InfoLog &infoLog,
613     bool webglCompatibility,
614     InterfaceBlockMap *instancelessInterfaceBlocksFields)
615 {
616     for (ShaderType shaderType : kAllGraphicsShaderTypes)
617     {
618         // Validate that instanceless blocks of different names don't have fields of the same name.
619         if (shaderInterfaceBlocks[shaderType] &&
620             !ValidateInstancelessGraphicsInterfaceBlocksPerShader(
621                 *shaderInterfaceBlocks[shaderType], shaderType, instancelessInterfaceBlocksFields,
622                 infoLog))
623         {
624             return false;
625         }
626     }
627 
628     if (numShadersHasInterfaceBlocks < 2u)
629     {
630         return true;
631     }
632 
633     ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]);
634 
635     // Check that interface blocks defined in the graphics shaders are identical
636 
637     InterfaceBlockMap linkedInterfaceBlocks;
638 
639     bool interfaceBlockMapInitialized = false;
640     for (ShaderType shaderType : kAllGraphicsShaderTypes)
641     {
642         if (!shaderInterfaceBlocks[shaderType])
643         {
644             continue;
645         }
646 
647         if (!interfaceBlockMapInitialized)
648         {
649             InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
650                                         &linkedInterfaceBlocks);
651             interfaceBlockMapInitialized = true;
652         }
653         else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType],
654                                                            shaderType, webglCompatibility,
655                                                            &linkedInterfaceBlocks, infoLog))
656         {
657             return false;
658         }
659     }
660 
661     return true;
662 }
663 
UpdateInterfaceVariable(std::vector<sh::ShaderVariable> * block,const sh::ShaderVariable & var)664 void UpdateInterfaceVariable(std::vector<sh::ShaderVariable> *block, const sh::ShaderVariable &var)
665 {
666     if (!var.isStruct())
667     {
668         block->emplace_back(var);
669         block->back().resetEffectiveLocation();
670     }
671 
672     for (const sh::ShaderVariable &field : var.fields)
673     {
674         ASSERT(!var.name.empty() || var.isShaderIOBlock);
675 
676         // Shader I/O block naming is similar to UBOs and SSBOs:
677         //
678         //     in Block
679         //     {
680         //         type field;  // produces "field"
681         //     };
682         //
683         //     in Block2
684         //     {
685         //         type field;  // produces "Block2.field"
686         //     } block2;
687         //
688         const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
689         const std::string prefix    = var.name.empty() ? "" : baseName + ".";
690 
691         if (!field.isStruct())
692         {
693             sh::ShaderVariable fieldCopy = field;
694             fieldCopy.updateEffectiveLocation(var);
695             fieldCopy.name = prefix + field.name;
696             block->emplace_back(fieldCopy);
697         }
698 
699         for (const sh::ShaderVariable &nested : field.fields)
700         {
701             sh::ShaderVariable nestedCopy = nested;
702             nestedCopy.updateEffectiveLocation(field);
703             nestedCopy.name = prefix + field.name + "." + nested.name;
704             block->emplace_back(nestedCopy);
705         }
706     }
707 }
708 
WriteShaderVariableBuffer(BinaryOutputStream * stream,const ShaderVariableBuffer & var)709 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
710 {
711     stream->writeInt(var.binding);
712     stream->writeInt(var.dataSize);
713 
714     for (ShaderType shaderType : AllShaderTypes())
715     {
716         stream->writeBool(var.isActive(shaderType));
717     }
718 
719     stream->writeInt(var.memberIndexes.size());
720     for (unsigned int memberCounterIndex : var.memberIndexes)
721     {
722         stream->writeInt(memberCounterIndex);
723     }
724 }
725 
LoadShaderVariableBuffer(BinaryInputStream * stream,ShaderVariableBuffer * var)726 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
727 {
728     var->binding  = stream->readInt<int>();
729     var->dataSize = stream->readInt<unsigned int>();
730 
731     for (ShaderType shaderType : AllShaderTypes())
732     {
733         var->setActive(shaderType, stream->readBool());
734     }
735 
736     size_t numMembers = stream->readInt<size_t>();
737     for (size_t blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
738     {
739         var->memberIndexes.push_back(stream->readInt<unsigned int>());
740     }
741 }
742 
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)743 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
744 {
745     WriteShaderVar(stream, var);
746 
747     stream->writeInt(var.bufferIndex);
748     WriteBlockMemberInfo(stream, var.blockInfo);
749     stream->writeInt(var.topLevelArraySize);
750 
751     for (ShaderType shaderType : AllShaderTypes())
752     {
753         stream->writeBool(var.isActive(shaderType));
754     }
755 }
756 
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)757 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
758 {
759     LoadShaderVar(stream, var);
760 
761     var->bufferIndex = stream->readInt<int>();
762     LoadBlockMemberInfo(stream, &var->blockInfo);
763     var->topLevelArraySize = stream->readInt<int>();
764 
765     for (ShaderType shaderType : AllShaderTypes())
766     {
767         var->setActive(shaderType, stream->readBool());
768     }
769 }
770 
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)771 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
772 {
773     stream->writeString(block.name);
774     stream->writeString(block.mappedName);
775     stream->writeBool(block.isArray);
776     stream->writeInt(block.arrayElement);
777 
778     WriteShaderVariableBuffer(stream, block);
779 }
780 
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)781 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
782 {
783     block->name         = stream->readString();
784     block->mappedName   = stream->readString();
785     block->isArray      = stream->readBool();
786     block->arrayElement = stream->readInt<unsigned int>();
787 
788     LoadShaderVariableBuffer(stream, block);
789 }
790 
791 // Saves the linking context for later use in resolveLink().
792 struct Program::LinkingState
793 {
794     std::shared_ptr<ProgramExecutable> linkedExecutable;
795     ProgramLinkedResources resources;
796     egl::BlobCache::Key programHash;
797     std::unique_ptr<rx::LinkEvent> linkEvent;
798     bool linkingFromBinary;
799 };
800 
801 const char *const g_fakepath = "C:\\fakepath";
802 
803 // InfoLog implementation.
InfoLog()804 InfoLog::InfoLog() : mLazyStream(nullptr) {}
805 
~InfoLog()806 InfoLog::~InfoLog() {}
807 
getLength() const808 size_t InfoLog::getLength() const
809 {
810     if (!mLazyStream)
811     {
812         return 0;
813     }
814 
815     const std::string &logString = mLazyStream->str();
816     return logString.empty() ? 0 : logString.length() + 1;
817 }
818 
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const819 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
820 {
821     size_t index = 0;
822 
823     if (bufSize > 0)
824     {
825         const std::string logString(str());
826 
827         if (!logString.empty())
828         {
829             index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
830             memcpy(infoLog, logString.c_str(), index);
831         }
832 
833         infoLog[index] = '\0';
834     }
835 
836     if (length)
837     {
838         *length = static_cast<GLsizei>(index);
839     }
840 }
841 
842 // append a santized message to the program info log.
843 // The D3D compiler includes a fake file path in some of the warning or error
844 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)845 void InfoLog::appendSanitized(const char *message)
846 {
847     ensureInitialized();
848 
849     std::string msg(message);
850 
851     size_t found;
852     do
853     {
854         found = msg.find(g_fakepath);
855         if (found != std::string::npos)
856         {
857             msg.erase(found, strlen(g_fakepath));
858         }
859     } while (found != std::string::npos);
860 
861     if (!msg.empty())
862     {
863         *mLazyStream << message << std::endl;
864     }
865 }
866 
reset()867 void InfoLog::reset()
868 {
869     if (mLazyStream)
870     {
871         mLazyStream.reset(nullptr);
872     }
873 }
874 
empty() const875 bool InfoLog::empty() const
876 {
877     if (!mLazyStream)
878     {
879         return true;
880     }
881 
882     return mLazyStream->rdbuf()->in_avail() == 0;
883 }
884 
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)885 void LogLinkMismatch(InfoLog &infoLog,
886                      const std::string &variableName,
887                      const char *variableType,
888                      LinkMismatchError linkError,
889                      const std::string &mismatchedStructOrBlockFieldName,
890                      ShaderType shaderType1,
891                      ShaderType shaderType2)
892 {
893     std::ostringstream stream;
894     stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
895            << variableName;
896 
897     if (!mismatchedStructOrBlockFieldName.empty())
898     {
899         stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
900     }
901 
902     stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
903            << GetShaderTypeString(shaderType2) << " shaders.";
904 
905     infoLog << stream.str();
906 }
907 
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)908 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
909 {
910     // Only 'packed' blocks are allowed to be considered inactive.
911     return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
912 }
913 
WriteBlockMemberInfo(BinaryOutputStream * stream,const sh::BlockMemberInfo & var)914 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var)
915 {
916     stream->writeInt(var.arrayStride);
917     stream->writeBool(var.isRowMajorMatrix);
918     stream->writeInt(var.matrixStride);
919     stream->writeInt(var.offset);
920     stream->writeInt(var.topLevelArrayStride);
921 }
922 
LoadBlockMemberInfo(BinaryInputStream * stream,sh::BlockMemberInfo * var)923 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
924 {
925     var->arrayStride         = stream->readInt<int>();
926     var->isRowMajorMatrix    = stream->readBool();
927     var->matrixStride        = stream->readInt<int>();
928     var->offset              = stream->readInt<int>();
929     var->topLevelArrayStride = stream->readInt<int>();
930 }
931 
WriteShaderVar(BinaryOutputStream * stream,const sh::ShaderVariable & var)932 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
933 {
934     stream->writeInt(var.type);
935     stream->writeInt(var.precision);
936     stream->writeString(var.name);
937     stream->writeString(var.mappedName);
938     stream->writeIntVector(var.arraySizes);
939     stream->writeBool(var.staticUse);
940     stream->writeBool(var.active);
941     stream->writeInt<size_t>(var.fields.size());
942     for (const sh::ShaderVariable &shaderVariable : var.fields)
943     {
944         WriteShaderVar(stream, shaderVariable);
945     }
946     stream->writeString(var.structOrBlockName);
947     stream->writeString(var.mappedStructOrBlockName);
948     stream->writeBool(var.isRowMajorLayout);
949     stream->writeInt(var.location);
950     stream->writeBool(var.hasImplicitLocation);
951     stream->writeInt(var.binding);
952     stream->writeInt(var.imageUnitFormat);
953     stream->writeInt(var.offset);
954     stream->writeBool(var.readonly);
955     stream->writeBool(var.writeonly);
956     stream->writeBool(var.isFragmentInOut);
957     stream->writeInt(var.index);
958     stream->writeBool(var.yuv);
959     stream->writeEnum(var.interpolation);
960     stream->writeBool(var.isInvariant);
961     stream->writeBool(var.isShaderIOBlock);
962     stream->writeBool(var.isPatch);
963     stream->writeBool(var.texelFetchStaticUse);
964     stream->writeInt(var.getFlattenedOffsetInParentArrays());
965 }
966 
LoadShaderVar(gl::BinaryInputStream * stream,sh::ShaderVariable * var)967 void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
968 {
969     var->type      = stream->readInt<GLenum>();
970     var->precision = stream->readInt<GLenum>();
971     stream->readString(&var->name);
972     stream->readString(&var->mappedName);
973     stream->readIntVector<unsigned int>(&var->arraySizes);
974     var->staticUse      = stream->readBool();
975     var->active         = stream->readBool();
976     size_t elementCount = stream->readInt<size_t>();
977     var->fields.resize(elementCount);
978     for (sh::ShaderVariable &variable : var->fields)
979     {
980         LoadShaderVar(stream, &variable);
981     }
982     stream->readString(&var->structOrBlockName);
983     stream->readString(&var->mappedStructOrBlockName);
984     var->isRowMajorLayout    = stream->readBool();
985     var->location            = stream->readInt<int>();
986     var->hasImplicitLocation = stream->readBool();
987     var->binding             = stream->readInt<int>();
988     var->imageUnitFormat     = stream->readInt<GLenum>();
989     var->offset              = stream->readInt<int>();
990     var->readonly            = stream->readBool();
991     var->writeonly           = stream->readBool();
992     var->isFragmentInOut     = stream->readBool();
993     var->index               = stream->readInt<int>();
994     var->yuv                 = stream->readBool();
995     var->interpolation       = stream->readEnum<sh::InterpolationType>();
996     var->isInvariant         = stream->readBool();
997     var->isShaderIOBlock     = stream->readBool();
998     var->isPatch             = stream->readBool();
999     var->texelFetchStaticUse = stream->readBool();
1000     var->setParentArrayIndex(stream->readInt<int>());
1001 }
1002 
1003 // VariableLocation implementation.
VariableLocation()1004 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
1005 
VariableLocation(unsigned int arrayIndex,unsigned int index)1006 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
1007     : arrayIndex(arrayIndex), index(index), ignored(false)
1008 {
1009     ASSERT(arrayIndex != GL_INVALID_INDEX);
1010 }
1011 
1012 // SamplerBindings implementation.
SamplerBinding(TextureType textureTypeIn,GLenum samplerTypeIn,SamplerFormat formatIn,size_t elementCount)1013 SamplerBinding::SamplerBinding(TextureType textureTypeIn,
1014                                GLenum samplerTypeIn,
1015                                SamplerFormat formatIn,
1016                                size_t elementCount)
1017     : textureType(textureTypeIn),
1018       samplerType(samplerTypeIn),
1019       format(formatIn),
1020       boundTextureUnits(elementCount, 0)
1021 {}
1022 
1023 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
1024 
1025 SamplerBinding::~SamplerBinding() = default;
1026 
1027 // ProgramBindings implementation.
ProgramBindings()1028 ProgramBindings::ProgramBindings() {}
1029 
~ProgramBindings()1030 ProgramBindings::~ProgramBindings() {}
1031 
bindLocation(GLuint index,const std::string & name)1032 void ProgramBindings::bindLocation(GLuint index, const std::string &name)
1033 {
1034     mBindings[name] = index;
1035 }
1036 
getBindingByName(const std::string & name) const1037 int ProgramBindings::getBindingByName(const std::string &name) const
1038 {
1039     auto iter = mBindings.find(name);
1040     return (iter != mBindings.end()) ? iter->second : -1;
1041 }
1042 
getBinding(const sh::ShaderVariable & variable) const1043 int ProgramBindings::getBinding(const sh::ShaderVariable &variable) const
1044 {
1045     return getBindingByName(variable.name);
1046 }
1047 
begin() const1048 ProgramBindings::const_iterator ProgramBindings::begin() const
1049 {
1050     return mBindings.begin();
1051 }
1052 
end() const1053 ProgramBindings::const_iterator ProgramBindings::end() const
1054 {
1055     return mBindings.end();
1056 }
1057 
getStableIterationMap() const1058 std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
1059 {
1060     return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
1061 }
1062 
1063 // ProgramAliasedBindings implementation.
ProgramAliasedBindings()1064 ProgramAliasedBindings::ProgramAliasedBindings() {}
1065 
~ProgramAliasedBindings()1066 ProgramAliasedBindings::~ProgramAliasedBindings() {}
1067 
bindLocation(GLuint index,const std::string & name)1068 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
1069 {
1070     mBindings[name] = ProgramBinding(index);
1071 
1072     // EXT_blend_func_extended spec: "If it specifies the base name of an array,
1073     // it identifies the resources associated with the first element of the array."
1074     //
1075     // Normalize array bindings so that "name" and "name[0]" map to the same entry.
1076     // If this binding is of the form "name[0]", then mark the "name" binding as
1077     // aliased but do not update it yet in case "name" is not actually an array.
1078     size_t nameLengthWithoutArrayIndex;
1079     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1080     if (arrayIndex == 0)
1081     {
1082         std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1083         auto iter            = mBindings.find(baseName);
1084         if (iter != mBindings.end())
1085         {
1086             iter->second.aliased = true;
1087         }
1088     }
1089 }
1090 
getBindingByName(const std::string & name) const1091 int ProgramAliasedBindings::getBindingByName(const std::string &name) const
1092 {
1093     auto iter = mBindings.find(name);
1094     return (iter != mBindings.end()) ? iter->second.location : -1;
1095 }
1096 
getBindingByLocation(GLuint location) const1097 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
1098 {
1099     for (const auto &iter : mBindings)
1100     {
1101         if (iter.second.location == location)
1102         {
1103             return iter.second.location;
1104         }
1105     }
1106     return -1;
1107 }
1108 
getBinding(const sh::ShaderVariable & variable) const1109 int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const
1110 {
1111     const std::string &name = variable.name;
1112 
1113     // Check with the normalized array name if applicable.
1114     if (variable.isArray())
1115     {
1116         size_t nameLengthWithoutArrayIndex;
1117         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1118         if (arrayIndex == 0)
1119         {
1120             std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1121             auto iter            = mBindings.find(baseName);
1122             // If "name" exists and is not aliased, that means it was modified more
1123             // recently than its "name[0]" form and should be used instead of that.
1124             if (iter != mBindings.end() && !iter->second.aliased)
1125             {
1126                 return iter->second.location;
1127             }
1128         }
1129         else if (arrayIndex == GL_INVALID_INDEX)
1130         {
1131             auto iter = mBindings.find(variable.name);
1132             // If "name" exists and is not aliased, that means it was modified more
1133             // recently than its "name[0]" form and should be used instead of that.
1134             if (iter != mBindings.end() && !iter->second.aliased)
1135             {
1136                 return iter->second.location;
1137             }
1138             // The base name was aliased, so use the name with the array notation.
1139             return getBindingByName(name + "[0]");
1140         }
1141     }
1142 
1143     return getBindingByName(name);
1144 }
1145 
begin() const1146 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
1147 {
1148     return mBindings.begin();
1149 }
1150 
end() const1151 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
1152 {
1153     return mBindings.end();
1154 }
1155 
getStableIterationMap() const1156 std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
1157 {
1158     return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
1159 }
1160 
1161 // ImageBinding implementation.
ImageBinding(size_t count,TextureType textureTypeIn)1162 ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn)
1163     : textureType(textureTypeIn), boundImageUnits(count, 0)
1164 {}
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)1165 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
1166     : textureType(textureTypeIn)
1167 {
1168     for (size_t index = 0; index < count; ++index)
1169     {
1170         boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
1171     }
1172 }
1173 
1174 ImageBinding::ImageBinding(const ImageBinding &other) = default;
1175 
1176 ImageBinding::~ImageBinding() = default;
1177 
1178 // ProgramState implementation.
ProgramState()1179 ProgramState::ProgramState()
1180     : mLabel(),
1181       mAttachedShaders{},
1182       mLocationsUsedForXfbExtension(0),
1183       mAtomicCounterUniformRange(0, 0),
1184       mYUVOutput(false),
1185       mBinaryRetrieveableHint(false),
1186       mSeparable(false),
1187       mNumViews(-1),
1188       mDrawIDLocation(-1),
1189       mBaseVertexLocation(-1),
1190       mBaseInstanceLocation(-1),
1191       mCachedBaseVertex(0),
1192       mCachedBaseInstance(0),
1193       mExecutable(new ProgramExecutable())
1194 {
1195     mComputeShaderLocalSize.fill(1);
1196 }
1197 
~ProgramState()1198 ProgramState::~ProgramState()
1199 {
1200     ASSERT(!hasAttachedShader());
1201 }
1202 
getLabel()1203 const std::string &ProgramState::getLabel()
1204 {
1205     return mLabel;
1206 }
1207 
getAttachedShader(ShaderType shaderType) const1208 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
1209 {
1210     ASSERT(shaderType != ShaderType::InvalidEnum);
1211     return mAttachedShaders[shaderType];
1212 }
1213 
getUniformIndexFromName(const std::string & name) const1214 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
1215 {
1216     return GetResourceIndexFromName(mExecutable->mUniforms, name);
1217 }
1218 
getBufferVariableIndexFromName(const std::string & name) const1219 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
1220 {
1221     return GetResourceIndexFromName(mBufferVariables, name);
1222 }
1223 
getUniformIndexFromLocation(UniformLocation location) const1224 GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const
1225 {
1226     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
1227     return mUniformLocations[location.value].index;
1228 }
1229 
getSamplerIndex(UniformLocation location) const1230 Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
1231 {
1232     GLuint index = getUniformIndexFromLocation(location);
1233     if (!isSamplerUniformIndex(index))
1234     {
1235         return Optional<GLuint>::Invalid();
1236     }
1237 
1238     return getSamplerIndexFromUniformIndex(index);
1239 }
1240 
isSamplerUniformIndex(GLuint index) const1241 bool ProgramState::isSamplerUniformIndex(GLuint index) const
1242 {
1243     return mExecutable->mSamplerUniformRange.contains(index);
1244 }
1245 
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const1246 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
1247 {
1248     ASSERT(isSamplerUniformIndex(uniformIndex));
1249     return uniformIndex - mExecutable->mSamplerUniformRange.low();
1250 }
1251 
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const1252 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
1253 {
1254     ASSERT(samplerIndex < mExecutable->mSamplerUniformRange.length());
1255     return samplerIndex + mExecutable->mSamplerUniformRange.low();
1256 }
1257 
isImageUniformIndex(GLuint index) const1258 bool ProgramState::isImageUniformIndex(GLuint index) const
1259 {
1260     return mExecutable->mImageUniformRange.contains(index);
1261 }
1262 
getImageIndexFromUniformIndex(GLuint uniformIndex) const1263 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
1264 {
1265     ASSERT(isImageUniformIndex(uniformIndex));
1266     return uniformIndex - mExecutable->mImageUniformRange.low();
1267 }
1268 
getAttributeLocation(const std::string & name) const1269 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1270 {
1271     for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
1272     {
1273         if (attribute.name == name)
1274         {
1275             return attribute.location;
1276         }
1277     }
1278 
1279     return static_cast<GLuint>(-1);
1280 }
1281 
hasAttachedShader() const1282 bool ProgramState::hasAttachedShader() const
1283 {
1284     for (const Shader *shader : mAttachedShaders)
1285     {
1286         if (shader)
1287         {
1288             return true;
1289         }
1290     }
1291     return false;
1292 }
1293 
getFirstAttachedShaderStageType() const1294 ShaderType ProgramState::getFirstAttachedShaderStageType() const
1295 {
1296     const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1297     if (linkedStages.none())
1298     {
1299         return ShaderType::InvalidEnum;
1300     }
1301 
1302     return linkedStages.first();
1303 }
1304 
getLastAttachedShaderStageType() const1305 ShaderType ProgramState::getLastAttachedShaderStageType() const
1306 {
1307     const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1308     if (linkedStages.none())
1309     {
1310         return ShaderType::InvalidEnum;
1311     }
1312 
1313     return linkedStages.last();
1314 }
1315 
getAttachedTransformFeedbackStage() const1316 ShaderType ProgramState::getAttachedTransformFeedbackStage() const
1317 {
1318     if (mAttachedShaders[ShaderType::Geometry])
1319     {
1320         return ShaderType::Geometry;
1321     }
1322     if (mAttachedShaders[ShaderType::TessEvaluation])
1323     {
1324         return ShaderType::TessEvaluation;
1325     }
1326     return ShaderType::Vertex;
1327 }
1328 
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)1329 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
1330     : mSerial(factory->generateSerial()),
1331       mProgram(factory->createProgram(mState)),
1332       mValidated(false),
1333       mLinked(false),
1334       mDeleteStatus(false),
1335       mRefCount(0),
1336       mResourceManager(manager),
1337       mHandle(handle)
1338 {
1339     ASSERT(mProgram);
1340 
1341     unlink();
1342 }
1343 
~Program()1344 Program::~Program()
1345 {
1346     ASSERT(!mProgram);
1347 }
1348 
onDestroy(const Context * context)1349 void Program::onDestroy(const Context *context)
1350 {
1351     resolveLink(context);
1352     for (ShaderType shaderType : AllShaderTypes())
1353     {
1354         if (mState.mAttachedShaders[shaderType])
1355         {
1356             mState.mAttachedShaders[shaderType]->release(context);
1357             mState.mAttachedShaders[shaderType] = nullptr;
1358         }
1359     }
1360 
1361     mProgram->destroy(context);
1362 
1363     ASSERT(!mState.hasAttachedShader());
1364     SafeDelete(mProgram);
1365 
1366     delete this;
1367 }
id() const1368 ShaderProgramID Program::id() const
1369 {
1370     ASSERT(!mLinkingState);
1371     return mHandle;
1372 }
1373 
setLabel(const Context * context,const std::string & label)1374 void Program::setLabel(const Context *context, const std::string &label)
1375 {
1376     ASSERT(!mLinkingState);
1377     mState.mLabel = label;
1378 }
1379 
getLabel() const1380 const std::string &Program::getLabel() const
1381 {
1382     ASSERT(!mLinkingState);
1383     return mState.mLabel;
1384 }
1385 
attachShader(Shader * shader)1386 void Program::attachShader(Shader *shader)
1387 {
1388     ShaderType shaderType = shader->getType();
1389     ASSERT(shaderType != ShaderType::InvalidEnum);
1390 
1391     mState.mAttachedShaders[shaderType] = shader;
1392     mState.mAttachedShaders[shaderType]->addRef();
1393 }
1394 
detachShader(const Context * context,Shader * shader)1395 void Program::detachShader(const Context *context, Shader *shader)
1396 {
1397     resolveLink(context);
1398     ShaderType shaderType = shader->getType();
1399     ASSERT(shaderType != ShaderType::InvalidEnum);
1400 
1401     ASSERT(mState.mAttachedShaders[shaderType] == shader);
1402     shader->release(context);
1403     mState.mAttachedShaders[shaderType] = nullptr;
1404 }
1405 
getAttachedShadersCount() const1406 int Program::getAttachedShadersCount() const
1407 {
1408     ASSERT(!mLinkingState);
1409     int numAttachedShaders = 0;
1410     for (const Shader *shader : mState.mAttachedShaders)
1411     {
1412         if (shader)
1413         {
1414             ++numAttachedShaders;
1415         }
1416     }
1417 
1418     return numAttachedShaders;
1419 }
1420 
getAttachedShader(ShaderType shaderType) const1421 Shader *Program::getAttachedShader(ShaderType shaderType) const
1422 {
1423     ASSERT(!mLinkingState);
1424     return mState.getAttachedShader(shaderType);
1425 }
1426 
bindAttributeLocation(GLuint index,const char * name)1427 void Program::bindAttributeLocation(GLuint index, const char *name)
1428 {
1429     ASSERT(!mLinkingState);
1430     mAttributeBindings.bindLocation(index, name);
1431 }
1432 
bindUniformLocation(UniformLocation location,const char * name)1433 void Program::bindUniformLocation(UniformLocation location, const char *name)
1434 {
1435     ASSERT(!mLinkingState);
1436     mState.mUniformLocationBindings.bindLocation(location.value, name);
1437 }
1438 
bindFragmentOutputLocation(GLuint index,const char * name)1439 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1440 {
1441     mFragmentOutputLocations.bindLocation(index, name);
1442 }
1443 
bindFragmentOutputIndex(GLuint index,const char * name)1444 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1445 {
1446     mFragmentOutputIndexes.bindLocation(index, name);
1447 }
1448 
link(const Context * context)1449 angle::Result Program::link(const Context *context)
1450 {
1451     angle::Result result = linkImpl(context);
1452 
1453     // Avoid having two ProgramExecutables if the link failed and the Program had successfully
1454     // linked previously.
1455     if (mLinkingState && mLinkingState->linkedExecutable)
1456     {
1457         mState.mExecutable = mLinkingState->linkedExecutable;
1458     }
1459 
1460     return result;
1461 }
1462 
1463 // The attached shaders are checked for linking errors by matching up their variables.
1464 // Uniform, input and output variables get collected.
1465 // The code gets compiled into binaries.
linkImpl(const Context * context)1466 angle::Result Program::linkImpl(const Context *context)
1467 {
1468     ASSERT(!mLinkingState);
1469     // Don't make any local variables pointing to anything within the ProgramExecutable, since
1470     // unlink() could make a new ProgramExecutable making any references/pointers invalid.
1471     auto *platform   = ANGLEPlatformCurrent();
1472     double startTime = platform->currentTime(platform);
1473 
1474     // Unlink the program, but do not clear the validation-related caching yet, since we can still
1475     // use the previously linked program if linking the shaders fails.
1476     mLinked = false;
1477 
1478     mState.mExecutable->getInfoLog().reset();
1479 
1480     // Validate we have properly attached shaders before checking the cache.
1481     if (!linkValidateShaders(mState.mExecutable->getInfoLog()))
1482     {
1483         return angle::Result::Continue;
1484     }
1485 
1486     egl::BlobCache::Key programHash = {0};
1487     MemoryProgramCache *cache       = context->getMemoryProgramCache();
1488 
1489     // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1490     if (cache && !isSeparable())
1491     {
1492         std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1493         angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1494         ANGLE_TRY(cacheResult);
1495 
1496         // Check explicitly for Continue, Incomplete means a cache miss
1497         if (cacheResult == angle::Result::Continue)
1498         {
1499             // Succeeded in loading the binaries in the front-end, back end may still be loading
1500             // asynchronously
1501             double delta = platform->currentTime(platform) - startTime;
1502             int us       = static_cast<int>(delta * 1000000.0);
1503             ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1504             return angle::Result::Continue;
1505         }
1506     }
1507 
1508     // Cache load failed, fall through to normal linking.
1509     unlink();
1510     InfoLog &infoLog = mState.mExecutable->getInfoLog();
1511 
1512     // Re-link shaders after the unlink call.
1513     bool result = linkValidateShaders(infoLog);
1514     ASSERT(result);
1515 
1516     std::unique_ptr<LinkingState> linkingState(new LinkingState());
1517     ProgramMergedVaryings mergedVaryings;
1518     ProgramLinkedResources &resources = linkingState->resources;
1519 
1520     if (mState.mAttachedShaders[ShaderType::Compute])
1521     {
1522         resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1523                        &mState.mExecutable->mComputeShaderStorageBlocks, &mState.mBufferVariables,
1524                        &mState.mExecutable->mAtomicCounterBuffers);
1525 
1526         GLuint combinedImageUniforms = 0u;
1527         if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1528                           mState.mUniformLocationBindings, &combinedImageUniforms,
1529                           &resources.unusedUniforms))
1530         {
1531             return angle::Result::Continue;
1532         }
1533 
1534         GLuint combinedShaderStorageBlocks = 0u;
1535         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1536                                  context->getExtensions().webglCompatibility, infoLog,
1537                                  &combinedShaderStorageBlocks))
1538         {
1539             return angle::Result::Continue;
1540         }
1541 
1542         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1543         // A link error will be generated if the sum of the number of active image uniforms used in
1544         // all shaders, the number of active shader storage blocks, and the number of active
1545         // fragment shader outputs exceeds the implementation-dependent value of
1546         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1547         if (combinedImageUniforms + combinedShaderStorageBlocks >
1548             static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
1549         {
1550             infoLog
1551                 << "The sum of the number of active image uniforms, active shader storage blocks "
1552                    "and active fragment shader outputs exceeds "
1553                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1554                 << context->getCaps().maxCombinedShaderOutputResources << ")";
1555             return angle::Result::Continue;
1556         }
1557 
1558         InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1559         InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1560     }
1561     else
1562     {
1563         resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1564                        &mState.mExecutable->mGraphicsShaderStorageBlocks, &mState.mBufferVariables,
1565                        &mState.mExecutable->mAtomicCounterBuffers);
1566 
1567         if (!linkAttributes(context, infoLog))
1568         {
1569             return angle::Result::Continue;
1570         }
1571 
1572         if (!linkVaryings(infoLog))
1573         {
1574             return angle::Result::Continue;
1575         }
1576 
1577         GLuint combinedImageUniforms = 0u;
1578         if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1579                           mState.mUniformLocationBindings, &combinedImageUniforms,
1580                           &resources.unusedUniforms))
1581         {
1582             return angle::Result::Continue;
1583         }
1584 
1585         GLuint combinedShaderStorageBlocks = 0u;
1586         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1587                                  context->getExtensions().webglCompatibility, infoLog,
1588                                  &combinedShaderStorageBlocks))
1589         {
1590             return angle::Result::Continue;
1591         }
1592 
1593         if (!LinkValidateProgramGlobalNames(infoLog, *this))
1594         {
1595             return angle::Result::Continue;
1596         }
1597 
1598         if (!linkOutputVariables(context->getCaps(), context->getExtensions(),
1599                                  context->getClientVersion(), combinedImageUniforms,
1600                                  combinedShaderStorageBlocks))
1601         {
1602             return angle::Result::Continue;
1603         }
1604 
1605         gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1606         if (vertexShader)
1607         {
1608             mState.mNumViews = vertexShader->getNumViews();
1609             mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
1610         }
1611 
1612         gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1613         if (fragmentShader)
1614         {
1615             mState.mEarlyFramentTestsOptimization =
1616                 fragmentShader->hasEarlyFragmentTestsOptimization();
1617             mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
1618         }
1619 
1620         InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1621         InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1622 
1623         mergedVaryings = GetMergedVaryingsFromShaders(*this, getExecutable());
1624         if (!mState.mExecutable->linkMergedVaryings(context, *this, mergedVaryings,
1625                                                     mState.mTransformFeedbackVaryingNames,
1626                                                     isSeparable(), &resources.varyingPacking))
1627         {
1628             return angle::Result::Continue;
1629         }
1630     }
1631 
1632     updateLinkedShaderStages();
1633 
1634     mLinkingState                    = std::move(linkingState);
1635     mLinkingState->linkingFromBinary = false;
1636     mLinkingState->programHash       = programHash;
1637     mLinkingState->linkEvent         = mProgram->link(context, resources, infoLog, mergedVaryings);
1638 
1639     // Must be after mProgram->link() to avoid misleading the linker about output variables.
1640     mState.updateProgramInterfaceInputs();
1641     mState.updateProgramInterfaceOutputs();
1642 
1643     // Linking has succeeded, so we need to save some information that may get overwritten by a
1644     // later linkProgram() that could fail.
1645     if (mState.mSeparable)
1646     {
1647         mState.mExecutable->saveLinkedStateInfo(mState);
1648         mLinkingState->linkedExecutable = mState.mExecutable;
1649     }
1650 
1651     return angle::Result::Continue;
1652 }
1653 
isLinking() const1654 bool Program::isLinking() const
1655 {
1656     return (mLinkingState.get() && mLinkingState->linkEvent &&
1657             mLinkingState->linkEvent->isLinking());
1658 }
1659 
resolveLinkImpl(const Context * context)1660 void Program::resolveLinkImpl(const Context *context)
1661 {
1662     ASSERT(mLinkingState.get());
1663 
1664     angle::Result result = mLinkingState->linkEvent->wait(context);
1665 
1666     mLinked                                    = result == angle::Result::Continue;
1667     std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1668     if (!mLinked)
1669     {
1670         return;
1671     }
1672 
1673     if (linkingState->linkingFromBinary)
1674     {
1675         // All internal Program state is already loaded from the binary.
1676         return;
1677     }
1678 
1679     initInterfaceBlockBindings();
1680 
1681     // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1682     // Only successfully linked program can replace the executables.
1683     ASSERT(mLinked);
1684 
1685     // Mark implementation-specific unreferenced uniforms as ignored.
1686     std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1687     mProgram->markUnusedUniformLocations(&mState.mUniformLocations,
1688                                          &mState.mExecutable->mSamplerBindings, imageBindings);
1689 
1690     // Must be called after markUnusedUniformLocations.
1691     postResolveLink(context);
1692 
1693     // Save to the program cache.
1694     std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1695     MemoryProgramCache *cache = context->getMemoryProgramCache();
1696     // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1697     if (cache && !isSeparable() &&
1698         (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
1699          !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
1700     {
1701         if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
1702         {
1703             // Don't fail linking if putting the program binary into the cache fails, the program is
1704             // still usable.
1705             WARN() << "Failed to save linked program to memory program cache.";
1706         }
1707     }
1708 }
1709 
updateLinkedShaderStages()1710 void Program::updateLinkedShaderStages()
1711 {
1712     mState.mExecutable->resetLinkedShaderStages();
1713 
1714     for (const Shader *shader : mState.mAttachedShaders)
1715     {
1716         if (shader)
1717         {
1718             mState.mExecutable->setLinkedShaderStages(shader->getType());
1719         }
1720     }
1721 
1722     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
1723     {
1724         mState.mExecutable->setIsCompute(true);
1725     }
1726     else
1727     {
1728         mState.mExecutable->setIsCompute(false);
1729     }
1730 }
1731 
updateActiveSamplers()1732 void ProgramState::updateActiveSamplers()
1733 {
1734     mExecutable->mActiveSamplerRefCounts.fill(0);
1735     mExecutable->updateActiveSamplers(*this);
1736 }
1737 
updateProgramInterfaceInputs()1738 void ProgramState::updateProgramInterfaceInputs()
1739 {
1740     const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType();
1741 
1742     if (firstAttachedShaderType == ShaderType::Vertex)
1743     {
1744         // Vertex attributes are already what we need, so nothing to do
1745         return;
1746     }
1747 
1748     Shader *shader = getAttachedShader(firstAttachedShaderType);
1749     ASSERT(shader);
1750 
1751     // Copy over each input varying, since the Shader could go away
1752     if (shader->getType() == ShaderType::Compute)
1753     {
1754         for (const sh::ShaderVariable &attribute : shader->getAllAttributes())
1755         {
1756             // Compute Shaders have the following built-in input variables.
1757             //
1758             // in uvec3 gl_NumWorkGroups;
1759             // in uvec3 gl_WorkGroupID;
1760             // in uvec3 gl_LocalInvocationID;
1761             // in uvec3 gl_GlobalInvocationID;
1762             // in uint  gl_LocalInvocationIndex;
1763             // They are all vecs or uints, so no special handling is required.
1764             mExecutable->mProgramInputs.emplace_back(attribute);
1765         }
1766     }
1767     else
1768     {
1769         for (const sh::ShaderVariable &varying : shader->getInputVaryings())
1770         {
1771             UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1772         }
1773     }
1774 }
1775 
updateProgramInterfaceOutputs()1776 void ProgramState::updateProgramInterfaceOutputs()
1777 {
1778     const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType();
1779 
1780     if (lastAttachedShaderType == ShaderType::Fragment)
1781     {
1782         // Fragment outputs are already what we need, so nothing to do
1783         return;
1784     }
1785     if (lastAttachedShaderType == ShaderType::Compute)
1786     {
1787         // If the program only contains a Compute Shader, then there are no user-defined outputs.
1788         return;
1789     }
1790 
1791     Shader *shader = getAttachedShader(lastAttachedShaderType);
1792     ASSERT(shader);
1793 
1794     // Copy over each output varying, since the Shader could go away
1795     for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
1796     {
1797         UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1798     }
1799 }
1800 
1801 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1802 void Program::unlink()
1803 {
1804     if (mLinkingState && mLinkingState->linkedExecutable)
1805     {
1806         // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of
1807         // the last successfully linked ProgramExecutable, so we don't lose any state information.
1808         mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable));
1809     }
1810     mState.mExecutable->reset();
1811 
1812     mState.mUniformLocations.clear();
1813     mState.mBufferVariables.clear();
1814     mState.mOutputVariableTypes.clear();
1815     mState.mDrawBufferTypeMask.reset();
1816     mState.mYUVOutput = false;
1817     mState.mActiveOutputVariables.reset();
1818     mState.mComputeShaderLocalSize.fill(1);
1819     mState.mNumViews                      = -1;
1820     mState.mDrawIDLocation                = -1;
1821     mState.mBaseVertexLocation            = -1;
1822     mState.mBaseInstanceLocation          = -1;
1823     mState.mCachedBaseVertex              = 0;
1824     mState.mCachedBaseInstance            = 0;
1825     mState.mEarlyFramentTestsOptimization = false;
1826     mState.mDrawIDLocation                = -1;
1827     mState.mBaseVertexLocation            = -1;
1828     mState.mBaseInstanceLocation          = -1;
1829     mState.mCachedBaseVertex              = 0;
1830     mState.mCachedBaseInstance            = 0;
1831     mState.mEarlyFramentTestsOptimization = false;
1832     mState.mSpecConstUsageBits.reset();
1833 
1834     mValidated = false;
1835 
1836     mLinked = false;
1837 }
1838 
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1839 angle::Result Program::loadBinary(const Context *context,
1840                                   GLenum binaryFormat,
1841                                   const void *binary,
1842                                   GLsizei length)
1843 {
1844     ASSERT(!mLinkingState);
1845     unlink();
1846     InfoLog &infoLog = mState.mExecutable->getInfoLog();
1847 
1848 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1849     return angle::Result::Continue;
1850 #else
1851     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1852     if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1853     {
1854         infoLog << "Invalid program binary format.";
1855         return angle::Result::Continue;
1856     }
1857 
1858     BinaryInputStream stream(binary, length);
1859     ANGLE_TRY(deserialize(context, stream, infoLog));
1860 
1861     // Currently we require the full shader text to compute the program hash.
1862     // We could also store the binary in the internal program cache.
1863 
1864     for (size_t uniformBlockIndex = 0;
1865          uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
1866     {
1867         mDirtyBits.set(uniformBlockIndex);
1868     }
1869 
1870     // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple
1871     // implementations. In some implementations, a background thread is used to compile the
1872     // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with
1873     // the operation.
1874 
1875     // We do not want to call LinkEvent::wait because that will cause the background thread
1876     // to finish its task before returning, thus defeating the purpose of background compilation.
1877     // We need to defer waiting on background compilation until the very last minute when we
1878     // absolutely need the results, such as when the developer binds the program or queries
1879     // for the completion status.
1880 
1881     // If load returns nullptr, we know for sure that the binary is not compatible with the backend.
1882     // The loaded binary could have been read from the on-disk shader cache and be corrupted or
1883     // serialized with different revision and subsystem id than the currently loaded backend.
1884     // Returning 'Incomplete' to the caller results in link happening using the original shader
1885     // sources.
1886     angle::Result result;
1887     std::unique_ptr<LinkingState> linkingState;
1888     std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog);
1889     if (linkEvent)
1890     {
1891         linkingState                    = std::make_unique<LinkingState>();
1892         linkingState->linkingFromBinary = true;
1893         linkingState->linkEvent         = std::move(linkEvent);
1894         result                          = angle::Result::Continue;
1895     }
1896     else
1897     {
1898         result = angle::Result::Incomplete;
1899     }
1900     mLinkingState = std::move(linkingState);
1901 
1902     return result;
1903 #endif  // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1904 }
1905 
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1906 angle::Result Program::saveBinary(Context *context,
1907                                   GLenum *binaryFormat,
1908                                   void *binary,
1909                                   GLsizei bufSize,
1910                                   GLsizei *length) const
1911 {
1912     ASSERT(!mLinkingState);
1913     if (binaryFormat)
1914     {
1915         *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1916     }
1917 
1918     angle::MemoryBuffer memoryBuf;
1919     ANGLE_TRY(serialize(context, &memoryBuf));
1920 
1921     GLsizei streamLength       = static_cast<GLsizei>(memoryBuf.size());
1922     const uint8_t *streamState = memoryBuf.data();
1923 
1924     if (streamLength > bufSize)
1925     {
1926         if (length)
1927         {
1928             *length = 0;
1929         }
1930 
1931         // TODO: This should be moved to the validation layer but computing the size of the binary
1932         // before saving it causes the save to happen twice.  It may be possible to write the binary
1933         // to a separate buffer, validate sizes and then copy it.
1934         ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1935     }
1936 
1937     if (binary)
1938     {
1939         char *ptr = reinterpret_cast<char *>(binary);
1940 
1941         memcpy(ptr, streamState, streamLength);
1942         ptr += streamLength;
1943 
1944         ASSERT(ptr - streamLength == binary);
1945     }
1946 
1947     if (length)
1948     {
1949         *length = streamLength;
1950     }
1951 
1952     return angle::Result::Continue;
1953 }
1954 
getBinaryLength(Context * context) const1955 GLint Program::getBinaryLength(Context *context) const
1956 {
1957     ASSERT(!mLinkingState);
1958     if (!mLinked)
1959     {
1960         return 0;
1961     }
1962 
1963     GLint length;
1964     angle::Result result =
1965         saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1966     if (result != angle::Result::Continue)
1967     {
1968         return 0;
1969     }
1970 
1971     return length;
1972 }
1973 
setBinaryRetrievableHint(bool retrievable)1974 void Program::setBinaryRetrievableHint(bool retrievable)
1975 {
1976     ASSERT(!mLinkingState);
1977     // TODO(jmadill) : replace with dirty bits
1978     mProgram->setBinaryRetrievableHint(retrievable);
1979     mState.mBinaryRetrieveableHint = retrievable;
1980 }
1981 
getBinaryRetrievableHint() const1982 bool Program::getBinaryRetrievableHint() const
1983 {
1984     ASSERT(!mLinkingState);
1985     return mState.mBinaryRetrieveableHint;
1986 }
1987 
setSeparable(bool separable)1988 void Program::setSeparable(bool separable)
1989 {
1990     ASSERT(!mLinkingState);
1991     // TODO(yunchao) : replace with dirty bits
1992     if (mState.mSeparable != separable)
1993     {
1994         mProgram->setSeparable(separable);
1995         mState.mSeparable = separable;
1996     }
1997 }
1998 
isSeparable() const1999 bool Program::isSeparable() const
2000 {
2001     ASSERT(!mLinkingState);
2002     return mState.mSeparable;
2003 }
2004 
deleteSelf(const Context * context)2005 void Program::deleteSelf(const Context *context)
2006 {
2007     ASSERT(mRefCount == 0 && mDeleteStatus);
2008     mResourceManager->deleteProgram(context, mHandle);
2009 }
2010 
getRefCount() const2011 unsigned int Program::getRefCount() const
2012 {
2013     return mRefCount;
2014 }
2015 
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const2016 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
2017 {
2018     ASSERT(!mLinkingState);
2019     int total = 0;
2020 
2021     for (const Shader *shader : mState.mAttachedShaders)
2022     {
2023         if (shader && (total < maxCount))
2024         {
2025             shaders[total] = shader->getHandle();
2026             ++total;
2027         }
2028     }
2029 
2030     if (count)
2031     {
2032         *count = total;
2033     }
2034 }
2035 
getAttributeLocation(const std::string & name) const2036 GLuint Program::getAttributeLocation(const std::string &name) const
2037 {
2038     ASSERT(!mLinkingState);
2039     return mState.getAttributeLocation(name);
2040 }
2041 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2042 void Program::getActiveAttribute(GLuint index,
2043                                  GLsizei bufsize,
2044                                  GLsizei *length,
2045                                  GLint *size,
2046                                  GLenum *type,
2047                                  GLchar *name) const
2048 {
2049     ASSERT(!mLinkingState);
2050     if (!mLinked)
2051     {
2052         if (bufsize > 0)
2053         {
2054             name[0] = '\0';
2055         }
2056 
2057         if (length)
2058         {
2059             *length = 0;
2060         }
2061 
2062         *type = GL_NONE;
2063         *size = 1;
2064         return;
2065     }
2066 
2067     ASSERT(index < mState.mExecutable->getProgramInputs().size());
2068     const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
2069 
2070     if (bufsize > 0)
2071     {
2072         CopyStringToBuffer(name, attrib.name, bufsize, length);
2073     }
2074 
2075     // Always a single 'type' instance
2076     *size = 1;
2077     *type = attrib.type;
2078 }
2079 
getActiveAttributeCount() const2080 GLint Program::getActiveAttributeCount() const
2081 {
2082     ASSERT(!mLinkingState);
2083     if (!mLinked)
2084     {
2085         return 0;
2086     }
2087 
2088     return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
2089 }
2090 
getActiveAttributeMaxLength() const2091 GLint Program::getActiveAttributeMaxLength() const
2092 {
2093     ASSERT(!mLinkingState);
2094     if (!mLinked)
2095     {
2096         return 0;
2097     }
2098 
2099     size_t maxLength = 0;
2100 
2101     for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
2102     {
2103         maxLength = std::max(attrib.name.length() + 1, maxLength);
2104     }
2105 
2106     return static_cast<GLint>(maxLength);
2107 }
2108 
getAttributes() const2109 const std::vector<sh::ShaderVariable> &Program::getAttributes() const
2110 {
2111     ASSERT(!mLinkingState);
2112     return mState.mExecutable->getProgramInputs();
2113 }
2114 
getComputeShaderLocalSize() const2115 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
2116 {
2117     ASSERT(!mLinkingState);
2118     return mState.mComputeShaderLocalSize;
2119 }
2120 
getGeometryShaderInputPrimitiveType() const2121 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
2122 {
2123     ASSERT(!mLinkingState && mState.mExecutable);
2124     return mState.mExecutable->getGeometryShaderInputPrimitiveType();
2125 }
getGeometryShaderOutputPrimitiveType() const2126 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
2127 {
2128     ASSERT(!mLinkingState && mState.mExecutable);
2129     return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
2130 }
getGeometryShaderInvocations() const2131 GLint Program::getGeometryShaderInvocations() const
2132 {
2133     ASSERT(!mLinkingState && mState.mExecutable);
2134     return mState.mExecutable->getGeometryShaderInvocations();
2135 }
getGeometryShaderMaxVertices() const2136 GLint Program::getGeometryShaderMaxVertices() const
2137 {
2138     ASSERT(!mLinkingState && mState.mExecutable);
2139     return mState.mExecutable->getGeometryShaderMaxVertices();
2140 }
2141 
getTessControlShaderVertices() const2142 GLint Program::getTessControlShaderVertices() const
2143 {
2144     ASSERT(!mLinkingState && mState.mExecutable);
2145     return mState.mExecutable->mTessControlShaderVertices;
2146 }
2147 
getTessGenMode() const2148 GLenum Program::getTessGenMode() const
2149 {
2150     ASSERT(!mLinkingState && mState.mExecutable);
2151     return mState.mExecutable->mTessGenMode;
2152 }
2153 
getTessGenPointMode() const2154 GLenum Program::getTessGenPointMode() const
2155 {
2156     ASSERT(!mLinkingState && mState.mExecutable);
2157     return mState.mExecutable->mTessGenPointMode;
2158 }
2159 
getTessGenSpacing() const2160 GLenum Program::getTessGenSpacing() const
2161 {
2162     ASSERT(!mLinkingState && mState.mExecutable);
2163     return mState.mExecutable->mTessGenSpacing;
2164 }
2165 
getTessGenVertexOrder() const2166 GLenum Program::getTessGenVertexOrder() const
2167 {
2168     ASSERT(!mLinkingState && mState.mExecutable);
2169     return mState.mExecutable->mTessGenVertexOrder;
2170 }
2171 
getInputResource(size_t index) const2172 const sh::ShaderVariable &Program::getInputResource(size_t index) const
2173 {
2174     ASSERT(!mLinkingState);
2175     ASSERT(index < mState.mExecutable->getProgramInputs().size());
2176     return mState.mExecutable->getProgramInputs()[index];
2177 }
2178 
getInputResourceIndex(const GLchar * name) const2179 GLuint Program::getInputResourceIndex(const GLchar *name) const
2180 {
2181     ASSERT(!mLinkingState);
2182     const std::string nameString = StripLastArrayIndex(name);
2183 
2184     for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
2185     {
2186         sh::ShaderVariable resource = getInputResource(index);
2187         if (resource.name == nameString)
2188         {
2189             return static_cast<GLuint>(index);
2190         }
2191     }
2192 
2193     return GL_INVALID_INDEX;
2194 }
2195 
getResourceMaxNameSize(const sh::ShaderVariable & resource,GLint max) const2196 GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
2197 {
2198     if (resource.isArray())
2199     {
2200         return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
2201     }
2202     else
2203     {
2204         return std::max(max, clampCast<GLint>((resource.name).size()));
2205     }
2206 }
2207 
getInputResourceMaxNameSize() const2208 GLuint Program::getInputResourceMaxNameSize() const
2209 {
2210     GLint max = 0;
2211 
2212     for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
2213     {
2214         max = getResourceMaxNameSize(resource, max);
2215     }
2216 
2217     return max;
2218 }
2219 
getOutputResourceMaxNameSize() const2220 GLuint Program::getOutputResourceMaxNameSize() const
2221 {
2222     GLint max = 0;
2223 
2224     for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
2225     {
2226         max = getResourceMaxNameSize(resource, max);
2227     }
2228 
2229     return max;
2230 }
2231 
getResourceLocation(const GLchar * name,const sh::ShaderVariable & variable) const2232 GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
2233 {
2234     if (variable.isBuiltIn())
2235     {
2236         return GL_INVALID_INDEX;
2237     }
2238 
2239     GLint location = variable.location;
2240     if (variable.isArray())
2241     {
2242         size_t nameLengthWithoutArrayIndexOut;
2243         size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
2244         // The 'name' string may not contain the array notation "[0]"
2245         if (arrayIndex != GL_INVALID_INDEX)
2246         {
2247             location += arrayIndex;
2248         }
2249     }
2250 
2251     return location;
2252 }
2253 
getInputResourceLocation(const GLchar * name) const2254 GLuint Program::getInputResourceLocation(const GLchar *name) const
2255 {
2256     const GLuint index = getInputResourceIndex(name);
2257     if (index == GL_INVALID_INDEX)
2258     {
2259         return index;
2260     }
2261 
2262     const sh::ShaderVariable &variable = getInputResource(index);
2263 
2264     return getResourceLocation(name, variable);
2265 }
2266 
getOutputResourceLocation(const GLchar * name) const2267 GLuint Program::getOutputResourceLocation(const GLchar *name) const
2268 {
2269     const GLuint index = getOutputResourceIndex(name);
2270     if (index == GL_INVALID_INDEX)
2271     {
2272         return index;
2273     }
2274 
2275     const sh::ShaderVariable &variable = getOutputResource(index);
2276 
2277     return getResourceLocation(name, variable);
2278 }
2279 
getOutputResourceIndex(const GLchar * name) const2280 GLuint Program::getOutputResourceIndex(const GLchar *name) const
2281 {
2282     ASSERT(!mLinkingState);
2283     const std::string nameString = StripLastArrayIndex(name);
2284 
2285     for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
2286     {
2287         sh::ShaderVariable resource = getOutputResource(index);
2288         if (resource.name == nameString)
2289         {
2290             return static_cast<GLuint>(index);
2291         }
2292     }
2293 
2294     return GL_INVALID_INDEX;
2295 }
2296 
getOutputResourceCount() const2297 size_t Program::getOutputResourceCount() const
2298 {
2299     ASSERT(!mLinkingState);
2300     return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
2301 }
2302 
getOutputVariableTypes() const2303 const std::vector<GLenum> &Program::getOutputVariableTypes() const
2304 {
2305     ASSERT(!mLinkingState);
2306     return mState.mOutputVariableTypes;
2307 }
2308 
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2309 void Program::getResourceName(const std::string name,
2310                               GLsizei bufSize,
2311                               GLsizei *length,
2312                               GLchar *dest) const
2313 {
2314     if (length)
2315     {
2316         *length = 0;
2317     }
2318 
2319     if (!mLinked)
2320     {
2321         if (bufSize > 0)
2322         {
2323             dest[0] = '\0';
2324         }
2325         return;
2326     }
2327 
2328     if (bufSize > 0)
2329     {
2330         CopyStringToBuffer(dest, name, bufSize, length);
2331     }
2332 }
2333 
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2334 void Program::getInputResourceName(GLuint index,
2335                                    GLsizei bufSize,
2336                                    GLsizei *length,
2337                                    GLchar *name) const
2338 {
2339     ASSERT(!mLinkingState);
2340     getResourceName(getInputResourceName(index), bufSize, length, name);
2341 }
2342 
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2343 void Program::getOutputResourceName(GLuint index,
2344                                     GLsizei bufSize,
2345                                     GLsizei *length,
2346                                     GLchar *name) const
2347 {
2348     ASSERT(!mLinkingState);
2349     getResourceName(getOutputResourceName(index), bufSize, length, name);
2350 }
2351 
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2352 void Program::getUniformResourceName(GLuint index,
2353                                      GLsizei bufSize,
2354                                      GLsizei *length,
2355                                      GLchar *name) const
2356 {
2357     ASSERT(!mLinkingState);
2358     ASSERT(index < mState.mExecutable->getUniforms().size());
2359     getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
2360 }
2361 
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2362 void Program::getBufferVariableResourceName(GLuint index,
2363                                             GLsizei bufSize,
2364                                             GLsizei *length,
2365                                             GLchar *name) const
2366 {
2367     ASSERT(!mLinkingState);
2368     ASSERT(index < mState.mBufferVariables.size());
2369     getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
2370 }
2371 
getResourceName(const sh::ShaderVariable & resource) const2372 const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
2373 {
2374     std::string resourceName = resource.name;
2375 
2376     if (resource.isArray())
2377     {
2378         resourceName += "[0]";
2379     }
2380 
2381     return resourceName;
2382 }
2383 
getInputResourceName(GLuint index) const2384 const std::string Program::getInputResourceName(GLuint index) const
2385 {
2386     ASSERT(!mLinkingState);
2387     const sh::ShaderVariable &resource = getInputResource(index);
2388 
2389     return getResourceName(resource);
2390 }
2391 
getOutputResourceName(GLuint index) const2392 const std::string Program::getOutputResourceName(GLuint index) const
2393 {
2394     ASSERT(!mLinkingState);
2395     const sh::ShaderVariable &resource = getOutputResource(index);
2396 
2397     return getResourceName(resource);
2398 }
2399 
getOutputResource(size_t index) const2400 const sh::ShaderVariable &Program::getOutputResource(size_t index) const
2401 {
2402     ASSERT(!mLinkingState);
2403     ASSERT(index < mState.mExecutable->getOutputVariables().size());
2404     return mState.mExecutable->getOutputVariables()[index];
2405 }
2406 
getAttributeBindings() const2407 const ProgramBindings &Program::getAttributeBindings() const
2408 {
2409     ASSERT(!mLinkingState);
2410     return mAttributeBindings;
2411 }
getUniformLocationBindings() const2412 const ProgramAliasedBindings &Program::getUniformLocationBindings() const
2413 {
2414     ASSERT(!mLinkingState);
2415     return mState.mUniformLocationBindings;
2416 }
2417 
getFragmentOutputLocations() const2418 const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
2419 {
2420     ASSERT(!mLinkingState);
2421     return mFragmentOutputLocations;
2422 }
2423 
getFragmentOutputIndexes() const2424 const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
2425 {
2426     ASSERT(!mLinkingState);
2427     return mFragmentOutputIndexes;
2428 }
2429 
getDrawBufferTypeMask() const2430 ComponentTypeMask Program::getDrawBufferTypeMask() const
2431 {
2432     ASSERT(!mLinkingState);
2433     return mState.mDrawBufferTypeMask;
2434 }
2435 
getTransformFeedbackStrides() const2436 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2437 {
2438     ASSERT(!mLinkingState);
2439     return mState.mExecutable->getTransformFeedbackStrides();
2440 }
2441 
getFragDataLocation(const std::string & name) const2442 GLint Program::getFragDataLocation(const std::string &name) const
2443 {
2444     ASSERT(!mLinkingState);
2445     GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
2446                                                 mState.mExecutable->getOutputLocations(), name);
2447     if (primaryLocation != -1)
2448     {
2449         return primaryLocation;
2450     }
2451     return GetVariableLocation(mState.mExecutable->getOutputVariables(),
2452                                mState.mExecutable->getSecondaryOutputLocations(), name);
2453 }
2454 
getFragDataIndex(const std::string & name) const2455 GLint Program::getFragDataIndex(const std::string &name) const
2456 {
2457     ASSERT(!mLinkingState);
2458     if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2459                             mState.mExecutable->getOutputLocations(), name) != -1)
2460     {
2461         return 0;
2462     }
2463     if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2464                             mState.mExecutable->getSecondaryOutputLocations(), name) != -1)
2465     {
2466         return 1;
2467     }
2468     return -1;
2469 }
2470 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2471 void Program::getActiveUniform(GLuint index,
2472                                GLsizei bufsize,
2473                                GLsizei *length,
2474                                GLint *size,
2475                                GLenum *type,
2476                                GLchar *name) const
2477 {
2478     ASSERT(!mLinkingState);
2479     if (mLinked)
2480     {
2481         // index must be smaller than getActiveUniformCount()
2482         ASSERT(index < mState.mExecutable->getUniforms().size());
2483         const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
2484 
2485         if (bufsize > 0)
2486         {
2487             std::string string = uniform.name;
2488             CopyStringToBuffer(name, string, bufsize, length);
2489         }
2490 
2491         *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2492         *type = uniform.type;
2493     }
2494     else
2495     {
2496         if (bufsize > 0)
2497         {
2498             name[0] = '\0';
2499         }
2500 
2501         if (length)
2502         {
2503             *length = 0;
2504         }
2505 
2506         *size = 0;
2507         *type = GL_NONE;
2508     }
2509 }
2510 
getActiveUniformCount() const2511 GLint Program::getActiveUniformCount() const
2512 {
2513     ASSERT(!mLinkingState);
2514     if (mLinked)
2515     {
2516         return static_cast<GLint>(mState.mExecutable->getUniforms().size());
2517     }
2518     else
2519     {
2520         return 0;
2521     }
2522 }
2523 
getActiveBufferVariableCount() const2524 size_t Program::getActiveBufferVariableCount() const
2525 {
2526     ASSERT(!mLinkingState);
2527     return mLinked ? mState.mBufferVariables.size() : 0;
2528 }
2529 
getActiveUniformMaxLength() const2530 GLint Program::getActiveUniformMaxLength() const
2531 {
2532     ASSERT(!mLinkingState);
2533     size_t maxLength = 0;
2534 
2535     if (mLinked)
2536     {
2537         for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
2538         {
2539             if (!uniform.name.empty())
2540             {
2541                 size_t length = uniform.name.length() + 1u;
2542                 if (uniform.isArray())
2543                 {
2544                     length += 3;  // Counting in "[0]".
2545                 }
2546                 maxLength = std::max(length, maxLength);
2547             }
2548         }
2549     }
2550 
2551     return static_cast<GLint>(maxLength);
2552 }
2553 
isValidUniformLocation(UniformLocation location) const2554 bool Program::isValidUniformLocation(UniformLocation location) const
2555 {
2556     ASSERT(!mLinkingState);
2557     ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2558     return (location.value >= 0 &&
2559             static_cast<size_t>(location.value) < mState.mUniformLocations.size() &&
2560             mState.mUniformLocations[static_cast<size_t>(location.value)].used());
2561 }
2562 
getUniformByLocation(UniformLocation location) const2563 const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const
2564 {
2565     ASSERT(!mLinkingState);
2566     ASSERT(location.value >= 0 &&
2567            static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2568     return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
2569 }
2570 
getUniformLocation(UniformLocation location) const2571 const VariableLocation &Program::getUniformLocation(UniformLocation location) const
2572 {
2573     ASSERT(!mLinkingState);
2574     ASSERT(location.value >= 0 &&
2575            static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2576     return mState.mUniformLocations[location.value];
2577 }
2578 
getBufferVariableByIndex(GLuint index) const2579 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2580 {
2581     ASSERT(!mLinkingState);
2582     ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2583     return mState.mBufferVariables[index];
2584 }
2585 
getUniformLocation(const std::string & name) const2586 UniformLocation Program::getUniformLocation(const std::string &name) const
2587 {
2588     ASSERT(!mLinkingState);
2589     return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
2590 }
2591 
getUniformIndex(const std::string & name) const2592 GLuint Program::getUniformIndex(const std::string &name) const
2593 {
2594     ASSERT(!mLinkingState);
2595     return mState.getUniformIndexFromName(name);
2596 }
2597 
shouldIgnoreUniform(UniformLocation location) const2598 bool Program::shouldIgnoreUniform(UniformLocation location) const
2599 {
2600     if (location.value == -1)
2601     {
2602         return true;
2603     }
2604 
2605     if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored)
2606     {
2607         return true;
2608     }
2609 
2610     return false;
2611 }
2612 
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2613 void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2614 {
2615     ASSERT(!mLinkingState);
2616     if (shouldIgnoreUniform(location))
2617     {
2618         return;
2619     }
2620 
2621     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2622     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2623     mProgram->setUniform1fv(location.value, clampedCount, v);
2624 }
2625 
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2626 void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2627 {
2628     ASSERT(!mLinkingState);
2629     if (shouldIgnoreUniform(location))
2630     {
2631         return;
2632     }
2633 
2634     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2635     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2636     mProgram->setUniform2fv(location.value, clampedCount, v);
2637 }
2638 
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2639 void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2640 {
2641     ASSERT(!mLinkingState);
2642     if (shouldIgnoreUniform(location))
2643     {
2644         return;
2645     }
2646 
2647     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2648     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2649     mProgram->setUniform3fv(location.value, clampedCount, v);
2650 }
2651 
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2652 void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2653 {
2654     ASSERT(!mLinkingState);
2655     if (shouldIgnoreUniform(location))
2656     {
2657         return;
2658     }
2659 
2660     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2661     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2662     mProgram->setUniform4fv(location.value, clampedCount, v);
2663 }
2664 
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2665 void Program::setUniform1iv(Context *context,
2666                             UniformLocation location,
2667                             GLsizei count,
2668                             const GLint *v)
2669 {
2670     ASSERT(!mLinkingState);
2671     if (shouldIgnoreUniform(location))
2672     {
2673         return;
2674     }
2675 
2676     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2677     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2678 
2679     mProgram->setUniform1iv(location.value, clampedCount, v);
2680 
2681     if (mState.isSamplerUniformIndex(locationInfo.index))
2682     {
2683         updateSamplerUniform(context, locationInfo, clampedCount, v);
2684     }
2685 }
2686 
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2687 void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2688 {
2689     ASSERT(!mLinkingState);
2690     if (shouldIgnoreUniform(location))
2691     {
2692         return;
2693     }
2694 
2695     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2696     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2697     mProgram->setUniform2iv(location.value, clampedCount, v);
2698 }
2699 
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2700 void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2701 {
2702     ASSERT(!mLinkingState);
2703     if (shouldIgnoreUniform(location))
2704     {
2705         return;
2706     }
2707 
2708     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2709     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2710     mProgram->setUniform3iv(location.value, clampedCount, v);
2711 }
2712 
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2713 void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2714 {
2715     ASSERT(!mLinkingState);
2716     if (shouldIgnoreUniform(location))
2717     {
2718         return;
2719     }
2720 
2721     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2722     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2723     mProgram->setUniform4iv(location.value, clampedCount, v);
2724 }
2725 
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2726 void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2727 {
2728     ASSERT(!mLinkingState);
2729     if (shouldIgnoreUniform(location))
2730     {
2731         return;
2732     }
2733 
2734     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2735     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2736     mProgram->setUniform1uiv(location.value, clampedCount, v);
2737 }
2738 
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2739 void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2740 {
2741     ASSERT(!mLinkingState);
2742     if (shouldIgnoreUniform(location))
2743     {
2744         return;
2745     }
2746 
2747     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2748     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2749     mProgram->setUniform2uiv(location.value, clampedCount, v);
2750 }
2751 
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2752 void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2753 {
2754     ASSERT(!mLinkingState);
2755     if (shouldIgnoreUniform(location))
2756     {
2757         return;
2758     }
2759 
2760     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2761     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2762     mProgram->setUniform3uiv(location.value, clampedCount, v);
2763 }
2764 
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2765 void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2766 {
2767     ASSERT(!mLinkingState);
2768     if (shouldIgnoreUniform(location))
2769     {
2770         return;
2771     }
2772 
2773     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2774     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2775     mProgram->setUniform4uiv(location.value, clampedCount, v);
2776 }
2777 
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2778 void Program::setUniformMatrix2fv(UniformLocation location,
2779                                   GLsizei count,
2780                                   GLboolean transpose,
2781                                   const GLfloat *v)
2782 {
2783     ASSERT(!mLinkingState);
2784     if (shouldIgnoreUniform(location))
2785     {
2786         return;
2787     }
2788 
2789     GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
2790     mProgram->setUniformMatrix2fv(location.value, clampedCount, transpose, v);
2791 }
2792 
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2793 void Program::setUniformMatrix3fv(UniformLocation location,
2794                                   GLsizei count,
2795                                   GLboolean transpose,
2796                                   const GLfloat *v)
2797 {
2798     ASSERT(!mLinkingState);
2799     if (shouldIgnoreUniform(location))
2800     {
2801         return;
2802     }
2803 
2804     GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
2805     mProgram->setUniformMatrix3fv(location.value, clampedCount, transpose, v);
2806 }
2807 
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2808 void Program::setUniformMatrix4fv(UniformLocation location,
2809                                   GLsizei count,
2810                                   GLboolean transpose,
2811                                   const GLfloat *v)
2812 {
2813     ASSERT(!mLinkingState);
2814     if (shouldIgnoreUniform(location))
2815     {
2816         return;
2817     }
2818 
2819     GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
2820     mProgram->setUniformMatrix4fv(location.value, clampedCount, transpose, v);
2821 }
2822 
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2823 void Program::setUniformMatrix2x3fv(UniformLocation location,
2824                                     GLsizei count,
2825                                     GLboolean transpose,
2826                                     const GLfloat *v)
2827 {
2828     ASSERT(!mLinkingState);
2829     if (shouldIgnoreUniform(location))
2830     {
2831         return;
2832     }
2833 
2834     GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
2835     mProgram->setUniformMatrix2x3fv(location.value, clampedCount, transpose, v);
2836 }
2837 
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2838 void Program::setUniformMatrix2x4fv(UniformLocation location,
2839                                     GLsizei count,
2840                                     GLboolean transpose,
2841                                     const GLfloat *v)
2842 {
2843     ASSERT(!mLinkingState);
2844     if (shouldIgnoreUniform(location))
2845     {
2846         return;
2847     }
2848 
2849     GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
2850     mProgram->setUniformMatrix2x4fv(location.value, clampedCount, transpose, v);
2851 }
2852 
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2853 void Program::setUniformMatrix3x2fv(UniformLocation location,
2854                                     GLsizei count,
2855                                     GLboolean transpose,
2856                                     const GLfloat *v)
2857 {
2858     ASSERT(!mLinkingState);
2859     if (shouldIgnoreUniform(location))
2860     {
2861         return;
2862     }
2863 
2864     GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
2865     mProgram->setUniformMatrix3x2fv(location.value, clampedCount, transpose, v);
2866 }
2867 
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2868 void Program::setUniformMatrix3x4fv(UniformLocation location,
2869                                     GLsizei count,
2870                                     GLboolean transpose,
2871                                     const GLfloat *v)
2872 {
2873     ASSERT(!mLinkingState);
2874     if (shouldIgnoreUniform(location))
2875     {
2876         return;
2877     }
2878 
2879     GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
2880     mProgram->setUniformMatrix3x4fv(location.value, clampedCount, transpose, v);
2881 }
2882 
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2883 void Program::setUniformMatrix4x2fv(UniformLocation location,
2884                                     GLsizei count,
2885                                     GLboolean transpose,
2886                                     const GLfloat *v)
2887 {
2888     ASSERT(!mLinkingState);
2889     if (shouldIgnoreUniform(location))
2890     {
2891         return;
2892     }
2893 
2894     GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
2895     mProgram->setUniformMatrix4x2fv(location.value, clampedCount, transpose, v);
2896 }
2897 
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2898 void Program::setUniformMatrix4x3fv(UniformLocation location,
2899                                     GLsizei count,
2900                                     GLboolean transpose,
2901                                     const GLfloat *v)
2902 {
2903     ASSERT(!mLinkingState);
2904     if (shouldIgnoreUniform(location))
2905     {
2906         return;
2907     }
2908 
2909     GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
2910     mProgram->setUniformMatrix4x3fv(location.value, clampedCount, transpose, v);
2911 }
2912 
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2913 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2914 {
2915     ASSERT(!mLinkingState);
2916     GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2917     const std::vector<GLuint> &boundTextureUnits =
2918         mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
2919     return (uniformLocation.arrayIndex < boundTextureUnits.size())
2920                ? boundTextureUnits[uniformLocation.arrayIndex]
2921                : 0;
2922 }
2923 
getImageUniformBinding(const VariableLocation & uniformLocation) const2924 GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
2925 {
2926     ASSERT(!mLinkingState);
2927     GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
2928 
2929     const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings();
2930     const std::vector<GLuint> &boundImageUnits     = imageBindings[imageIndex].boundImageUnits;
2931     return boundImageUnits[uniformLocation.arrayIndex];
2932 }
2933 
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2934 void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const
2935 {
2936     ASSERT(!mLinkingState);
2937     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2938     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2939 
2940     if (uniform.isSampler())
2941     {
2942         *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2943         return;
2944     }
2945     else if (uniform.isImage())
2946     {
2947         *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2948         return;
2949     }
2950 
2951     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2952     if (nativeType == GL_FLOAT)
2953     {
2954         mProgram->getUniformfv(context, location.value, v);
2955     }
2956     else
2957     {
2958         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2959     }
2960 }
2961 
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2962 void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const
2963 {
2964     ASSERT(!mLinkingState);
2965     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2966     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2967 
2968     if (uniform.isSampler())
2969     {
2970         *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2971         return;
2972     }
2973     else if (uniform.isImage())
2974     {
2975         *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2976         return;
2977     }
2978 
2979     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2980     if (nativeType == GL_INT || nativeType == GL_BOOL)
2981     {
2982         mProgram->getUniformiv(context, location.value, v);
2983     }
2984     else
2985     {
2986         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2987     }
2988 }
2989 
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2990 void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const
2991 {
2992     ASSERT(!mLinkingState);
2993     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2994     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2995 
2996     if (uniform.isSampler())
2997     {
2998         *v = getSamplerUniformBinding(uniformLocation);
2999         return;
3000     }
3001     else if (uniform.isImage())
3002     {
3003         *v = getImageUniformBinding(uniformLocation);
3004         return;
3005     }
3006 
3007     const GLenum nativeType = VariableComponentType(uniform.type);
3008     if (nativeType == GL_UNSIGNED_INT)
3009     {
3010         mProgram->getUniformuiv(context, location.value, v);
3011     }
3012     else
3013     {
3014         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
3015     }
3016 }
3017 
flagForDeletion()3018 void Program::flagForDeletion()
3019 {
3020     ASSERT(!mLinkingState);
3021     mDeleteStatus = true;
3022 }
3023 
isFlaggedForDeletion() const3024 bool Program::isFlaggedForDeletion() const
3025 {
3026     ASSERT(!mLinkingState);
3027     return mDeleteStatus;
3028 }
3029 
validate(const Caps & caps)3030 void Program::validate(const Caps &caps)
3031 {
3032     ASSERT(!mLinkingState);
3033     mState.mExecutable->resetInfoLog();
3034     InfoLog &infoLog = mState.mExecutable->getInfoLog();
3035 
3036     if (mLinked)
3037     {
3038         mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
3039     }
3040     else
3041     {
3042         infoLog << "Program has not been successfully linked.";
3043     }
3044 }
3045 
isValidated() const3046 bool Program::isValidated() const
3047 {
3048     ASSERT(!mLinkingState);
3049     return mValidated;
3050 }
3051 
getActiveUniformBlockName(const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3052 void Program::getActiveUniformBlockName(const UniformBlockIndex blockIndex,
3053                                         GLsizei bufSize,
3054                                         GLsizei *length,
3055                                         GLchar *blockName) const
3056 {
3057     ASSERT(!mLinkingState);
3058     GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
3059                           blockName);
3060 }
3061 
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3062 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
3063                                               GLsizei bufSize,
3064                                               GLsizei *length,
3065                                               GLchar *blockName) const
3066 {
3067     ASSERT(!mLinkingState);
3068     GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize,
3069                           length, blockName);
3070 }
3071 
3072 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const3073 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
3074 {
3075     int maxLength = 0;
3076 
3077     if (mLinked)
3078     {
3079         for (const T &resource : resources)
3080         {
3081             if (!resource.name.empty())
3082             {
3083                 int length = static_cast<int>(resource.nameWithArrayIndex().length());
3084                 maxLength  = std::max(length + 1, maxLength);
3085             }
3086         }
3087     }
3088 
3089     return maxLength;
3090 }
3091 
getActiveUniformBlockMaxNameLength() const3092 GLint Program::getActiveUniformBlockMaxNameLength() const
3093 {
3094     ASSERT(!mLinkingState);
3095     return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
3096 }
3097 
getActiveShaderStorageBlockMaxNameLength() const3098 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
3099 {
3100     ASSERT(!mLinkingState);
3101     return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
3102 }
3103 
getUniformBlockIndex(const std::string & name) const3104 GLuint Program::getUniformBlockIndex(const std::string &name) const
3105 {
3106     ASSERT(!mLinkingState);
3107     return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
3108 }
3109 
getShaderStorageBlockIndex(const std::string & name) const3110 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
3111 {
3112     ASSERT(!mLinkingState);
3113     return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
3114 }
3115 
getUniformBlockByIndex(GLuint index) const3116 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
3117 {
3118     ASSERT(!mLinkingState);
3119     ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
3120     return mState.mExecutable->getUniformBlocks()[index];
3121 }
3122 
getShaderStorageBlockByIndex(GLuint index) const3123 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
3124 {
3125     ASSERT(!mLinkingState);
3126     ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
3127     return mState.mExecutable->getShaderStorageBlocks()[index];
3128 }
3129 
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)3130 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
3131 {
3132     ASSERT(!mLinkingState);
3133     mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding;
3134     mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value,
3135                                                         uniformBlockBinding != 0);
3136     mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value);
3137 }
3138 
getUniformBlockBinding(GLuint uniformBlockIndex) const3139 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
3140 {
3141     ASSERT(!mLinkingState);
3142     return mState.getUniformBlockBinding(uniformBlockIndex);
3143 }
3144 
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const3145 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
3146 {
3147     ASSERT(!mLinkingState);
3148     return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
3149 }
3150 
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)3151 void Program::setTransformFeedbackVaryings(GLsizei count,
3152                                            const GLchar *const *varyings,
3153                                            GLenum bufferMode)
3154 {
3155     ASSERT(!mLinkingState);
3156     mState.mTransformFeedbackVaryingNames.resize(count);
3157     for (GLsizei i = 0; i < count; i++)
3158     {
3159         mState.mTransformFeedbackVaryingNames[i] = varyings[i];
3160     }
3161 
3162     mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
3163 }
3164 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const3165 void Program::getTransformFeedbackVarying(GLuint index,
3166                                           GLsizei bufSize,
3167                                           GLsizei *length,
3168                                           GLsizei *size,
3169                                           GLenum *type,
3170                                           GLchar *name) const
3171 {
3172     ASSERT(!mLinkingState);
3173     if (mLinked)
3174     {
3175         ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3176         const auto &var     = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3177         std::string varName = var.nameWithArrayIndex();
3178         GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
3179         if (length)
3180         {
3181             *length = lastNameIdx;
3182         }
3183         if (size)
3184         {
3185             *size = var.size();
3186         }
3187         if (type)
3188         {
3189             *type = var.type;
3190         }
3191         if (name)
3192         {
3193             memcpy(name, varName.c_str(), lastNameIdx);
3194             name[lastNameIdx] = '\0';
3195         }
3196     }
3197 }
3198 
getTransformFeedbackVaryingCount() const3199 GLsizei Program::getTransformFeedbackVaryingCount() const
3200 {
3201     ASSERT(!mLinkingState);
3202     if (mLinked)
3203     {
3204         return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3205     }
3206     else
3207     {
3208         return 0;
3209     }
3210 }
3211 
getTransformFeedbackVaryingMaxLength() const3212 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
3213 {
3214     ASSERT(!mLinkingState);
3215     if (mLinked)
3216     {
3217         GLsizei maxSize = 0;
3218         for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
3219         {
3220             maxSize =
3221                 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
3222         }
3223 
3224         return maxSize;
3225     }
3226     else
3227     {
3228         return 0;
3229     }
3230 }
3231 
getTransformFeedbackBufferMode() const3232 GLenum Program::getTransformFeedbackBufferMode() const
3233 {
3234     ASSERT(!mLinkingState);
3235     return mState.mExecutable->getTransformFeedbackBufferMode();
3236 }
3237 
linkValidateShaders(InfoLog & infoLog)3238 bool Program::linkValidateShaders(InfoLog &infoLog)
3239 {
3240     const ShaderMap<Shader *> &shaders = mState.mAttachedShaders;
3241 
3242     bool isComputeShaderAttached  = shaders[ShaderType::Compute] != nullptr;
3243     bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] ||
3244                                     shaders[ShaderType::TessControl] ||
3245                                     shaders[ShaderType::TessEvaluation] ||
3246                                     shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment];
3247     // Check whether we both have a compute and non-compute shaders attached.
3248     // If there are of both types attached, then linking should fail.
3249     // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
3250     if (isComputeShaderAttached && isGraphicsShaderAttached)
3251     {
3252         infoLog << "Both compute and graphics shaders are attached to the same program.";
3253         return false;
3254     }
3255 
3256     Optional<int> version;
3257     for (ShaderType shaderType : kAllGraphicsShaderTypes)
3258     {
3259         Shader *shader = shaders[shaderType];
3260         ASSERT(!shader || shader->getType() == shaderType);
3261         if (!shader)
3262         {
3263             continue;
3264         }
3265 
3266         if (!shader->isCompiled())
3267         {
3268             infoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
3269             return false;
3270         }
3271 
3272         if (!version.valid())
3273         {
3274             version = shader->getShaderVersion();
3275         }
3276         else if (version != shader->getShaderVersion())
3277         {
3278             infoLog << ShaderTypeToString(shaderType)
3279                     << " shader version does not match other shader versions.";
3280             return false;
3281         }
3282     }
3283 
3284     if (isComputeShaderAttached)
3285     {
3286         ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute);
3287 
3288         mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize();
3289 
3290         // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
3291         // If the work group size is not specified, a link time error should occur.
3292         if (!mState.mComputeShaderLocalSize.isDeclared())
3293         {
3294             infoLog << "Work group size is not specified.";
3295             return false;
3296         }
3297     }
3298     else
3299     {
3300         if (!isGraphicsShaderAttached)
3301         {
3302             infoLog << "No compiled shaders.";
3303             return false;
3304         }
3305 
3306         bool hasVertex   = shaders[ShaderType::Vertex] != nullptr;
3307         bool hasFragment = shaders[ShaderType::Fragment] != nullptr;
3308         if (!isSeparable() && (!hasVertex || !hasFragment))
3309         {
3310             infoLog
3311                 << "The program must contain objects to form both a vertex and fragment shader.";
3312             return false;
3313         }
3314 
3315         bool hasTessControl    = shaders[ShaderType::TessControl] != nullptr;
3316         bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr;
3317         if (!isSeparable() && (hasTessControl != hasTessEvaluation))
3318         {
3319             infoLog << "Tessellation control and evaluation shaders must be specified together.";
3320             return false;
3321         }
3322 
3323         Shader *geometryShader = shaders[ShaderType::Geometry];
3324         if (shaders[ShaderType::Geometry])
3325         {
3326             // [GL_EXT_geometry_shader] Chapter 7
3327             // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
3328             // Language Specification, as well as any of the following reasons:
3329             // * One or more of the shader objects attached to <program> are not compiled
3330             //   successfully.
3331             // * The shaders do not use the same shader language version.
3332             // * <program> contains objects to form a geometry shader, and
3333             //   - <program> is not separable and contains no objects to form a vertex shader; or
3334             //   - the input primitive type, output primitive type, or maximum output vertex count
3335             //     is not specified in the compiled geometry shader object.
3336             ASSERT(geometryShader->getType() == ShaderType::Geometry);
3337 
3338             Optional<PrimitiveMode> inputPrimitive =
3339                 geometryShader->getGeometryShaderInputPrimitiveType();
3340             if (!inputPrimitive.valid())
3341             {
3342                 infoLog << "Input primitive type is not specified in the geometry shader.";
3343                 return false;
3344             }
3345 
3346             Optional<PrimitiveMode> outputPrimitive =
3347                 geometryShader->getGeometryShaderOutputPrimitiveType();
3348             if (!outputPrimitive.valid())
3349             {
3350                 infoLog << "Output primitive type is not specified in the geometry shader.";
3351                 return false;
3352             }
3353 
3354             Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
3355             if (!maxVertices.valid())
3356             {
3357                 infoLog << "'max_vertices' is not specified in the geometry shader.";
3358                 return false;
3359             }
3360 
3361             mState.mExecutable->mGeometryShaderInputPrimitiveType  = inputPrimitive.value();
3362             mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
3363             mState.mExecutable->mGeometryShaderMaxVertices         = maxVertices.value();
3364             mState.mExecutable->mGeometryShaderInvocations =
3365                 geometryShader->getGeometryShaderInvocations();
3366         }
3367 
3368         Shader *tessControlShader = shaders[ShaderType::TessControl];
3369         if (tessControlShader)
3370         {
3371             int tcsShaderVertices = tessControlShader->getTessControlShaderVertices();
3372             if (tcsShaderVertices == 0)
3373             {
3374                 // In tessellation control shader, output vertices should be specified at least
3375                 // once.
3376                 // > GLSL ES Version 3.20.6 spec:
3377                 // > 4.4.2. Output Layout Qualifiers
3378                 // > Tessellation Control Outputs
3379                 // > ...
3380                 // > There must be at least one layout qualifier specifying an output patch vertex
3381                 // > count in any program containing a tessellation control shader.
3382                 infoLog << "In Tessellation Control Shader, at least one layout qualifier "
3383                            "specifying an output patch vertex count must exist.";
3384                 return false;
3385             }
3386 
3387             mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
3388         }
3389 
3390         Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
3391         if (tessEvaluationShader)
3392         {
3393             GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode();
3394             if (tesPrimitiveMode == 0)
3395             {
3396                 // In tessellation evaluation shader, a primitive mode should be specified at least
3397                 // once.
3398                 // > GLSL ES Version 3.20.6 spec:
3399                 // > 4.4.1. Input Layout Qualifiers
3400                 // > Tessellation Evaluation Inputs
3401                 // > ...
3402                 // > The tessellation evaluation shader object in a program must declare a primitive
3403                 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
3404                 // > identifiers is optional.
3405                 infoLog << "The Tessellation Evaluation Shader object in a program must declare a "
3406                            "primitive mode in its input layout.";
3407                 return false;
3408             }
3409 
3410             mState.mExecutable->mTessGenMode        = tesPrimitiveMode;
3411             mState.mExecutable->mTessGenSpacing     = tessEvaluationShader->getTessGenSpacing();
3412             mState.mExecutable->mTessGenVertexOrder = tessEvaluationShader->getTessGenVertexOrder();
3413             mState.mExecutable->mTessGenPointMode   = tessEvaluationShader->getTessGenPointMode();
3414         }
3415     }
3416 
3417     return true;
3418 }
3419 
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const3420 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
3421 {
3422     ASSERT(!mLinkingState);
3423     for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
3424          ++tfIndex)
3425     {
3426         const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
3427         if (tf.nameWithArrayIndex() == name)
3428         {
3429             return tfIndex;
3430         }
3431     }
3432     return GL_INVALID_INDEX;
3433 }
3434 
getTransformFeedbackVaryingResource(GLuint index) const3435 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
3436 {
3437     ASSERT(!mLinkingState);
3438     ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3439     return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3440 }
3441 
hasDrawIDUniform() const3442 bool Program::hasDrawIDUniform() const
3443 {
3444     ASSERT(!mLinkingState);
3445     return mState.mDrawIDLocation >= 0;
3446 }
3447 
setDrawIDUniform(GLint drawid)3448 void Program::setDrawIDUniform(GLint drawid)
3449 {
3450     ASSERT(!mLinkingState);
3451     ASSERT(mState.mDrawIDLocation >= 0);
3452     mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
3453 }
3454 
hasBaseVertexUniform() const3455 bool Program::hasBaseVertexUniform() const
3456 {
3457     ASSERT(!mLinkingState);
3458     return mState.mBaseVertexLocation >= 0;
3459 }
3460 
setBaseVertexUniform(GLint baseVertex)3461 void Program::setBaseVertexUniform(GLint baseVertex)
3462 {
3463     ASSERT(!mLinkingState);
3464     ASSERT(mState.mBaseVertexLocation >= 0);
3465     if (baseVertex == mState.mCachedBaseVertex)
3466     {
3467         return;
3468     }
3469     mState.mCachedBaseVertex = baseVertex;
3470     mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
3471 }
3472 
hasBaseInstanceUniform() const3473 bool Program::hasBaseInstanceUniform() const
3474 {
3475     ASSERT(!mLinkingState);
3476     return mState.mBaseInstanceLocation >= 0;
3477 }
3478 
setBaseInstanceUniform(GLuint baseInstance)3479 void Program::setBaseInstanceUniform(GLuint baseInstance)
3480 {
3481     ASSERT(!mLinkingState);
3482     ASSERT(mState.mBaseInstanceLocation >= 0);
3483     if (baseInstance == mState.mCachedBaseInstance)
3484     {
3485         return;
3486     }
3487     mState.mCachedBaseInstance = baseInstance;
3488     GLint baseInstanceInt      = baseInstance;
3489     mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
3490 }
3491 
linkVaryings(InfoLog & infoLog) const3492 bool Program::linkVaryings(InfoLog &infoLog) const
3493 {
3494     ShaderType previousShaderType = ShaderType::InvalidEnum;
3495     for (ShaderType shaderType : kAllGraphicsShaderTypes)
3496     {
3497         Shader *currentShader = mState.mAttachedShaders[shaderType];
3498         if (!currentShader)
3499         {
3500             continue;
3501         }
3502 
3503         if (previousShaderType != ShaderType::InvalidEnum)
3504         {
3505             Shader *previousShader = mState.mAttachedShaders[previousShaderType];
3506             const std::vector<sh::ShaderVariable> &outputVaryings =
3507                 previousShader->getOutputVaryings();
3508 
3509             if (!LinkValidateShaderInterfaceMatching(
3510                     outputVaryings, currentShader->getInputVaryings(), previousShaderType,
3511                     currentShader->getType(), previousShader->getShaderVersion(),
3512                     currentShader->getShaderVersion(), isSeparable(), infoLog))
3513             {
3514                 return false;
3515             }
3516         }
3517         previousShaderType = currentShader->getType();
3518     }
3519 
3520     // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
3521     // Need to move logic of validating builtin varyings inside the for-loop above.
3522     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
3523     // can be redeclared in Geometry or Tessellation shaders as well.
3524     Shader *vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
3525     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
3526     if (vertexShader && fragmentShader &&
3527         !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
3528                                      fragmentShader->getInputVaryings(), vertexShader->getType(),
3529                                      fragmentShader->getType(), vertexShader->getShaderVersion(),
3530                                      fragmentShader->getShaderVersion(), infoLog))
3531     {
3532         return false;
3533     }
3534 
3535     return true;
3536 }
3537 
linkUniforms(const Caps & caps,const Version & version,InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings,GLuint * combinedImageUniformsCount,std::vector<UnusedUniform> * unusedUniforms)3538 bool Program::linkUniforms(const Caps &caps,
3539                            const Version &version,
3540                            InfoLog &infoLog,
3541                            const ProgramAliasedBindings &uniformLocationBindings,
3542                            GLuint *combinedImageUniformsCount,
3543                            std::vector<UnusedUniform> *unusedUniforms)
3544 {
3545     UniformLinker linker(mState);
3546     if (!linker.link(caps, infoLog, uniformLocationBindings))
3547     {
3548         return false;
3549     }
3550 
3551     linker.getResults(&mState.mExecutable->mUniforms, unusedUniforms, &mState.mUniformLocations);
3552 
3553     linkSamplerAndImageBindings(combinedImageUniformsCount);
3554 
3555     if (!linkAtomicCounterBuffers())
3556     {
3557         return false;
3558     }
3559 
3560     if (version >= Version(3, 1))
3561     {
3562         GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size());
3563 
3564         if (locationSize > caps.maxUniformLocations)
3565         {
3566             infoLog << "Exceeded maximum uniform location size";
3567             return false;
3568         }
3569     }
3570 
3571     return true;
3572 }
3573 
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)3574 void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
3575 {
3576     ASSERT(combinedImageUniforms);
3577 
3578     // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
3579     // atomic counters, images and samplers in that order.
3580     auto highIter = mState.mExecutable->getUniforms().rbegin();
3581     auto lowIter  = highIter;
3582 
3583     unsigned int high = static_cast<unsigned int>(mState.mExecutable->getUniforms().size());
3584     unsigned int low  = high;
3585 
3586     // Note that uniform block uniforms are not yet appended to this list.
3587     ASSERT(mState.mExecutable->getUniforms().size() == 0 || highIter->isAtomicCounter() ||
3588            highIter->isImage() || highIter->isSampler() || highIter->isInDefaultBlock() ||
3589            highIter->isFragmentInOut);
3590 
3591     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isFragmentInOut;
3592          ++lowIter)
3593     {
3594         --low;
3595     }
3596 
3597     mState.mExecutable->mFragmentInoutRange = RangeUI(low, high);
3598 
3599     highIter = lowIter;
3600     high     = low;
3601 
3602     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isAtomicCounter();
3603          ++lowIter)
3604     {
3605         --low;
3606     }
3607 
3608     mState.mAtomicCounterUniformRange = RangeUI(low, high);
3609 
3610     highIter = lowIter;
3611     high     = low;
3612 
3613     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isImage(); ++lowIter)
3614     {
3615         --low;
3616     }
3617 
3618     mState.mExecutable->mImageUniformRange = RangeUI(low, high);
3619     *combinedImageUniforms                 = 0u;
3620     // The Program is still linking, so getExecutable().isCompute() isn't accurate yet.
3621     bool hasComputeShader = mState.mAttachedShaders[ShaderType::Compute] != nullptr;
3622     std::vector<ImageBinding> &imageBindings = hasComputeShader
3623                                                    ? mState.mExecutable->mComputeImageBindings
3624                                                    : mState.mExecutable->mGraphicsImageBindings;
3625     // If uniform is a image type, insert it into the mImageBindings array.
3626     for (unsigned int imageIndex : mState.mExecutable->getImageUniformRange())
3627     {
3628         // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
3629         // cannot load values into a uniform defined as an image. if declare without a
3630         // binding qualifier, any uniform image variable (include all elements of
3631         // unbound image array) shoud be bound to unit zero.
3632         auto &imageUniform      = mState.mExecutable->getUniforms()[imageIndex];
3633         TextureType textureType = ImageTypeToTextureType(imageUniform.type);
3634         const GLuint arraySize  = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
3635 
3636         if (imageUniform.binding == -1)
3637         {
3638             imageBindings.emplace_back(
3639                 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
3640         }
3641         else
3642         {
3643             // The arrays of arrays are flattened to arrays, it needs to record the array offset for
3644             // the correct binding image unit.
3645             imageBindings.emplace_back(
3646                 ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize,
3647                              imageUniform.getBasicTypeElementCount(), textureType));
3648         }
3649 
3650         *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
3651     }
3652 
3653     highIter = lowIter;
3654     high     = low;
3655 
3656     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isSampler(); ++lowIter)
3657     {
3658         --low;
3659     }
3660 
3661     mState.mExecutable->mSamplerUniformRange = RangeUI(low, high);
3662 
3663     // If uniform is a sampler type, insert it into the mSamplerBindings array.
3664     for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
3665     {
3666         const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
3667         TextureType textureType    = SamplerTypeToTextureType(samplerUniform.type);
3668         GLenum samplerType         = samplerUniform.typeInfo->type;
3669         unsigned int elementCount  = samplerUniform.getBasicTypeElementCount();
3670         SamplerFormat format       = samplerUniform.typeInfo->samplerFormat;
3671         mState.mExecutable->mSamplerBindings.emplace_back(textureType, samplerType, format,
3672                                                           elementCount);
3673     }
3674 
3675     // Whatever is left constitutes the default uniforms.
3676     mState.mExecutable->mDefaultUniformRange = RangeUI(0, low);
3677 }
3678 
linkAtomicCounterBuffers()3679 bool Program::linkAtomicCounterBuffers()
3680 {
3681     for (unsigned int index : mState.mAtomicCounterUniformRange)
3682     {
3683         auto &uniform                      = mState.mExecutable->mUniforms[index];
3684         uniform.blockInfo.offset           = uniform.offset;
3685         uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
3686         uniform.blockInfo.matrixStride     = 0;
3687         uniform.blockInfo.isRowMajorMatrix = false;
3688 
3689         bool found = false;
3690         for (unsigned int bufferIndex = 0;
3691              bufferIndex < mState.mExecutable->getActiveAtomicCounterBufferCount(); ++bufferIndex)
3692         {
3693             auto &buffer = mState.mExecutable->mAtomicCounterBuffers[bufferIndex];
3694             if (buffer.binding == uniform.binding)
3695             {
3696                 buffer.memberIndexes.push_back(index);
3697                 uniform.bufferIndex = bufferIndex;
3698                 found               = true;
3699                 buffer.unionReferencesWith(uniform);
3700                 break;
3701             }
3702         }
3703         if (!found)
3704         {
3705             AtomicCounterBuffer atomicCounterBuffer;
3706             atomicCounterBuffer.binding = uniform.binding;
3707             atomicCounterBuffer.memberIndexes.push_back(index);
3708             atomicCounterBuffer.unionReferencesWith(uniform);
3709             mState.mExecutable->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
3710             uniform.bufferIndex =
3711                 static_cast<int>(mState.mExecutable->getActiveAtomicCounterBufferCount() - 1);
3712         }
3713     }
3714     // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
3715     // gl_Max[Vertex|Fragment|Compute|Geometry|Combined]AtomicCounterBuffers.
3716 
3717     return true;
3718 }
3719 
3720 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3721 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3722 {
3723     const Caps &caps               = context->getCaps();
3724     const Limitations &limitations = context->getLimitations();
3725     bool webglCompatibility        = context->getExtensions().webglCompatibility;
3726     int shaderVersion              = -1;
3727     unsigned int usedLocations     = 0;
3728 
3729     Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
3730 
3731     if (!vertexShader)
3732     {
3733         // No vertex shader, so no attributes, so nothing to do
3734         return true;
3735     }
3736 
3737     shaderVersion = vertexShader->getShaderVersion();
3738     if (shaderVersion >= 300)
3739     {
3740         // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
3741         // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
3742         // aliasing checks.
3743         mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes();
3744     }
3745     else
3746     {
3747         // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3748         mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes();
3749     }
3750 
3751     GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
3752     std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
3753 
3754     // Assign locations to attributes that have a binding location and check for attribute aliasing.
3755     for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3756     {
3757         // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3758         // structures, so we don't need to worry about adjusting their names or generating entries
3759         // for each member/element (unlike uniforms for example).
3760         ASSERT(!attribute.isArray() && !attribute.isStruct());
3761 
3762         int bindingLocation = mAttributeBindings.getBinding(attribute);
3763         if (attribute.location == -1 && bindingLocation != -1)
3764         {
3765             attribute.location = bindingLocation;
3766         }
3767 
3768         if (attribute.location != -1)
3769         {
3770             // Location is set by glBindAttribLocation or by location layout qualifier
3771             const int regs = VariableRegisterCount(attribute.type);
3772 
3773             if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3774             {
3775                 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3776                         << " is too big to fit";
3777 
3778                 return false;
3779             }
3780 
3781             for (int reg = 0; reg < regs; reg++)
3782             {
3783                 const int regLocation               = attribute.location + reg;
3784                 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3785 
3786                 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3787                 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3788                 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3789                 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3790                 if (linkedAttribute)
3791                 {
3792                     if (shaderVersion >= 300 || webglCompatibility ||
3793                         limitations.noVertexAttributeAliasing)
3794                     {
3795                         infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3796                                 << linkedAttribute->name << "' at location " << regLocation;
3797                         return false;
3798                     }
3799                 }
3800                 else
3801                 {
3802                     usedAttribMap[regLocation] = &attribute;
3803                 }
3804 
3805                 usedLocations |= 1 << regLocation;
3806             }
3807         }
3808     }
3809 
3810     // Assign locations to attributes that don't have a binding location.
3811     for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3812     {
3813         // Not set by glBindAttribLocation or by location layout qualifier
3814         if (attribute.location == -1)
3815         {
3816             int regs           = VariableRegisterCount(attribute.type);
3817             int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3818 
3819             if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3820             {
3821                 infoLog << "Too many attributes (" << attribute.name << ")";
3822                 return false;
3823             }
3824 
3825             attribute.location = availableIndex;
3826         }
3827     }
3828 
3829     ASSERT(mState.mExecutable->mAttributesTypeMask.none());
3830     ASSERT(mState.mExecutable->mAttributesMask.none());
3831 
3832     // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3833     // shader versions we're only processing active attributes to begin with.
3834     if (shaderVersion >= 300)
3835     {
3836         for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
3837              attributeIter != mState.mExecutable->getProgramInputs().end();)
3838         {
3839             if (attributeIter->active)
3840             {
3841                 ++attributeIter;
3842             }
3843             else
3844             {
3845                 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
3846             }
3847         }
3848     }
3849 
3850     for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
3851     {
3852         ASSERT(attribute.active);
3853         ASSERT(attribute.location != -1);
3854         unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3855 
3856         unsigned int location = static_cast<unsigned int>(attribute.location);
3857         for (unsigned int r = 0; r < regs; r++)
3858         {
3859             // Built-in active program inputs don't have a bound attribute.
3860             if (!attribute.isBuiltIn())
3861             {
3862                 mState.mExecutable->mActiveAttribLocationsMask.set(location);
3863                 mState.mExecutable->mMaxActiveAttribLocation =
3864                     std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
3865 
3866                 ComponentType componentType =
3867                     GLenumToComponentType(VariableComponentType(attribute.type));
3868 
3869                 SetComponentTypeMask(componentType, location,
3870                                      &mState.mExecutable->mAttributesTypeMask);
3871                 mState.mExecutable->mAttributesMask.set(location);
3872 
3873                 location++;
3874             }
3875         }
3876     }
3877 
3878     return true;
3879 }
3880 
linkInterfaceBlocks(const Caps & caps,const Version & version,bool webglCompatibility,InfoLog & infoLog,GLuint * combinedShaderStorageBlocksCount)3881 bool Program::linkInterfaceBlocks(const Caps &caps,
3882                                   const Version &version,
3883                                   bool webglCompatibility,
3884                                   InfoLog &infoLog,
3885                                   GLuint *combinedShaderStorageBlocksCount)
3886 {
3887     ASSERT(combinedShaderStorageBlocksCount);
3888 
3889     GLuint combinedUniformBlocksCount                                         = 0u;
3890     GLuint numShadersHasUniformBlocks                                         = 0u;
3891     ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
3892     InterfaceBlockMap instancelessInterfaceBlocksFields;
3893 
3894     for (ShaderType shaderType : AllShaderTypes())
3895     {
3896         Shader *shader = mState.mAttachedShaders[shaderType];
3897         if (!shader)
3898         {
3899             continue;
3900         }
3901 
3902         const auto &uniformBlocks = shader->getUniformBlocks();
3903         if (!uniformBlocks.empty())
3904         {
3905             if (!ValidateInterfaceBlocksCount(
3906                     static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks,
3907                     shaderType, sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
3908             {
3909                 return false;
3910             }
3911 
3912             allShaderUniformBlocks[shaderType] = &uniformBlocks;
3913             ++numShadersHasUniformBlocks;
3914         }
3915     }
3916 
3917     if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks))
3918     {
3919         infoLog << "The sum of the number of active uniform blocks exceeds "
3920                    "MAX_COMBINED_UNIFORM_BLOCKS ("
3921                 << caps.maxCombinedUniformBlocks << ").";
3922         return false;
3923     }
3924 
3925     if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
3926                                       webglCompatibility, &instancelessInterfaceBlocksFields))
3927     {
3928         return false;
3929     }
3930 
3931     if (version >= Version(3, 1))
3932     {
3933         *combinedShaderStorageBlocksCount                                         = 0u;
3934         GLuint numShadersHasShaderStorageBlocks                                   = 0u;
3935         ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
3936         for (ShaderType shaderType : AllShaderTypes())
3937         {
3938             Shader *shader = mState.mAttachedShaders[shaderType];
3939             if (!shader)
3940             {
3941                 continue;
3942             }
3943 
3944             const auto &shaderStorageBlocks = shader->getShaderStorageBlocks();
3945             if (!shaderStorageBlocks.empty())
3946             {
3947                 if (!ValidateInterfaceBlocksCount(
3948                         static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]),
3949                         shaderStorageBlocks, shaderType, sh::BlockType::BLOCK_BUFFER,
3950                         combinedShaderStorageBlocksCount, infoLog))
3951                 {
3952                     return false;
3953                 }
3954 
3955                 allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
3956                 ++numShadersHasShaderStorageBlocks;
3957             }
3958         }
3959 
3960         if (*combinedShaderStorageBlocksCount >
3961             static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks))
3962         {
3963             infoLog << "The sum of the number of active shader storage blocks exceeds "
3964                        "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
3965                     << caps.maxCombinedShaderStorageBlocks << ").";
3966             return false;
3967         }
3968 
3969         if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
3970                                           infoLog, webglCompatibility,
3971                                           &instancelessInterfaceBlocksFields))
3972         {
3973             return false;
3974         }
3975     }
3976 
3977     return true;
3978 }
3979 
getOutputLocationForLink(const sh::ShaderVariable & outputVariable) const3980 int Program::getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const
3981 {
3982     if (outputVariable.location != -1)
3983     {
3984         return outputVariable.location;
3985     }
3986     int apiLocation = mFragmentOutputLocations.getBinding(outputVariable);
3987     if (apiLocation != -1)
3988     {
3989         return apiLocation;
3990     }
3991     return -1;
3992 }
3993 
isOutputSecondaryForLink(const sh::ShaderVariable & outputVariable) const3994 bool Program::isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const
3995 {
3996     if (outputVariable.index != -1)
3997     {
3998         ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
3999         return (outputVariable.index == 1);
4000     }
4001     int apiIndex = mFragmentOutputIndexes.getBinding(outputVariable);
4002     if (apiIndex != -1)
4003     {
4004         // Index layout qualifier from the shader takes precedence, so the index from the API is
4005         // checked only if the index was not set in the shader. This is not specified in the EXT
4006         // spec, but is specified in desktop OpenGL specs.
4007         return (apiIndex == 1);
4008     }
4009     // EXT_blend_func_extended: Outputs get index 0 by default.
4010     return false;
4011 }
4012 
4013 namespace
4014 {
4015 
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)4016 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
4017                             unsigned int baseLocation,
4018                             unsigned int elementCount,
4019                             const std::vector<VariableLocation> &reservedLocations,
4020                             unsigned int variableIndex)
4021 {
4022     if (baseLocation + elementCount > outputLocations.size())
4023     {
4024         elementCount = baseLocation < outputLocations.size()
4025                            ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
4026                            : 0;
4027     }
4028     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4029     {
4030         const unsigned int location = baseLocation + elementIndex;
4031         if (outputLocations[location].used())
4032         {
4033             VariableLocation locationInfo(elementIndex, variableIndex);
4034             if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4035                 reservedLocations.end())
4036             {
4037                 return true;
4038             }
4039         }
4040     }
4041     return false;
4042 }
4043 
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex,sh::ShaderVariable & outputVariable)4044 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
4045                            unsigned int baseLocation,
4046                            unsigned int elementCount,
4047                            const std::vector<VariableLocation> &reservedLocations,
4048                            unsigned int variableIndex,
4049                            sh::ShaderVariable &outputVariable)
4050 {
4051     if (baseLocation + elementCount > outputLocations.size())
4052     {
4053         outputLocations.resize(baseLocation + elementCount);
4054     }
4055     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4056     {
4057         VariableLocation locationInfo(elementIndex, variableIndex);
4058         if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4059             reservedLocations.end())
4060         {
4061             outputVariable.location     = baseLocation;
4062             const unsigned int location = baseLocation + elementIndex;
4063             outputLocations[location]   = locationInfo;
4064         }
4065     }
4066 }
4067 
4068 }  // anonymous namespace
4069 
linkOutputVariables(const Caps & caps,const Extensions & extensions,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount)4070 bool Program::linkOutputVariables(const Caps &caps,
4071                                   const Extensions &extensions,
4072                                   const Version &version,
4073                                   GLuint combinedImageUniformsCount,
4074                                   GLuint combinedShaderStorageBlocksCount)
4075 {
4076     InfoLog &infoLog       = mState.mExecutable->getInfoLog();
4077     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
4078 
4079     ASSERT(mState.mOutputVariableTypes.empty());
4080     ASSERT(mState.mActiveOutputVariables.none());
4081     ASSERT(mState.mDrawBufferTypeMask.none());
4082     ASSERT(!mState.mYUVOutput);
4083 
4084     if (!fragmentShader)
4085     {
4086         // No fragment shader, so nothing to link
4087         return true;
4088     }
4089 
4090     const std::vector<sh::ShaderVariable> &outputVariables =
4091         fragmentShader->getActiveOutputVariables();
4092 
4093     // Gather output variable types
4094     for (const sh::ShaderVariable &outputVariable : outputVariables)
4095     {
4096         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
4097             outputVariable.name != "gl_FragData")
4098         {
4099             continue;
4100         }
4101 
4102         unsigned int baseLocation =
4103             (outputVariable.location == -1 ? 0u
4104                                            : static_cast<unsigned int>(outputVariable.location));
4105 
4106         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4107         // structures, so we may use getBasicTypeElementCount().
4108         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4109         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4110         {
4111             const unsigned int location = baseLocation + elementIndex;
4112             if (location >= mState.mOutputVariableTypes.size())
4113             {
4114                 mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
4115             }
4116             ASSERT(location < mState.mActiveOutputVariables.size());
4117             mState.mActiveOutputVariables.set(location);
4118             mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
4119             ComponentType componentType =
4120                 GLenumToComponentType(mState.mOutputVariableTypes[location]);
4121             SetComponentTypeMask(componentType, location, &mState.mDrawBufferTypeMask);
4122         }
4123 
4124         if (outputVariable.yuv)
4125         {
4126             ASSERT(outputVariables.size() == 1);
4127             mState.mYUVOutput = true;
4128         }
4129     }
4130 
4131     if (version >= ES_3_1)
4132     {
4133         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
4134         // A link error will be generated if the sum of the number of active image uniforms used in
4135         // all shaders, the number of active shader storage blocks, and the number of active
4136         // fragment shader outputs exceeds the implementation-dependent value of
4137         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
4138         if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
4139                 mState.mActiveOutputVariables.count() >
4140             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
4141         {
4142             infoLog
4143                 << "The sum of the number of active image uniforms, active shader storage blocks "
4144                    "and active fragment shader outputs exceeds "
4145                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
4146                 << caps.maxCombinedShaderOutputResources << ")";
4147             return false;
4148         }
4149     }
4150 
4151     // Skip this step for GLES2 shaders.
4152     if (fragmentShader && fragmentShader->getShaderVersion() == 100)
4153         return true;
4154 
4155     mState.mExecutable->mOutputVariables = outputVariables;
4156     mState.mExecutable->mYUVOutput       = mState.mYUVOutput;
4157     // TODO(jmadill): any caps validation here?
4158 
4159     // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
4160     // output array in explicit terms.
4161     //
4162     // Assuming fragData is an output array, you can defend the position that:
4163     // P1) you must support binding "fragData" because it's specified
4164     // P2) you must support querying "fragData[x]" because it's specified
4165     // P3) you must support binding "fragData[0]" because it's a frequently used pattern
4166     //
4167     // Then you can make the leap of faith:
4168     // P4) you must support binding "fragData[x]" because you support "fragData[0]"
4169     // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
4170     //
4171     // The spec brings in the "world of arrays" when it mentions binding the arrays and the
4172     // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
4173     // must infer the only possible interpretation (?). Note again: this need of interpretation
4174     // might be completely off of what GL spec logic is.
4175     //
4176     // The other complexity is that unless you implement this feature, it's hard to understand what
4177     // should happen when the client invokes the feature. You cannot add an additional error as it
4178     // is not specified. One can ignore it, but obviously it creates the discrepancies...
4179 
4180     std::vector<VariableLocation> reservedLocations;
4181 
4182     // Process any output API bindings for arrays that don't alias to the first element.
4183     for (const auto &binding : mFragmentOutputLocations)
4184     {
4185         size_t nameLengthWithoutArrayIndex;
4186         unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
4187         if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
4188         {
4189             continue;
4190         }
4191         for (unsigned int outputVariableIndex = 0;
4192              outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4193              outputVariableIndex++)
4194         {
4195             const sh::ShaderVariable &outputVariable =
4196                 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4197             // Check that the binding corresponds to an output array and its array index fits.
4198             if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
4199                 !angle::BeginsWith(outputVariable.name, binding.first,
4200                                    nameLengthWithoutArrayIndex) ||
4201                 arrayIndex >= outputVariable.getOutermostArraySize())
4202             {
4203                 continue;
4204             }
4205 
4206             // Get the API index that corresponds to this exact binding.
4207             // This index may differ from the index used for the array's base.
4208             auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1
4209                                         ? mState.mExecutable->mSecondaryOutputLocations
4210                                         : mState.mExecutable->mOutputLocations;
4211             unsigned int location = binding.second.location;
4212             VariableLocation locationInfo(arrayIndex, outputVariableIndex);
4213             if (location >= outputLocations.size())
4214             {
4215                 outputLocations.resize(location + 1);
4216             }
4217             if (outputLocations[location].used())
4218             {
4219                 infoLog << "Location of variable " << outputVariable.name
4220                         << " conflicts with another variable.";
4221                 return false;
4222             }
4223             outputLocations[location] = locationInfo;
4224 
4225             // Note the array binding location so that it can be skipped later.
4226             reservedLocations.push_back(locationInfo);
4227         }
4228     }
4229 
4230     // Reserve locations for output variables whose location is fixed in the shader or through the
4231     // API. Otherwise, the remaining unallocated outputs will be processed later.
4232     for (unsigned int outputVariableIndex = 0;
4233          outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4234          outputVariableIndex++)
4235     {
4236         const sh::ShaderVariable &outputVariable =
4237             mState.mExecutable->getOutputVariables()[outputVariableIndex];
4238 
4239         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4240         if (outputVariable.isBuiltIn())
4241             continue;
4242 
4243         int fixedLocation = getOutputLocationForLink(outputVariable);
4244         if (fixedLocation == -1)
4245         {
4246             // Here we're only reserving locations for variables whose location is fixed.
4247             continue;
4248         }
4249         unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
4250 
4251         auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4252                                     ? mState.mExecutable->mSecondaryOutputLocations
4253                                     : mState.mExecutable->mOutputLocations;
4254 
4255         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4256         // structures, so we may use getBasicTypeElementCount().
4257         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4258         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
4259                                    outputVariableIndex))
4260         {
4261             infoLog << "Location of variable " << outputVariable.name
4262                     << " conflicts with another variable.";
4263             return false;
4264         }
4265         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4266                               outputVariableIndex,
4267                               mState.mExecutable->mOutputVariables[outputVariableIndex]);
4268     }
4269 
4270     // Here we assign locations for the output variables that don't yet have them. Note that we're
4271     // not necessarily able to fit the variables optimally, since then we might have to try
4272     // different arrangements of output arrays. Now we just assign the locations in the order that
4273     // we got the output variables. The spec isn't clear on what kind of algorithm is required for
4274     // finding locations for the output variables, so this should be acceptable at least for now.
4275     GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
4276     if (!mState.mExecutable->getSecondaryOutputLocations().empty())
4277     {
4278         // EXT_blend_func_extended: Program outputs will be validated against
4279         // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
4280         maxLocation = extensions.maxDualSourceDrawBuffers;
4281     }
4282 
4283     for (unsigned int outputVariableIndex = 0;
4284          outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4285          outputVariableIndex++)
4286     {
4287         const sh::ShaderVariable &outputVariable =
4288             mState.mExecutable->getOutputVariables()[outputVariableIndex];
4289 
4290         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4291         if (outputVariable.isBuiltIn())
4292             continue;
4293 
4294         int fixedLocation     = getOutputLocationForLink(outputVariable);
4295         auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4296                                     ? mState.mExecutable->mSecondaryOutputLocations
4297                                     : mState.mExecutable->mOutputLocations;
4298         unsigned int baseLocation = 0;
4299         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4300         if (fixedLocation != -1)
4301         {
4302             // Secondary inputs might have caused the max location to drop below what has already
4303             // been explicitly assigned locations. Check for any fixed locations above the max
4304             // that should cause linking to fail.
4305             baseLocation = static_cast<unsigned int>(fixedLocation);
4306         }
4307         else
4308         {
4309             // No fixed location, so try to fit the output in unassigned locations.
4310             // Try baseLocations starting from 0 one at a time and see if the variable fits.
4311             while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
4312                                           reservedLocations, outputVariableIndex))
4313             {
4314                 baseLocation++;
4315             }
4316             AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4317                                   outputVariableIndex,
4318                                   mState.mExecutable->mOutputVariables[outputVariableIndex]);
4319         }
4320 
4321         // Check for any elements assigned above the max location that are actually used.
4322         if (baseLocation + elementCount > maxLocation &&
4323             (baseLocation >= maxLocation ||
4324              FindUsedOutputLocation(outputLocations, maxLocation,
4325                                     baseLocation + elementCount - maxLocation, reservedLocations,
4326                                     outputVariableIndex)))
4327         {
4328             // EXT_blend_func_extended: Linking can fail:
4329             // "if the explicit binding assignments do not leave enough space for the linker to
4330             // automatically assign a location for a varying out array, which requires multiple
4331             // contiguous locations."
4332             infoLog << "Could not fit output variable into available locations: "
4333                     << outputVariable.name;
4334             return false;
4335         }
4336     }
4337 
4338     return true;
4339 }
4340 
setUniformValuesFromBindingQualifiers()4341 void Program::setUniformValuesFromBindingQualifiers()
4342 {
4343     for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
4344     {
4345         const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
4346         if (samplerUniform.binding != -1)
4347         {
4348             UniformLocation location = getUniformLocation(samplerUniform.name);
4349             ASSERT(location.value != -1);
4350             std::vector<GLint> boundTextureUnits;
4351             for (unsigned int elementIndex = 0;
4352                  elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
4353             {
4354                 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
4355             }
4356 
4357             // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
4358             // We know it's safe not to notify the Context because this is only called after link.
4359             setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
4360                           boundTextureUnits.data());
4361         }
4362     }
4363 }
4364 
initInterfaceBlockBindings()4365 void Program::initInterfaceBlockBindings()
4366 {
4367     // Set initial bindings from shader.
4368     for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
4369          blockIndex++)
4370     {
4371         InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
4372         bindUniformBlock({blockIndex}, uniformBlock.binding);
4373     }
4374 }
4375 
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)4376 void Program::updateSamplerUniform(Context *context,
4377                                    const VariableLocation &locationInfo,
4378                                    GLsizei clampedCount,
4379                                    const GLint *v)
4380 {
4381     ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
4382     GLuint samplerIndex            = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
4383     SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
4384     std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
4385 
4386     if (locationInfo.arrayIndex >= boundTextureUnits.size())
4387     {
4388         return;
4389     }
4390     GLsizei safeUniformCount = std::min(
4391         clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
4392 
4393     // Update the sampler uniforms.
4394     for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
4395     {
4396         GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
4397         GLint newTextureUnit = v[arrayIndex];
4398 
4399         if (oldTextureUnit == newTextureUnit)
4400         {
4401             continue;
4402         }
4403 
4404         boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
4405 
4406         // Update the reference counts.
4407         uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
4408         uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit];
4409         ASSERT(oldRefCount > 0);
4410         ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
4411         oldRefCount--;
4412         newRefCount++;
4413 
4414         // Check for binding type change.
4415         TextureType &newSamplerType     = mState.mExecutable->mActiveSamplerTypes[newTextureUnit];
4416         TextureType &oldSamplerType     = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit];
4417         SamplerFormat &newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit];
4418         SamplerFormat &oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit];
4419 
4420         if (newRefCount == 1)
4421         {
4422             newSamplerType   = samplerBinding.textureType;
4423             newSamplerFormat = samplerBinding.format;
4424             mState.mExecutable->mActiveSamplersMask.set(newTextureUnit);
4425             mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] =
4426                 mState.mExecutable->getUniforms()[locationInfo.index].activeShaders();
4427         }
4428         else
4429         {
4430             if (newSamplerType != samplerBinding.textureType)
4431             {
4432                 // Conflict detected. Ensure we reset it properly.
4433                 newSamplerType = TextureType::InvalidEnum;
4434             }
4435             if (newSamplerFormat != samplerBinding.format)
4436             {
4437                 newSamplerFormat = SamplerFormat::InvalidEnum;
4438             }
4439         }
4440 
4441         // Unset previously active sampler.
4442         if (oldRefCount == 0)
4443         {
4444             oldSamplerType   = TextureType::InvalidEnum;
4445             oldSamplerFormat = SamplerFormat::InvalidEnum;
4446             mState.mExecutable->mActiveSamplersMask.reset(oldTextureUnit);
4447         }
4448         else
4449         {
4450             if (oldSamplerType == TextureType::InvalidEnum ||
4451                 oldSamplerFormat == SamplerFormat::InvalidEnum)
4452             {
4453                 // Previous conflict. Check if this new change fixed the conflict.
4454                 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
4455             }
4456         }
4457 
4458         // Update the observing PPO's executable, if any.
4459         // Do this before any of the Context work, since that uses the current ProgramExecutable,
4460         // which will be the PPO's if this Program is bound to it, rather than this Program's.
4461         if (isSeparable())
4462         {
4463             onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
4464         }
4465 
4466         // Notify context.
4467         if (context)
4468         {
4469             context->onSamplerUniformChange(newTextureUnit);
4470             context->onSamplerUniformChange(oldTextureUnit);
4471         }
4472     }
4473 
4474     // Invalidate the validation cache.
4475     getExecutable().resetCachedValidateSamplersResult();
4476     // Inform any PPOs this Program may be bound to.
4477     onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
4478 }
4479 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)4480 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
4481 {
4482     mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
4483                                                        mExecutable->mSamplerBindings);
4484 }
4485 
4486 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)4487 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
4488                                    GLsizei count,
4489                                    int vectorSize,
4490                                    const T *v)
4491 {
4492     if (count == 1)
4493         return 1;
4494 
4495     const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4496 
4497     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4498     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4499     unsigned int remainingElements =
4500         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4501     GLsizei maxElementCount =
4502         static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
4503 
4504     if (count * vectorSize > maxElementCount)
4505     {
4506         return maxElementCount / vectorSize;
4507     }
4508 
4509     return count;
4510 }
4511 
4512 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)4513 GLsizei Program::clampMatrixUniformCount(UniformLocation location,
4514                                          GLsizei count,
4515                                          GLboolean transpose,
4516                                          const T *v)
4517 {
4518     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
4519 
4520     if (!transpose)
4521     {
4522         return clampUniformCount(locationInfo, count, cols * rows, v);
4523     }
4524 
4525     const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4526 
4527     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4528     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4529     unsigned int remainingElements =
4530         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4531     return std::min(count, static_cast<GLsizei>(remainingElements));
4532 }
4533 
4534 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
4535 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
4536 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const4537 void Program::getUniformInternal(const Context *context,
4538                                  DestT *dataOut,
4539                                  UniformLocation location,
4540                                  GLenum nativeType,
4541                                  int components) const
4542 {
4543     switch (nativeType)
4544     {
4545         case GL_BOOL:
4546         {
4547             GLint tempValue[16] = {0};
4548             mProgram->getUniformiv(context, location.value, tempValue);
4549             UniformStateQueryCastLoop<GLboolean>(
4550                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4551             break;
4552         }
4553         case GL_INT:
4554         {
4555             GLint tempValue[16] = {0};
4556             mProgram->getUniformiv(context, location.value, tempValue);
4557             UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4558                                              components);
4559             break;
4560         }
4561         case GL_UNSIGNED_INT:
4562         {
4563             GLuint tempValue[16] = {0};
4564             mProgram->getUniformuiv(context, location.value, tempValue);
4565             UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4566                                               components);
4567             break;
4568         }
4569         case GL_FLOAT:
4570         {
4571             GLfloat tempValue[16] = {0};
4572             mProgram->getUniformfv(context, location.value, tempValue);
4573             UniformStateQueryCastLoop<GLfloat>(
4574                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4575             break;
4576         }
4577         default:
4578             UNREACHABLE();
4579             break;
4580     }
4581 }
4582 
syncState(const Context * context)4583 angle::Result Program::syncState(const Context *context)
4584 {
4585     if (mDirtyBits.any())
4586     {
4587         ASSERT(!mLinkingState);
4588         ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
4589         mDirtyBits.reset();
4590     }
4591 
4592     return angle::Result::Continue;
4593 }
4594 
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const4595 angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
4596 {
4597     BinaryOutputStream stream;
4598 
4599     stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
4600                       ANGLE_COMMIT_HASH_SIZE);
4601 
4602     // nullptr context is supported when computing binary length.
4603     if (context)
4604     {
4605         stream.writeInt(context->getClientVersion().major);
4606         stream.writeInt(context->getClientVersion().minor);
4607     }
4608     else
4609     {
4610         stream.writeInt(2);
4611         stream.writeInt(0);
4612     }
4613 
4614     // Must be before mExecutable->save(), since it uses the value.
4615     stream.writeBool(mState.mSeparable);
4616 
4617     mState.mExecutable->save(mState.mSeparable, &stream);
4618 
4619     const auto &computeLocalSize = mState.getComputeShaderLocalSize();
4620 
4621     stream.writeInt(computeLocalSize[0]);
4622     stream.writeInt(computeLocalSize[1]);
4623     stream.writeInt(computeLocalSize[2]);
4624 
4625     stream.writeInt(mState.mNumViews);
4626     stream.writeBool(mState.mEarlyFramentTestsOptimization);
4627     stream.writeInt(mState.mSpecConstUsageBits.bits());
4628 
4629     stream.writeInt(mState.getUniformLocations().size());
4630     for (const auto &variable : mState.getUniformLocations())
4631     {
4632         stream.writeInt(variable.arrayIndex);
4633         stream.writeIntOrNegOne(variable.index);
4634         stream.writeBool(variable.ignored);
4635     }
4636 
4637     stream.writeInt(mState.getBufferVariables().size());
4638     for (const BufferVariable &bufferVariable : mState.getBufferVariables())
4639     {
4640         WriteBufferVariable(&stream, bufferVariable);
4641     }
4642 
4643     // Warn the app layer if saving a binary with unsupported transform feedback.
4644     if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
4645         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4646     {
4647         WARN() << "Saving program binary with transform feedback, which is not supported on this "
4648                   "driver.";
4649     }
4650 
4651     stream.writeInt(mState.mOutputVariableTypes.size());
4652     for (const auto &outputVariableType : mState.mOutputVariableTypes)
4653     {
4654         stream.writeInt(outputVariableType);
4655     }
4656 
4657     static_assert(
4658         IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4659         "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
4660     stream.writeInt(static_cast<int>(mState.mDrawBufferTypeMask.to_ulong()));
4661     stream.writeInt(static_cast<int>(mState.mActiveOutputVariables.to_ulong()));
4662 
4663     stream.writeBool(mState.isYUVOutput());
4664 
4665     stream.writeInt(mState.getAtomicCounterUniformRange().low());
4666     stream.writeInt(mState.getAtomicCounterUniformRange().high());
4667 
4668     mProgram->save(context, &stream);
4669 
4670     ASSERT(binaryOut);
4671     if (!binaryOut->resize(stream.length()))
4672     {
4673         WARN() << "Failed to allocate enough memory to serialize a program. (" << stream.length()
4674                << " bytes )";
4675         return angle::Result::Incomplete;
4676     }
4677     memcpy(binaryOut->data(), stream.data(), stream.length());
4678     return angle::Result::Continue;
4679 }
4680 
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)4681 angle::Result Program::deserialize(const Context *context,
4682                                    BinaryInputStream &stream,
4683                                    InfoLog &infoLog)
4684 {
4685     unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
4686     stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
4687     if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
4688         0)
4689     {
4690         infoLog << "Invalid program binary version.";
4691         return angle::Result::Stop;
4692     }
4693 
4694     int majorVersion = stream.readInt<int>();
4695     int minorVersion = stream.readInt<int>();
4696     if (majorVersion != context->getClientMajorVersion() ||
4697         minorVersion != context->getClientMinorVersion())
4698     {
4699         infoLog << "Cannot load program binaries across different ES context versions.";
4700         return angle::Result::Stop;
4701     }
4702 
4703     // Must be before mExecutable->load(), since it uses the value.
4704     mState.mSeparable = stream.readBool();
4705 
4706     mState.mExecutable->load(mState.mSeparable, &stream);
4707 
4708     mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
4709     mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
4710     mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
4711 
4712     mState.mNumViews                      = stream.readInt<int>();
4713     mState.mEarlyFramentTestsOptimization = stream.readBool();
4714     mState.mSpecConstUsageBits            = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
4715 
4716     const size_t uniformIndexCount = stream.readInt<size_t>();
4717     ASSERT(mState.mUniformLocations.empty());
4718     for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex)
4719     {
4720         VariableLocation variable;
4721         stream.readInt(&variable.arrayIndex);
4722         stream.readInt(&variable.index);
4723         stream.readBool(&variable.ignored);
4724 
4725         mState.mUniformLocations.push_back(variable);
4726     }
4727 
4728     size_t bufferVariableCount = stream.readInt<size_t>();
4729     ASSERT(mState.mBufferVariables.empty());
4730     for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
4731     {
4732         BufferVariable bufferVariable;
4733         LoadBufferVariable(&stream, &bufferVariable);
4734         mState.mBufferVariables.push_back(bufferVariable);
4735     }
4736 
4737     size_t outputTypeCount = stream.readInt<size_t>();
4738     for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
4739     {
4740         mState.mOutputVariableTypes.push_back(stream.readInt<GLenum>());
4741     }
4742 
4743     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4744                   "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
4745                   "into 32 bits each");
4746     mState.mDrawBufferTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4747     mState.mActiveOutputVariables =
4748         gl::DrawBufferMask(stream.readInt<gl::DrawBufferMask::value_type>());
4749 
4750     stream.readBool(&mState.mYUVOutput);
4751 
4752     unsigned int atomicCounterRangeLow  = stream.readInt<unsigned int>();
4753     unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
4754     mState.mAtomicCounterUniformRange   = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
4755 
4756     static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
4757                   "Too many shader types");
4758 
4759     // Reject programs that use transform feedback varyings if the hardware cannot support them.
4760     if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
4761         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4762     {
4763         infoLog << "Current driver does not support transform feedback in binary programs.";
4764         return angle::Result::Stop;
4765     }
4766 
4767     if (!mState.mAttachedShaders[ShaderType::Compute])
4768     {
4769         mState.mExecutable->updateTransformFeedbackStrides();
4770     }
4771 
4772     postResolveLink(context);
4773     mState.mExecutable->updateCanDrawWith();
4774 
4775     return angle::Result::Continue;
4776 }
4777 
postResolveLink(const gl::Context * context)4778 void Program::postResolveLink(const gl::Context *context)
4779 {
4780     mState.updateActiveSamplers();
4781     mState.mExecutable->mActiveImageShaderBits.fill({});
4782     mState.mExecutable->updateActiveImages(getExecutable());
4783 
4784     setUniformValuesFromBindingQualifiers();
4785 
4786     if (context->getExtensions().multiDraw)
4787     {
4788         mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value;
4789     }
4790 
4791     if (context->getExtensions().baseVertexBaseInstance)
4792     {
4793         mState.mBaseVertexLocation   = getUniformLocation("gl_BaseVertex").value;
4794         mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value;
4795     }
4796 }
4797 
4798 // HasAttachedShaders implementation.
getTransformFeedbackStage() const4799 ShaderType HasAttachedShaders::getTransformFeedbackStage() const
4800 {
4801     if (getAttachedShader(ShaderType::Geometry))
4802     {
4803         return ShaderType::Geometry;
4804     }
4805     if (getAttachedShader(ShaderType::TessEvaluation))
4806     {
4807         return ShaderType::TessEvaluation;
4808     }
4809     return ShaderType::Vertex;
4810 }
4811 }  // namespace gl
4812