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>
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 
1058 // ProgramAliasedBindings implementation.
ProgramAliasedBindings()1059 ProgramAliasedBindings::ProgramAliasedBindings() {}
1060 
~ProgramAliasedBindings()1061 ProgramAliasedBindings::~ProgramAliasedBindings() {}
1062 
bindLocation(GLuint index,const std::string & name)1063 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
1064 {
1065     mBindings[name] = ProgramBinding(index);
1066 
1067     // EXT_blend_func_extended spec: "If it specifies the base name of an array,
1068     // it identifies the resources associated with the first element of the array."
1069     //
1070     // Normalize array bindings so that "name" and "name[0]" map to the same entry.
1071     // If this binding is of the form "name[0]", then mark the "name" binding as
1072     // aliased but do not update it yet in case "name" is not actually an array.
1073     size_t nameLengthWithoutArrayIndex;
1074     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1075     if (arrayIndex == 0)
1076     {
1077         std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1078         auto iter            = mBindings.find(baseName);
1079         if (iter != mBindings.end())
1080         {
1081             iter->second.aliased = true;
1082         }
1083     }
1084 }
1085 
getBindingByName(const std::string & name) const1086 int ProgramAliasedBindings::getBindingByName(const std::string &name) const
1087 {
1088     auto iter = mBindings.find(name);
1089     return (iter != mBindings.end()) ? iter->second.location : -1;
1090 }
1091 
getBindingByLocation(GLuint location) const1092 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
1093 {
1094     for (const auto &iter : mBindings)
1095     {
1096         if (iter.second.location == location)
1097         {
1098             return iter.second.location;
1099         }
1100     }
1101     return -1;
1102 }
1103 
getBinding(const sh::ShaderVariable & variable) const1104 int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const
1105 {
1106     const std::string &name = variable.name;
1107 
1108     // Check with the normalized array name if applicable.
1109     if (variable.isArray())
1110     {
1111         size_t nameLengthWithoutArrayIndex;
1112         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1113         if (arrayIndex == 0)
1114         {
1115             std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1116             auto iter            = mBindings.find(baseName);
1117             // If "name" exists and is not aliased, that means it was modified more
1118             // recently than its "name[0]" form and should be used instead of that.
1119             if (iter != mBindings.end() && !iter->second.aliased)
1120             {
1121                 return iter->second.location;
1122             }
1123         }
1124         else if (arrayIndex == GL_INVALID_INDEX)
1125         {
1126             auto iter = mBindings.find(variable.name);
1127             // If "name" exists and is not aliased, that means it was modified more
1128             // recently than its "name[0]" form and should be used instead of that.
1129             if (iter != mBindings.end() && !iter->second.aliased)
1130             {
1131                 return iter->second.location;
1132             }
1133             // The base name was aliased, so use the name with the array notation.
1134             return getBindingByName(name + "[0]");
1135         }
1136     }
1137 
1138     return getBindingByName(name);
1139 }
1140 
begin() const1141 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
1142 {
1143     return mBindings.begin();
1144 }
1145 
end() const1146 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
1147 {
1148     return mBindings.end();
1149 }
1150 
1151 // ImageBinding implementation.
ImageBinding(size_t count,TextureType textureTypeIn)1152 ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn)
1153     : textureType(textureTypeIn), boundImageUnits(count, 0)
1154 {}
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)1155 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
1156     : textureType(textureTypeIn)
1157 {
1158     for (size_t index = 0; index < count; ++index)
1159     {
1160         boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
1161     }
1162 }
1163 
1164 ImageBinding::ImageBinding(const ImageBinding &other) = default;
1165 
1166 ImageBinding::~ImageBinding() = default;
1167 
1168 // ProgramState implementation.
ProgramState()1169 ProgramState::ProgramState()
1170     : mLabel(),
1171       mAttachedShaders{},
1172       mLocationsUsedForXfbExtension(0),
1173       mAtomicCounterUniformRange(0, 0),
1174       mYUVOutput(false),
1175       mBinaryRetrieveableHint(false),
1176       mSeparable(false),
1177       mNumViews(-1),
1178       mDrawIDLocation(-1),
1179       mBaseVertexLocation(-1),
1180       mBaseInstanceLocation(-1),
1181       mCachedBaseVertex(0),
1182       mCachedBaseInstance(0),
1183       mExecutable(new ProgramExecutable())
1184 {
1185     mComputeShaderLocalSize.fill(1);
1186 }
1187 
~ProgramState()1188 ProgramState::~ProgramState()
1189 {
1190     ASSERT(!hasAttachedShader());
1191 }
1192 
getLabel()1193 const std::string &ProgramState::getLabel()
1194 {
1195     return mLabel;
1196 }
1197 
getAttachedShader(ShaderType shaderType) const1198 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
1199 {
1200     ASSERT(shaderType != ShaderType::InvalidEnum);
1201     return mAttachedShaders[shaderType];
1202 }
1203 
getUniformIndexFromName(const std::string & name) const1204 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
1205 {
1206     return GetResourceIndexFromName(mExecutable->mUniforms, name);
1207 }
1208 
getBufferVariableIndexFromName(const std::string & name) const1209 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
1210 {
1211     return GetResourceIndexFromName(mBufferVariables, name);
1212 }
1213 
getUniformIndexFromLocation(UniformLocation location) const1214 GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const
1215 {
1216     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
1217     return mUniformLocations[location.value].index;
1218 }
1219 
getSamplerIndex(UniformLocation location) const1220 Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
1221 {
1222     GLuint index = getUniformIndexFromLocation(location);
1223     if (!isSamplerUniformIndex(index))
1224     {
1225         return Optional<GLuint>::Invalid();
1226     }
1227 
1228     return getSamplerIndexFromUniformIndex(index);
1229 }
1230 
isSamplerUniformIndex(GLuint index) const1231 bool ProgramState::isSamplerUniformIndex(GLuint index) const
1232 {
1233     return mExecutable->mSamplerUniformRange.contains(index);
1234 }
1235 
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const1236 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
1237 {
1238     ASSERT(isSamplerUniformIndex(uniformIndex));
1239     return uniformIndex - mExecutable->mSamplerUniformRange.low();
1240 }
1241 
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const1242 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
1243 {
1244     ASSERT(samplerIndex < mExecutable->mSamplerUniformRange.length());
1245     return samplerIndex + mExecutable->mSamplerUniformRange.low();
1246 }
1247 
isImageUniformIndex(GLuint index) const1248 bool ProgramState::isImageUniformIndex(GLuint index) const
1249 {
1250     return mExecutable->mImageUniformRange.contains(index);
1251 }
1252 
getImageIndexFromUniformIndex(GLuint uniformIndex) const1253 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
1254 {
1255     ASSERT(isImageUniformIndex(uniformIndex));
1256     return uniformIndex - mExecutable->mImageUniformRange.low();
1257 }
1258 
getAttributeLocation(const std::string & name) const1259 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1260 {
1261     for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
1262     {
1263         if (attribute.name == name)
1264         {
1265             return attribute.location;
1266         }
1267     }
1268 
1269     return static_cast<GLuint>(-1);
1270 }
1271 
hasAttachedShader() const1272 bool ProgramState::hasAttachedShader() const
1273 {
1274     for (const Shader *shader : mAttachedShaders)
1275     {
1276         if (shader)
1277         {
1278             return true;
1279         }
1280     }
1281     return false;
1282 }
1283 
getFirstAttachedShaderStageType() const1284 ShaderType ProgramState::getFirstAttachedShaderStageType() const
1285 {
1286     const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1287     if (linkedStages.none())
1288     {
1289         return ShaderType::InvalidEnum;
1290     }
1291 
1292     return linkedStages.first();
1293 }
1294 
getLastAttachedShaderStageType() const1295 ShaderType ProgramState::getLastAttachedShaderStageType() const
1296 {
1297     const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1298     if (linkedStages.none())
1299     {
1300         return ShaderType::InvalidEnum;
1301     }
1302 
1303     return linkedStages.last();
1304 }
1305 
getAttachedTransformFeedbackStage() const1306 ShaderType ProgramState::getAttachedTransformFeedbackStage() const
1307 {
1308     if (mAttachedShaders[ShaderType::Geometry])
1309     {
1310         return ShaderType::Geometry;
1311     }
1312     if (mAttachedShaders[ShaderType::TessEvaluation])
1313     {
1314         return ShaderType::TessEvaluation;
1315     }
1316     return ShaderType::Vertex;
1317 }
1318 
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)1319 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
1320     : mSerial(factory->generateSerial()),
1321       mProgram(factory->createProgram(mState)),
1322       mValidated(false),
1323       mLinked(false),
1324       mDeleteStatus(false),
1325       mRefCount(0),
1326       mResourceManager(manager),
1327       mHandle(handle)
1328 {
1329     ASSERT(mProgram);
1330 
1331     unlink();
1332 }
1333 
~Program()1334 Program::~Program()
1335 {
1336     ASSERT(!mProgram);
1337 }
1338 
onDestroy(const Context * context)1339 void Program::onDestroy(const Context *context)
1340 {
1341     resolveLink(context);
1342     for (ShaderType shaderType : AllShaderTypes())
1343     {
1344         if (mState.mAttachedShaders[shaderType])
1345         {
1346             mState.mAttachedShaders[shaderType]->release(context);
1347             mState.mAttachedShaders[shaderType] = nullptr;
1348         }
1349     }
1350 
1351     mProgram->destroy(context);
1352 
1353     ASSERT(!mState.hasAttachedShader());
1354     SafeDelete(mProgram);
1355 
1356     delete this;
1357 }
id() const1358 ShaderProgramID Program::id() const
1359 {
1360     ASSERT(!mLinkingState);
1361     return mHandle;
1362 }
1363 
setLabel(const Context * context,const std::string & label)1364 void Program::setLabel(const Context *context, const std::string &label)
1365 {
1366     ASSERT(!mLinkingState);
1367     mState.mLabel = label;
1368 }
1369 
getLabel() const1370 const std::string &Program::getLabel() const
1371 {
1372     ASSERT(!mLinkingState);
1373     return mState.mLabel;
1374 }
1375 
attachShader(Shader * shader)1376 void Program::attachShader(Shader *shader)
1377 {
1378     ShaderType shaderType = shader->getType();
1379     ASSERT(shaderType != ShaderType::InvalidEnum);
1380 
1381     mState.mAttachedShaders[shaderType] = shader;
1382     mState.mAttachedShaders[shaderType]->addRef();
1383 }
1384 
detachShader(const Context * context,Shader * shader)1385 void Program::detachShader(const Context *context, Shader *shader)
1386 {
1387     resolveLink(context);
1388     ShaderType shaderType = shader->getType();
1389     ASSERT(shaderType != ShaderType::InvalidEnum);
1390 
1391     ASSERT(mState.mAttachedShaders[shaderType] == shader);
1392     shader->release(context);
1393     mState.mAttachedShaders[shaderType] = nullptr;
1394 }
1395 
getAttachedShadersCount() const1396 int Program::getAttachedShadersCount() const
1397 {
1398     ASSERT(!mLinkingState);
1399     int numAttachedShaders = 0;
1400     for (const Shader *shader : mState.mAttachedShaders)
1401     {
1402         if (shader)
1403         {
1404             ++numAttachedShaders;
1405         }
1406     }
1407 
1408     return numAttachedShaders;
1409 }
1410 
getAttachedShader(ShaderType shaderType) const1411 Shader *Program::getAttachedShader(ShaderType shaderType) const
1412 {
1413     ASSERT(!mLinkingState);
1414     return mState.getAttachedShader(shaderType);
1415 }
1416 
bindAttributeLocation(GLuint index,const char * name)1417 void Program::bindAttributeLocation(GLuint index, const char *name)
1418 {
1419     ASSERT(!mLinkingState);
1420     mAttributeBindings.bindLocation(index, name);
1421 }
1422 
bindUniformLocation(UniformLocation location,const char * name)1423 void Program::bindUniformLocation(UniformLocation location, const char *name)
1424 {
1425     ASSERT(!mLinkingState);
1426     mState.mUniformLocationBindings.bindLocation(location.value, name);
1427 }
1428 
bindFragmentOutputLocation(GLuint index,const char * name)1429 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1430 {
1431     mFragmentOutputLocations.bindLocation(index, name);
1432 }
1433 
bindFragmentOutputIndex(GLuint index,const char * name)1434 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1435 {
1436     mFragmentOutputIndexes.bindLocation(index, name);
1437 }
1438 
link(const Context * context)1439 angle::Result Program::link(const Context *context)
1440 {
1441     angle::Result result = linkImpl(context);
1442 
1443     // Avoid having two ProgramExecutables if the link failed and the Program had successfully
1444     // linked previously.
1445     if (mLinkingState && mLinkingState->linkedExecutable)
1446     {
1447         mState.mExecutable = mLinkingState->linkedExecutable;
1448     }
1449 
1450     return result;
1451 }
1452 
1453 // The attached shaders are checked for linking errors by matching up their variables.
1454 // Uniform, input and output variables get collected.
1455 // The code gets compiled into binaries.
linkImpl(const Context * context)1456 angle::Result Program::linkImpl(const Context *context)
1457 {
1458     ASSERT(!mLinkingState);
1459     // Don't make any local variables pointing to anything within the ProgramExecutable, since
1460     // unlink() could make a new ProgramExecutable making any references/pointers invalid.
1461     auto *platform   = ANGLEPlatformCurrent();
1462     double startTime = platform->currentTime(platform);
1463 
1464     // Unlink the program, but do not clear the validation-related caching yet, since we can still
1465     // use the previously linked program if linking the shaders fails.
1466     mLinked = false;
1467 
1468     mState.mExecutable->getInfoLog().reset();
1469 
1470     // Validate we have properly attached shaders before checking the cache.
1471     if (!linkValidateShaders(mState.mExecutable->getInfoLog()))
1472     {
1473         return angle::Result::Continue;
1474     }
1475 
1476     egl::BlobCache::Key programHash = {0};
1477     MemoryProgramCache *cache       = context->getMemoryProgramCache();
1478 
1479     // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1480     if (cache && !isSeparable())
1481     {
1482         std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1483         angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1484         ANGLE_TRY(cacheResult);
1485 
1486         // Check explicitly for Continue, Incomplete means a cache miss
1487         if (cacheResult == angle::Result::Continue)
1488         {
1489             // Succeeded in loading the binaries in the front-end, back end may still be loading
1490             // asynchronously
1491             double delta = platform->currentTime(platform) - startTime;
1492             int us       = static_cast<int>(delta * 1000000.0);
1493             ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1494             return angle::Result::Continue;
1495         }
1496     }
1497 
1498     // Cache load failed, fall through to normal linking.
1499     unlink();
1500     InfoLog &infoLog = mState.mExecutable->getInfoLog();
1501 
1502     // Re-link shaders after the unlink call.
1503     bool result = linkValidateShaders(infoLog);
1504     ASSERT(result);
1505 
1506     std::unique_ptr<LinkingState> linkingState(new LinkingState());
1507     ProgramMergedVaryings mergedVaryings;
1508     ProgramLinkedResources &resources = linkingState->resources;
1509 
1510     if (mState.mAttachedShaders[ShaderType::Compute])
1511     {
1512         resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1513                        &mState.mExecutable->mComputeShaderStorageBlocks, &mState.mBufferVariables,
1514                        &mState.mExecutable->mAtomicCounterBuffers);
1515 
1516         GLuint combinedImageUniforms = 0u;
1517         if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1518                           mState.mUniformLocationBindings, &combinedImageUniforms,
1519                           &resources.unusedUniforms))
1520         {
1521             return angle::Result::Continue;
1522         }
1523 
1524         GLuint combinedShaderStorageBlocks = 0u;
1525         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1526                                  context->getExtensions().webglCompatibility, infoLog,
1527                                  &combinedShaderStorageBlocks))
1528         {
1529             return angle::Result::Continue;
1530         }
1531 
1532         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1533         // A link error will be generated if the sum of the number of active image uniforms used in
1534         // all shaders, the number of active shader storage blocks, and the number of active
1535         // fragment shader outputs exceeds the implementation-dependent value of
1536         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1537         if (combinedImageUniforms + combinedShaderStorageBlocks >
1538             static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
1539         {
1540             infoLog
1541                 << "The sum of the number of active image uniforms, active shader storage blocks "
1542                    "and active fragment shader outputs exceeds "
1543                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1544                 << context->getCaps().maxCombinedShaderOutputResources << ")";
1545             return angle::Result::Continue;
1546         }
1547 
1548         InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1549         InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1550     }
1551     else
1552     {
1553         resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1554                        &mState.mExecutable->mGraphicsShaderStorageBlocks, &mState.mBufferVariables,
1555                        &mState.mExecutable->mAtomicCounterBuffers);
1556 
1557         if (!linkAttributes(context, infoLog))
1558         {
1559             return angle::Result::Continue;
1560         }
1561 
1562         if (!linkVaryings(infoLog))
1563         {
1564             return angle::Result::Continue;
1565         }
1566 
1567         GLuint combinedImageUniforms = 0u;
1568         if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1569                           mState.mUniformLocationBindings, &combinedImageUniforms,
1570                           &resources.unusedUniforms))
1571         {
1572             return angle::Result::Continue;
1573         }
1574 
1575         GLuint combinedShaderStorageBlocks = 0u;
1576         if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1577                                  context->getExtensions().webglCompatibility, infoLog,
1578                                  &combinedShaderStorageBlocks))
1579         {
1580             return angle::Result::Continue;
1581         }
1582 
1583         if (!LinkValidateProgramGlobalNames(infoLog, *this))
1584         {
1585             return angle::Result::Continue;
1586         }
1587 
1588         if (!linkOutputVariables(context->getCaps(), context->getExtensions(),
1589                                  context->getClientVersion(), combinedImageUniforms,
1590                                  combinedShaderStorageBlocks))
1591         {
1592             return angle::Result::Continue;
1593         }
1594 
1595         gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1596         if (vertexShader)
1597         {
1598             mState.mNumViews = vertexShader->getNumViews();
1599             mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
1600         }
1601 
1602         gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1603         if (fragmentShader)
1604         {
1605             mState.mEarlyFramentTestsOptimization =
1606                 fragmentShader->hasEarlyFragmentTestsOptimization();
1607             mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
1608         }
1609 
1610         InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1611         InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1612 
1613         mergedVaryings = GetMergedVaryingsFromShaders(*this, getExecutable());
1614         if (!mState.mExecutable->linkMergedVaryings(context, *this, mergedVaryings,
1615                                                     mState.mTransformFeedbackVaryingNames,
1616                                                     isSeparable(), &resources.varyingPacking))
1617         {
1618             return angle::Result::Continue;
1619         }
1620     }
1621 
1622     updateLinkedShaderStages();
1623 
1624     mLinkingState                    = std::move(linkingState);
1625     mLinkingState->linkingFromBinary = false;
1626     mLinkingState->programHash       = programHash;
1627     mLinkingState->linkEvent         = mProgram->link(context, resources, infoLog, mergedVaryings);
1628 
1629     // Must be after mProgram->link() to avoid misleading the linker about output variables.
1630     mState.updateProgramInterfaceInputs();
1631     mState.updateProgramInterfaceOutputs();
1632 
1633     // Linking has succeeded, so we need to save some information that may get overwritten by a
1634     // later linkProgram() that could fail.
1635     if (mState.mSeparable)
1636     {
1637         mState.mExecutable->saveLinkedStateInfo(mState);
1638         mLinkingState->linkedExecutable = mState.mExecutable;
1639     }
1640 
1641     return angle::Result::Continue;
1642 }
1643 
isLinking() const1644 bool Program::isLinking() const
1645 {
1646     return (mLinkingState.get() && mLinkingState->linkEvent &&
1647             mLinkingState->linkEvent->isLinking());
1648 }
1649 
resolveLinkImpl(const Context * context)1650 void Program::resolveLinkImpl(const Context *context)
1651 {
1652     ASSERT(mLinkingState.get());
1653 
1654     angle::Result result = mLinkingState->linkEvent->wait(context);
1655 
1656     mLinked                                    = result == angle::Result::Continue;
1657     std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1658     if (!mLinked)
1659     {
1660         return;
1661     }
1662 
1663     if (linkingState->linkingFromBinary)
1664     {
1665         // All internal Program state is already loaded from the binary.
1666         return;
1667     }
1668 
1669     initInterfaceBlockBindings();
1670 
1671     // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1672     // Only successfully linked program can replace the executables.
1673     ASSERT(mLinked);
1674 
1675     // Mark implementation-specific unreferenced uniforms as ignored.
1676     std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1677     mProgram->markUnusedUniformLocations(&mState.mUniformLocations,
1678                                          &mState.mExecutable->mSamplerBindings, imageBindings);
1679 
1680     // Must be called after markUnusedUniformLocations.
1681     postResolveLink(context);
1682 
1683     // Save to the program cache.
1684     std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1685     MemoryProgramCache *cache = context->getMemoryProgramCache();
1686     // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1687     if (cache && !isSeparable() &&
1688         (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
1689          !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
1690     {
1691         if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
1692         {
1693             // Don't fail linking if putting the program binary into the cache fails, the program is
1694             // still usable.
1695             WARN() << "Failed to save linked program to memory program cache.";
1696         }
1697     }
1698 }
1699 
updateLinkedShaderStages()1700 void Program::updateLinkedShaderStages()
1701 {
1702     mState.mExecutable->resetLinkedShaderStages();
1703 
1704     for (const Shader *shader : mState.mAttachedShaders)
1705     {
1706         if (shader)
1707         {
1708             mState.mExecutable->setLinkedShaderStages(shader->getType());
1709         }
1710     }
1711 
1712     if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
1713     {
1714         mState.mExecutable->setIsCompute(true);
1715     }
1716     else
1717     {
1718         mState.mExecutable->setIsCompute(false);
1719     }
1720 }
1721 
updateActiveSamplers()1722 void ProgramState::updateActiveSamplers()
1723 {
1724     mExecutable->mActiveSamplerRefCounts.fill(0);
1725     mExecutable->updateActiveSamplers(*this);
1726 }
1727 
updateProgramInterfaceInputs()1728 void ProgramState::updateProgramInterfaceInputs()
1729 {
1730     const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType();
1731 
1732     if (firstAttachedShaderType == ShaderType::Vertex)
1733     {
1734         // Vertex attributes are already what we need, so nothing to do
1735         return;
1736     }
1737 
1738     Shader *shader = getAttachedShader(firstAttachedShaderType);
1739     ASSERT(shader);
1740 
1741     // Copy over each input varying, since the Shader could go away
1742     if (shader->getType() == ShaderType::Compute)
1743     {
1744         for (const sh::ShaderVariable &attribute : shader->getAllAttributes())
1745         {
1746             // Compute Shaders have the following built-in input variables.
1747             //
1748             // in uvec3 gl_NumWorkGroups;
1749             // in uvec3 gl_WorkGroupID;
1750             // in uvec3 gl_LocalInvocationID;
1751             // in uvec3 gl_GlobalInvocationID;
1752             // in uint  gl_LocalInvocationIndex;
1753             // They are all vecs or uints, so no special handling is required.
1754             mExecutable->mProgramInputs.emplace_back(attribute);
1755         }
1756     }
1757     else
1758     {
1759         for (const sh::ShaderVariable &varying : shader->getInputVaryings())
1760         {
1761             UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1762         }
1763     }
1764 }
1765 
updateProgramInterfaceOutputs()1766 void ProgramState::updateProgramInterfaceOutputs()
1767 {
1768     const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType();
1769 
1770     if (lastAttachedShaderType == ShaderType::Fragment)
1771     {
1772         // Fragment outputs are already what we need, so nothing to do
1773         return;
1774     }
1775     if (lastAttachedShaderType == ShaderType::Compute)
1776     {
1777         // If the program only contains a Compute Shader, then there are no user-defined outputs.
1778         return;
1779     }
1780 
1781     Shader *shader = getAttachedShader(lastAttachedShaderType);
1782     ASSERT(shader);
1783 
1784     // Copy over each output varying, since the Shader could go away
1785     for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
1786     {
1787         UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1788     }
1789 }
1790 
1791 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1792 void Program::unlink()
1793 {
1794     if (mLinkingState && mLinkingState->linkedExecutable)
1795     {
1796         // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of
1797         // the last successfully linked ProgramExecutable, so we don't lose any state information.
1798         mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable));
1799     }
1800     mState.mExecutable->reset();
1801 
1802     mState.mUniformLocations.clear();
1803     mState.mBufferVariables.clear();
1804     mState.mOutputVariableTypes.clear();
1805     mState.mDrawBufferTypeMask.reset();
1806     mState.mYUVOutput = false;
1807     mState.mActiveOutputVariables.reset();
1808     mState.mComputeShaderLocalSize.fill(1);
1809     mState.mNumViews                      = -1;
1810     mState.mDrawIDLocation                = -1;
1811     mState.mBaseVertexLocation            = -1;
1812     mState.mBaseInstanceLocation          = -1;
1813     mState.mCachedBaseVertex              = 0;
1814     mState.mCachedBaseInstance            = 0;
1815     mState.mEarlyFramentTestsOptimization = false;
1816     mState.mDrawIDLocation                = -1;
1817     mState.mBaseVertexLocation            = -1;
1818     mState.mBaseInstanceLocation          = -1;
1819     mState.mCachedBaseVertex              = 0;
1820     mState.mCachedBaseInstance            = 0;
1821     mState.mEarlyFramentTestsOptimization = false;
1822     mState.mSpecConstUsageBits.reset();
1823 
1824     mValidated = false;
1825 
1826     mLinked = false;
1827 }
1828 
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1829 angle::Result Program::loadBinary(const Context *context,
1830                                   GLenum binaryFormat,
1831                                   const void *binary,
1832                                   GLsizei length)
1833 {
1834     ASSERT(!mLinkingState);
1835     unlink();
1836     InfoLog &infoLog = mState.mExecutable->getInfoLog();
1837 
1838 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1839     return angle::Result::Continue;
1840 #else
1841     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1842     if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1843     {
1844         infoLog << "Invalid program binary format.";
1845         return angle::Result::Continue;
1846     }
1847 
1848     BinaryInputStream stream(binary, length);
1849     ANGLE_TRY(deserialize(context, stream, infoLog));
1850 
1851     // Currently we require the full shader text to compute the program hash.
1852     // We could also store the binary in the internal program cache.
1853 
1854     for (size_t uniformBlockIndex = 0;
1855          uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
1856     {
1857         mDirtyBits.set(uniformBlockIndex);
1858     }
1859 
1860     // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple
1861     // implementations. In some implementations, a background thread is used to compile the
1862     // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with
1863     // the operation.
1864 
1865     // We do not want to call LinkEvent::wait because that will cause the background thread
1866     // to finish its task before returning, thus defeating the purpose of background compilation.
1867     // We need to defer waiting on background compilation until the very last minute when we
1868     // absolutely need the results, such as when the developer binds the program or queries
1869     // for the completion status.
1870 
1871     // If load returns nullptr, we know for sure that the binary is not compatible with the backend.
1872     // The loaded binary could have been read from the on-disk shader cache and be corrupted or
1873     // serialized with different revision and subsystem id than the currently loaded backend.
1874     // Returning 'Incomplete' to the caller results in link happening using the original shader
1875     // sources.
1876     angle::Result result;
1877     std::unique_ptr<LinkingState> linkingState;
1878     std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog);
1879     if (linkEvent)
1880     {
1881         linkingState                    = std::make_unique<LinkingState>();
1882         linkingState->linkingFromBinary = true;
1883         linkingState->linkEvent         = std::move(linkEvent);
1884         result                          = angle::Result::Continue;
1885     }
1886     else
1887     {
1888         result = angle::Result::Incomplete;
1889     }
1890     mLinkingState = std::move(linkingState);
1891 
1892     return result;
1893 #endif  // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1894 }
1895 
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1896 angle::Result Program::saveBinary(Context *context,
1897                                   GLenum *binaryFormat,
1898                                   void *binary,
1899                                   GLsizei bufSize,
1900                                   GLsizei *length) const
1901 {
1902     ASSERT(!mLinkingState);
1903     if (binaryFormat)
1904     {
1905         *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1906     }
1907 
1908     angle::MemoryBuffer memoryBuf;
1909     ANGLE_TRY(serialize(context, &memoryBuf));
1910 
1911     GLsizei streamLength       = static_cast<GLsizei>(memoryBuf.size());
1912     const uint8_t *streamState = memoryBuf.data();
1913 
1914     if (streamLength > bufSize)
1915     {
1916         if (length)
1917         {
1918             *length = 0;
1919         }
1920 
1921         // TODO: This should be moved to the validation layer but computing the size of the binary
1922         // before saving it causes the save to happen twice.  It may be possible to write the binary
1923         // to a separate buffer, validate sizes and then copy it.
1924         ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1925     }
1926 
1927     if (binary)
1928     {
1929         char *ptr = reinterpret_cast<char *>(binary);
1930 
1931         memcpy(ptr, streamState, streamLength);
1932         ptr += streamLength;
1933 
1934         ASSERT(ptr - streamLength == binary);
1935     }
1936 
1937     if (length)
1938     {
1939         *length = streamLength;
1940     }
1941 
1942     return angle::Result::Continue;
1943 }
1944 
getBinaryLength(Context * context) const1945 GLint Program::getBinaryLength(Context *context) const
1946 {
1947     ASSERT(!mLinkingState);
1948     if (!mLinked)
1949     {
1950         return 0;
1951     }
1952 
1953     GLint length;
1954     angle::Result result =
1955         saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1956     if (result != angle::Result::Continue)
1957     {
1958         return 0;
1959     }
1960 
1961     return length;
1962 }
1963 
setBinaryRetrievableHint(bool retrievable)1964 void Program::setBinaryRetrievableHint(bool retrievable)
1965 {
1966     ASSERT(!mLinkingState);
1967     // TODO(jmadill) : replace with dirty bits
1968     mProgram->setBinaryRetrievableHint(retrievable);
1969     mState.mBinaryRetrieveableHint = retrievable;
1970 }
1971 
getBinaryRetrievableHint() const1972 bool Program::getBinaryRetrievableHint() const
1973 {
1974     ASSERT(!mLinkingState);
1975     return mState.mBinaryRetrieveableHint;
1976 }
1977 
setSeparable(bool separable)1978 void Program::setSeparable(bool separable)
1979 {
1980     ASSERT(!mLinkingState);
1981     // TODO(yunchao) : replace with dirty bits
1982     if (mState.mSeparable != separable)
1983     {
1984         mProgram->setSeparable(separable);
1985         mState.mSeparable = separable;
1986     }
1987 }
1988 
isSeparable() const1989 bool Program::isSeparable() const
1990 {
1991     ASSERT(!mLinkingState);
1992     return mState.mSeparable;
1993 }
1994 
deleteSelf(const Context * context)1995 void Program::deleteSelf(const Context *context)
1996 {
1997     ASSERT(mRefCount == 0 && mDeleteStatus);
1998     mResourceManager->deleteProgram(context, mHandle);
1999 }
2000 
getRefCount() const2001 unsigned int Program::getRefCount() const
2002 {
2003     return mRefCount;
2004 }
2005 
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const2006 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
2007 {
2008     ASSERT(!mLinkingState);
2009     int total = 0;
2010 
2011     for (const Shader *shader : mState.mAttachedShaders)
2012     {
2013         if (shader && (total < maxCount))
2014         {
2015             shaders[total] = shader->getHandle();
2016             ++total;
2017         }
2018     }
2019 
2020     if (count)
2021     {
2022         *count = total;
2023     }
2024 }
2025 
getAttributeLocation(const std::string & name) const2026 GLuint Program::getAttributeLocation(const std::string &name) const
2027 {
2028     ASSERT(!mLinkingState);
2029     return mState.getAttributeLocation(name);
2030 }
2031 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2032 void Program::getActiveAttribute(GLuint index,
2033                                  GLsizei bufsize,
2034                                  GLsizei *length,
2035                                  GLint *size,
2036                                  GLenum *type,
2037                                  GLchar *name) const
2038 {
2039     ASSERT(!mLinkingState);
2040     if (!mLinked)
2041     {
2042         if (bufsize > 0)
2043         {
2044             name[0] = '\0';
2045         }
2046 
2047         if (length)
2048         {
2049             *length = 0;
2050         }
2051 
2052         *type = GL_NONE;
2053         *size = 1;
2054         return;
2055     }
2056 
2057     ASSERT(index < mState.mExecutable->getProgramInputs().size());
2058     const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
2059 
2060     if (bufsize > 0)
2061     {
2062         CopyStringToBuffer(name, attrib.name, bufsize, length);
2063     }
2064 
2065     // Always a single 'type' instance
2066     *size = 1;
2067     *type = attrib.type;
2068 }
2069 
getActiveAttributeCount() const2070 GLint Program::getActiveAttributeCount() const
2071 {
2072     ASSERT(!mLinkingState);
2073     if (!mLinked)
2074     {
2075         return 0;
2076     }
2077 
2078     return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
2079 }
2080 
getActiveAttributeMaxLength() const2081 GLint Program::getActiveAttributeMaxLength() const
2082 {
2083     ASSERT(!mLinkingState);
2084     if (!mLinked)
2085     {
2086         return 0;
2087     }
2088 
2089     size_t maxLength = 0;
2090 
2091     for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
2092     {
2093         maxLength = std::max(attrib.name.length() + 1, maxLength);
2094     }
2095 
2096     return static_cast<GLint>(maxLength);
2097 }
2098 
getAttributes() const2099 const std::vector<sh::ShaderVariable> &Program::getAttributes() const
2100 {
2101     ASSERT(!mLinkingState);
2102     return mState.mExecutable->getProgramInputs();
2103 }
2104 
getComputeShaderLocalSize() const2105 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
2106 {
2107     ASSERT(!mLinkingState);
2108     return mState.mComputeShaderLocalSize;
2109 }
2110 
getGeometryShaderInputPrimitiveType() const2111 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
2112 {
2113     ASSERT(!mLinkingState && mState.mExecutable);
2114     return mState.mExecutable->getGeometryShaderInputPrimitiveType();
2115 }
getGeometryShaderOutputPrimitiveType() const2116 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
2117 {
2118     ASSERT(!mLinkingState && mState.mExecutable);
2119     return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
2120 }
getGeometryShaderInvocations() const2121 GLint Program::getGeometryShaderInvocations() const
2122 {
2123     ASSERT(!mLinkingState && mState.mExecutable);
2124     return mState.mExecutable->getGeometryShaderInvocations();
2125 }
getGeometryShaderMaxVertices() const2126 GLint Program::getGeometryShaderMaxVertices() const
2127 {
2128     ASSERT(!mLinkingState && mState.mExecutable);
2129     return mState.mExecutable->getGeometryShaderMaxVertices();
2130 }
2131 
getTessControlShaderVertices() const2132 GLint Program::getTessControlShaderVertices() const
2133 {
2134     ASSERT(!mLinkingState && mState.mExecutable);
2135     return mState.mExecutable->mTessControlShaderVertices;
2136 }
2137 
getTessGenMode() const2138 GLenum Program::getTessGenMode() const
2139 {
2140     ASSERT(!mLinkingState && mState.mExecutable);
2141     return mState.mExecutable->mTessGenMode;
2142 }
2143 
getTessGenPointMode() const2144 GLenum Program::getTessGenPointMode() const
2145 {
2146     ASSERT(!mLinkingState && mState.mExecutable);
2147     return mState.mExecutable->mTessGenPointMode;
2148 }
2149 
getTessGenSpacing() const2150 GLenum Program::getTessGenSpacing() const
2151 {
2152     ASSERT(!mLinkingState && mState.mExecutable);
2153     return mState.mExecutable->mTessGenSpacing;
2154 }
2155 
getTessGenVertexOrder() const2156 GLenum Program::getTessGenVertexOrder() const
2157 {
2158     ASSERT(!mLinkingState && mState.mExecutable);
2159     return mState.mExecutable->mTessGenVertexOrder;
2160 }
2161 
getInputResource(size_t index) const2162 const sh::ShaderVariable &Program::getInputResource(size_t index) const
2163 {
2164     ASSERT(!mLinkingState);
2165     ASSERT(index < mState.mExecutable->getProgramInputs().size());
2166     return mState.mExecutable->getProgramInputs()[index];
2167 }
2168 
getInputResourceIndex(const GLchar * name) const2169 GLuint Program::getInputResourceIndex(const GLchar *name) const
2170 {
2171     ASSERT(!mLinkingState);
2172     const std::string nameString = StripLastArrayIndex(name);
2173 
2174     for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
2175     {
2176         sh::ShaderVariable resource = getInputResource(index);
2177         if (resource.name == nameString)
2178         {
2179             return static_cast<GLuint>(index);
2180         }
2181     }
2182 
2183     return GL_INVALID_INDEX;
2184 }
2185 
getResourceMaxNameSize(const sh::ShaderVariable & resource,GLint max) const2186 GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
2187 {
2188     if (resource.isArray())
2189     {
2190         return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
2191     }
2192     else
2193     {
2194         return std::max(max, clampCast<GLint>((resource.name).size()));
2195     }
2196 }
2197 
getInputResourceMaxNameSize() const2198 GLuint Program::getInputResourceMaxNameSize() const
2199 {
2200     GLint max = 0;
2201 
2202     for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
2203     {
2204         max = getResourceMaxNameSize(resource, max);
2205     }
2206 
2207     return max;
2208 }
2209 
getOutputResourceMaxNameSize() const2210 GLuint Program::getOutputResourceMaxNameSize() const
2211 {
2212     GLint max = 0;
2213 
2214     for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
2215     {
2216         max = getResourceMaxNameSize(resource, max);
2217     }
2218 
2219     return max;
2220 }
2221 
getResourceLocation(const GLchar * name,const sh::ShaderVariable & variable) const2222 GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
2223 {
2224     if (variable.isBuiltIn())
2225     {
2226         return GL_INVALID_INDEX;
2227     }
2228 
2229     GLint location = variable.location;
2230     if (variable.isArray())
2231     {
2232         size_t nameLengthWithoutArrayIndexOut;
2233         size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
2234         // The 'name' string may not contain the array notation "[0]"
2235         if (arrayIndex != GL_INVALID_INDEX)
2236         {
2237             location += arrayIndex;
2238         }
2239     }
2240 
2241     return location;
2242 }
2243 
getInputResourceLocation(const GLchar * name) const2244 GLuint Program::getInputResourceLocation(const GLchar *name) const
2245 {
2246     const GLuint index = getInputResourceIndex(name);
2247     if (index == GL_INVALID_INDEX)
2248     {
2249         return index;
2250     }
2251 
2252     const sh::ShaderVariable &variable = getInputResource(index);
2253 
2254     return getResourceLocation(name, variable);
2255 }
2256 
getOutputResourceLocation(const GLchar * name) const2257 GLuint Program::getOutputResourceLocation(const GLchar *name) const
2258 {
2259     const GLuint index = getOutputResourceIndex(name);
2260     if (index == GL_INVALID_INDEX)
2261     {
2262         return index;
2263     }
2264 
2265     const sh::ShaderVariable &variable = getOutputResource(index);
2266 
2267     return getResourceLocation(name, variable);
2268 }
2269 
getOutputResourceIndex(const GLchar * name) const2270 GLuint Program::getOutputResourceIndex(const GLchar *name) const
2271 {
2272     ASSERT(!mLinkingState);
2273     const std::string nameString = StripLastArrayIndex(name);
2274 
2275     for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
2276     {
2277         sh::ShaderVariable resource = getOutputResource(index);
2278         if (resource.name == nameString)
2279         {
2280             return static_cast<GLuint>(index);
2281         }
2282     }
2283 
2284     return GL_INVALID_INDEX;
2285 }
2286 
getOutputResourceCount() const2287 size_t Program::getOutputResourceCount() const
2288 {
2289     ASSERT(!mLinkingState);
2290     return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
2291 }
2292 
getOutputVariableTypes() const2293 const std::vector<GLenum> &Program::getOutputVariableTypes() const
2294 {
2295     ASSERT(!mLinkingState);
2296     return mState.mOutputVariableTypes;
2297 }
2298 
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2299 void Program::getResourceName(const std::string name,
2300                               GLsizei bufSize,
2301                               GLsizei *length,
2302                               GLchar *dest) const
2303 {
2304     if (length)
2305     {
2306         *length = 0;
2307     }
2308 
2309     if (!mLinked)
2310     {
2311         if (bufSize > 0)
2312         {
2313             dest[0] = '\0';
2314         }
2315         return;
2316     }
2317 
2318     if (bufSize > 0)
2319     {
2320         CopyStringToBuffer(dest, name, bufSize, length);
2321     }
2322 }
2323 
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2324 void Program::getInputResourceName(GLuint index,
2325                                    GLsizei bufSize,
2326                                    GLsizei *length,
2327                                    GLchar *name) const
2328 {
2329     ASSERT(!mLinkingState);
2330     getResourceName(getInputResourceName(index), bufSize, length, name);
2331 }
2332 
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2333 void Program::getOutputResourceName(GLuint index,
2334                                     GLsizei bufSize,
2335                                     GLsizei *length,
2336                                     GLchar *name) const
2337 {
2338     ASSERT(!mLinkingState);
2339     getResourceName(getOutputResourceName(index), bufSize, length, name);
2340 }
2341 
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2342 void Program::getUniformResourceName(GLuint index,
2343                                      GLsizei bufSize,
2344                                      GLsizei *length,
2345                                      GLchar *name) const
2346 {
2347     ASSERT(!mLinkingState);
2348     ASSERT(index < mState.mExecutable->getUniforms().size());
2349     getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
2350 }
2351 
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2352 void Program::getBufferVariableResourceName(GLuint index,
2353                                             GLsizei bufSize,
2354                                             GLsizei *length,
2355                                             GLchar *name) const
2356 {
2357     ASSERT(!mLinkingState);
2358     ASSERT(index < mState.mBufferVariables.size());
2359     getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
2360 }
2361 
getResourceName(const sh::ShaderVariable & resource) const2362 const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
2363 {
2364     std::string resourceName = resource.name;
2365 
2366     if (resource.isArray())
2367     {
2368         resourceName += "[0]";
2369     }
2370 
2371     return resourceName;
2372 }
2373 
getInputResourceName(GLuint index) const2374 const std::string Program::getInputResourceName(GLuint index) const
2375 {
2376     ASSERT(!mLinkingState);
2377     const sh::ShaderVariable &resource = getInputResource(index);
2378 
2379     return getResourceName(resource);
2380 }
2381 
getOutputResourceName(GLuint index) const2382 const std::string Program::getOutputResourceName(GLuint index) const
2383 {
2384     ASSERT(!mLinkingState);
2385     const sh::ShaderVariable &resource = getOutputResource(index);
2386 
2387     return getResourceName(resource);
2388 }
2389 
getOutputResource(size_t index) const2390 const sh::ShaderVariable &Program::getOutputResource(size_t index) const
2391 {
2392     ASSERT(!mLinkingState);
2393     ASSERT(index < mState.mExecutable->getOutputVariables().size());
2394     return mState.mExecutable->getOutputVariables()[index];
2395 }
2396 
getAttributeBindings() const2397 const ProgramBindings &Program::getAttributeBindings() const
2398 {
2399     ASSERT(!mLinkingState);
2400     return mAttributeBindings;
2401 }
getUniformLocationBindings() const2402 const ProgramAliasedBindings &Program::getUniformLocationBindings() const
2403 {
2404     ASSERT(!mLinkingState);
2405     return mState.mUniformLocationBindings;
2406 }
2407 
getFragmentOutputLocations() const2408 const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
2409 {
2410     ASSERT(!mLinkingState);
2411     return mFragmentOutputLocations;
2412 }
2413 
getFragmentOutputIndexes() const2414 const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
2415 {
2416     ASSERT(!mLinkingState);
2417     return mFragmentOutputIndexes;
2418 }
2419 
getDrawBufferTypeMask() const2420 ComponentTypeMask Program::getDrawBufferTypeMask() const
2421 {
2422     ASSERT(!mLinkingState);
2423     return mState.mDrawBufferTypeMask;
2424 }
2425 
getTransformFeedbackStrides() const2426 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2427 {
2428     ASSERT(!mLinkingState);
2429     return mState.mExecutable->getTransformFeedbackStrides();
2430 }
2431 
getFragDataLocation(const std::string & name) const2432 GLint Program::getFragDataLocation(const std::string &name) const
2433 {
2434     ASSERT(!mLinkingState);
2435     GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
2436                                                 mState.mExecutable->getOutputLocations(), name);
2437     if (primaryLocation != -1)
2438     {
2439         return primaryLocation;
2440     }
2441     return GetVariableLocation(mState.mExecutable->getOutputVariables(),
2442                                mState.mExecutable->getSecondaryOutputLocations(), name);
2443 }
2444 
getFragDataIndex(const std::string & name) const2445 GLint Program::getFragDataIndex(const std::string &name) const
2446 {
2447     ASSERT(!mLinkingState);
2448     if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2449                             mState.mExecutable->getOutputLocations(), name) != -1)
2450     {
2451         return 0;
2452     }
2453     if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2454                             mState.mExecutable->getSecondaryOutputLocations(), name) != -1)
2455     {
2456         return 1;
2457     }
2458     return -1;
2459 }
2460 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2461 void Program::getActiveUniform(GLuint index,
2462                                GLsizei bufsize,
2463                                GLsizei *length,
2464                                GLint *size,
2465                                GLenum *type,
2466                                GLchar *name) const
2467 {
2468     ASSERT(!mLinkingState);
2469     if (mLinked)
2470     {
2471         // index must be smaller than getActiveUniformCount()
2472         ASSERT(index < mState.mExecutable->getUniforms().size());
2473         const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
2474 
2475         if (bufsize > 0)
2476         {
2477             std::string string = uniform.name;
2478             CopyStringToBuffer(name, string, bufsize, length);
2479         }
2480 
2481         *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2482         *type = uniform.type;
2483     }
2484     else
2485     {
2486         if (bufsize > 0)
2487         {
2488             name[0] = '\0';
2489         }
2490 
2491         if (length)
2492         {
2493             *length = 0;
2494         }
2495 
2496         *size = 0;
2497         *type = GL_NONE;
2498     }
2499 }
2500 
getActiveUniformCount() const2501 GLint Program::getActiveUniformCount() const
2502 {
2503     ASSERT(!mLinkingState);
2504     if (mLinked)
2505     {
2506         return static_cast<GLint>(mState.mExecutable->getUniforms().size());
2507     }
2508     else
2509     {
2510         return 0;
2511     }
2512 }
2513 
getActiveBufferVariableCount() const2514 size_t Program::getActiveBufferVariableCount() const
2515 {
2516     ASSERT(!mLinkingState);
2517     return mLinked ? mState.mBufferVariables.size() : 0;
2518 }
2519 
getActiveUniformMaxLength() const2520 GLint Program::getActiveUniformMaxLength() const
2521 {
2522     ASSERT(!mLinkingState);
2523     size_t maxLength = 0;
2524 
2525     if (mLinked)
2526     {
2527         for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
2528         {
2529             if (!uniform.name.empty())
2530             {
2531                 size_t length = uniform.name.length() + 1u;
2532                 if (uniform.isArray())
2533                 {
2534                     length += 3;  // Counting in "[0]".
2535                 }
2536                 maxLength = std::max(length, maxLength);
2537             }
2538         }
2539     }
2540 
2541     return static_cast<GLint>(maxLength);
2542 }
2543 
isValidUniformLocation(UniformLocation location) const2544 bool Program::isValidUniformLocation(UniformLocation location) const
2545 {
2546     ASSERT(!mLinkingState);
2547     ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2548     return (location.value >= 0 &&
2549             static_cast<size_t>(location.value) < mState.mUniformLocations.size() &&
2550             mState.mUniformLocations[static_cast<size_t>(location.value)].used());
2551 }
2552 
getUniformByLocation(UniformLocation location) const2553 const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const
2554 {
2555     ASSERT(!mLinkingState);
2556     ASSERT(location.value >= 0 &&
2557            static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2558     return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
2559 }
2560 
getUniformLocation(UniformLocation location) const2561 const VariableLocation &Program::getUniformLocation(UniformLocation location) const
2562 {
2563     ASSERT(!mLinkingState);
2564     ASSERT(location.value >= 0 &&
2565            static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2566     return mState.mUniformLocations[location.value];
2567 }
2568 
getBufferVariableByIndex(GLuint index) const2569 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2570 {
2571     ASSERT(!mLinkingState);
2572     ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2573     return mState.mBufferVariables[index];
2574 }
2575 
getUniformLocation(const std::string & name) const2576 UniformLocation Program::getUniformLocation(const std::string &name) const
2577 {
2578     ASSERT(!mLinkingState);
2579     return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
2580 }
2581 
getUniformIndex(const std::string & name) const2582 GLuint Program::getUniformIndex(const std::string &name) const
2583 {
2584     ASSERT(!mLinkingState);
2585     return mState.getUniformIndexFromName(name);
2586 }
2587 
shouldIgnoreUniform(UniformLocation location) const2588 bool Program::shouldIgnoreUniform(UniformLocation location) const
2589 {
2590     if (location.value == -1)
2591     {
2592         return true;
2593     }
2594 
2595     if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored)
2596     {
2597         return true;
2598     }
2599 
2600     return false;
2601 }
2602 
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2603 void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2604 {
2605     ASSERT(!mLinkingState);
2606     if (shouldIgnoreUniform(location))
2607     {
2608         return;
2609     }
2610 
2611     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2612     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2613     mProgram->setUniform1fv(location.value, clampedCount, v);
2614 }
2615 
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2616 void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2617 {
2618     ASSERT(!mLinkingState);
2619     if (shouldIgnoreUniform(location))
2620     {
2621         return;
2622     }
2623 
2624     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2625     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2626     mProgram->setUniform2fv(location.value, clampedCount, v);
2627 }
2628 
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2629 void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2630 {
2631     ASSERT(!mLinkingState);
2632     if (shouldIgnoreUniform(location))
2633     {
2634         return;
2635     }
2636 
2637     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2638     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2639     mProgram->setUniform3fv(location.value, clampedCount, v);
2640 }
2641 
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2642 void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2643 {
2644     ASSERT(!mLinkingState);
2645     if (shouldIgnoreUniform(location))
2646     {
2647         return;
2648     }
2649 
2650     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2651     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2652     mProgram->setUniform4fv(location.value, clampedCount, v);
2653 }
2654 
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2655 void Program::setUniform1iv(Context *context,
2656                             UniformLocation location,
2657                             GLsizei count,
2658                             const GLint *v)
2659 {
2660     ASSERT(!mLinkingState);
2661     if (shouldIgnoreUniform(location))
2662     {
2663         return;
2664     }
2665 
2666     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2667     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2668 
2669     mProgram->setUniform1iv(location.value, clampedCount, v);
2670 
2671     if (mState.isSamplerUniformIndex(locationInfo.index))
2672     {
2673         updateSamplerUniform(context, locationInfo, clampedCount, v);
2674     }
2675 }
2676 
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2677 void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2678 {
2679     ASSERT(!mLinkingState);
2680     if (shouldIgnoreUniform(location))
2681     {
2682         return;
2683     }
2684 
2685     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2686     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2687     mProgram->setUniform2iv(location.value, clampedCount, v);
2688 }
2689 
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2690 void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2691 {
2692     ASSERT(!mLinkingState);
2693     if (shouldIgnoreUniform(location))
2694     {
2695         return;
2696     }
2697 
2698     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2699     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2700     mProgram->setUniform3iv(location.value, clampedCount, v);
2701 }
2702 
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2703 void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2704 {
2705     ASSERT(!mLinkingState);
2706     if (shouldIgnoreUniform(location))
2707     {
2708         return;
2709     }
2710 
2711     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2712     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2713     mProgram->setUniform4iv(location.value, clampedCount, v);
2714 }
2715 
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2716 void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2717 {
2718     ASSERT(!mLinkingState);
2719     if (shouldIgnoreUniform(location))
2720     {
2721         return;
2722     }
2723 
2724     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2725     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2726     mProgram->setUniform1uiv(location.value, clampedCount, v);
2727 }
2728 
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2729 void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2730 {
2731     ASSERT(!mLinkingState);
2732     if (shouldIgnoreUniform(location))
2733     {
2734         return;
2735     }
2736 
2737     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2738     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
2739     mProgram->setUniform2uiv(location.value, clampedCount, v);
2740 }
2741 
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2742 void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2743 {
2744     ASSERT(!mLinkingState);
2745     if (shouldIgnoreUniform(location))
2746     {
2747         return;
2748     }
2749 
2750     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2751     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
2752     mProgram->setUniform3uiv(location.value, clampedCount, v);
2753 }
2754 
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2755 void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2756 {
2757     ASSERT(!mLinkingState);
2758     if (shouldIgnoreUniform(location))
2759     {
2760         return;
2761     }
2762 
2763     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2764     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
2765     mProgram->setUniform4uiv(location.value, clampedCount, v);
2766 }
2767 
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2768 void Program::setUniformMatrix2fv(UniformLocation location,
2769                                   GLsizei count,
2770                                   GLboolean transpose,
2771                                   const GLfloat *v)
2772 {
2773     ASSERT(!mLinkingState);
2774     if (shouldIgnoreUniform(location))
2775     {
2776         return;
2777     }
2778 
2779     GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
2780     mProgram->setUniformMatrix2fv(location.value, clampedCount, transpose, v);
2781 }
2782 
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2783 void Program::setUniformMatrix3fv(UniformLocation location,
2784                                   GLsizei count,
2785                                   GLboolean transpose,
2786                                   const GLfloat *v)
2787 {
2788     ASSERT(!mLinkingState);
2789     if (shouldIgnoreUniform(location))
2790     {
2791         return;
2792     }
2793 
2794     GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
2795     mProgram->setUniformMatrix3fv(location.value, clampedCount, transpose, v);
2796 }
2797 
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2798 void Program::setUniformMatrix4fv(UniformLocation location,
2799                                   GLsizei count,
2800                                   GLboolean transpose,
2801                                   const GLfloat *v)
2802 {
2803     ASSERT(!mLinkingState);
2804     if (shouldIgnoreUniform(location))
2805     {
2806         return;
2807     }
2808 
2809     GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
2810     mProgram->setUniformMatrix4fv(location.value, clampedCount, transpose, v);
2811 }
2812 
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2813 void Program::setUniformMatrix2x3fv(UniformLocation location,
2814                                     GLsizei count,
2815                                     GLboolean transpose,
2816                                     const GLfloat *v)
2817 {
2818     ASSERT(!mLinkingState);
2819     if (shouldIgnoreUniform(location))
2820     {
2821         return;
2822     }
2823 
2824     GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
2825     mProgram->setUniformMatrix2x3fv(location.value, clampedCount, transpose, v);
2826 }
2827 
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2828 void Program::setUniformMatrix2x4fv(UniformLocation location,
2829                                     GLsizei count,
2830                                     GLboolean transpose,
2831                                     const GLfloat *v)
2832 {
2833     ASSERT(!mLinkingState);
2834     if (shouldIgnoreUniform(location))
2835     {
2836         return;
2837     }
2838 
2839     GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
2840     mProgram->setUniformMatrix2x4fv(location.value, clampedCount, transpose, v);
2841 }
2842 
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2843 void Program::setUniformMatrix3x2fv(UniformLocation location,
2844                                     GLsizei count,
2845                                     GLboolean transpose,
2846                                     const GLfloat *v)
2847 {
2848     ASSERT(!mLinkingState);
2849     if (shouldIgnoreUniform(location))
2850     {
2851         return;
2852     }
2853 
2854     GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
2855     mProgram->setUniformMatrix3x2fv(location.value, clampedCount, transpose, v);
2856 }
2857 
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2858 void Program::setUniformMatrix3x4fv(UniformLocation location,
2859                                     GLsizei count,
2860                                     GLboolean transpose,
2861                                     const GLfloat *v)
2862 {
2863     ASSERT(!mLinkingState);
2864     if (shouldIgnoreUniform(location))
2865     {
2866         return;
2867     }
2868 
2869     GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
2870     mProgram->setUniformMatrix3x4fv(location.value, clampedCount, transpose, v);
2871 }
2872 
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2873 void Program::setUniformMatrix4x2fv(UniformLocation location,
2874                                     GLsizei count,
2875                                     GLboolean transpose,
2876                                     const GLfloat *v)
2877 {
2878     ASSERT(!mLinkingState);
2879     if (shouldIgnoreUniform(location))
2880     {
2881         return;
2882     }
2883 
2884     GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
2885     mProgram->setUniformMatrix4x2fv(location.value, clampedCount, transpose, v);
2886 }
2887 
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2888 void Program::setUniformMatrix4x3fv(UniformLocation location,
2889                                     GLsizei count,
2890                                     GLboolean transpose,
2891                                     const GLfloat *v)
2892 {
2893     ASSERT(!mLinkingState);
2894     if (shouldIgnoreUniform(location))
2895     {
2896         return;
2897     }
2898 
2899     GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
2900     mProgram->setUniformMatrix4x3fv(location.value, clampedCount, transpose, v);
2901 }
2902 
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2903 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2904 {
2905     ASSERT(!mLinkingState);
2906     GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2907     const std::vector<GLuint> &boundTextureUnits =
2908         mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
2909     return (uniformLocation.arrayIndex < boundTextureUnits.size())
2910                ? boundTextureUnits[uniformLocation.arrayIndex]
2911                : 0;
2912 }
2913 
getImageUniformBinding(const VariableLocation & uniformLocation) const2914 GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
2915 {
2916     ASSERT(!mLinkingState);
2917     GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
2918 
2919     const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings();
2920     const std::vector<GLuint> &boundImageUnits     = imageBindings[imageIndex].boundImageUnits;
2921     return boundImageUnits[uniformLocation.arrayIndex];
2922 }
2923 
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2924 void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const
2925 {
2926     ASSERT(!mLinkingState);
2927     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2928     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2929 
2930     if (uniform.isSampler())
2931     {
2932         *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2933         return;
2934     }
2935     else if (uniform.isImage())
2936     {
2937         *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2938         return;
2939     }
2940 
2941     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2942     if (nativeType == GL_FLOAT)
2943     {
2944         mProgram->getUniformfv(context, location.value, v);
2945     }
2946     else
2947     {
2948         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2949     }
2950 }
2951 
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2952 void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const
2953 {
2954     ASSERT(!mLinkingState);
2955     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2956     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2957 
2958     if (uniform.isSampler())
2959     {
2960         *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2961         return;
2962     }
2963     else if (uniform.isImage())
2964     {
2965         *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2966         return;
2967     }
2968 
2969     const GLenum nativeType = gl::VariableComponentType(uniform.type);
2970     if (nativeType == GL_INT || nativeType == GL_BOOL)
2971     {
2972         mProgram->getUniformiv(context, location.value, v);
2973     }
2974     else
2975     {
2976         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2977     }
2978 }
2979 
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2980 void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const
2981 {
2982     ASSERT(!mLinkingState);
2983     const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2984     const LinkedUniform &uniform            = mState.getUniforms()[uniformLocation.index];
2985 
2986     if (uniform.isSampler())
2987     {
2988         *v = getSamplerUniformBinding(uniformLocation);
2989         return;
2990     }
2991     else if (uniform.isImage())
2992     {
2993         *v = getImageUniformBinding(uniformLocation);
2994         return;
2995     }
2996 
2997     const GLenum nativeType = VariableComponentType(uniform.type);
2998     if (nativeType == GL_UNSIGNED_INT)
2999     {
3000         mProgram->getUniformuiv(context, location.value, v);
3001     }
3002     else
3003     {
3004         getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
3005     }
3006 }
3007 
flagForDeletion()3008 void Program::flagForDeletion()
3009 {
3010     ASSERT(!mLinkingState);
3011     mDeleteStatus = true;
3012 }
3013 
isFlaggedForDeletion() const3014 bool Program::isFlaggedForDeletion() const
3015 {
3016     ASSERT(!mLinkingState);
3017     return mDeleteStatus;
3018 }
3019 
validate(const Caps & caps)3020 void Program::validate(const Caps &caps)
3021 {
3022     ASSERT(!mLinkingState);
3023     mState.mExecutable->resetInfoLog();
3024     InfoLog &infoLog = mState.mExecutable->getInfoLog();
3025 
3026     if (mLinked)
3027     {
3028         mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
3029     }
3030     else
3031     {
3032         infoLog << "Program has not been successfully linked.";
3033     }
3034 }
3035 
isValidated() const3036 bool Program::isValidated() const
3037 {
3038     ASSERT(!mLinkingState);
3039     return mValidated;
3040 }
3041 
getActiveUniformBlockName(const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3042 void Program::getActiveUniformBlockName(const UniformBlockIndex blockIndex,
3043                                         GLsizei bufSize,
3044                                         GLsizei *length,
3045                                         GLchar *blockName) const
3046 {
3047     ASSERT(!mLinkingState);
3048     GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
3049                           blockName);
3050 }
3051 
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3052 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
3053                                               GLsizei bufSize,
3054                                               GLsizei *length,
3055                                               GLchar *blockName) const
3056 {
3057     ASSERT(!mLinkingState);
3058     GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize,
3059                           length, blockName);
3060 }
3061 
3062 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const3063 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
3064 {
3065     int maxLength = 0;
3066 
3067     if (mLinked)
3068     {
3069         for (const T &resource : resources)
3070         {
3071             if (!resource.name.empty())
3072             {
3073                 int length = static_cast<int>(resource.nameWithArrayIndex().length());
3074                 maxLength  = std::max(length + 1, maxLength);
3075             }
3076         }
3077     }
3078 
3079     return maxLength;
3080 }
3081 
getActiveUniformBlockMaxNameLength() const3082 GLint Program::getActiveUniformBlockMaxNameLength() const
3083 {
3084     ASSERT(!mLinkingState);
3085     return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
3086 }
3087 
getActiveShaderStorageBlockMaxNameLength() const3088 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
3089 {
3090     ASSERT(!mLinkingState);
3091     return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
3092 }
3093 
getUniformBlockIndex(const std::string & name) const3094 GLuint Program::getUniformBlockIndex(const std::string &name) const
3095 {
3096     ASSERT(!mLinkingState);
3097     return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
3098 }
3099 
getShaderStorageBlockIndex(const std::string & name) const3100 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
3101 {
3102     ASSERT(!mLinkingState);
3103     return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
3104 }
3105 
getUniformBlockByIndex(GLuint index) const3106 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
3107 {
3108     ASSERT(!mLinkingState);
3109     ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
3110     return mState.mExecutable->getUniformBlocks()[index];
3111 }
3112 
getShaderStorageBlockByIndex(GLuint index) const3113 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
3114 {
3115     ASSERT(!mLinkingState);
3116     ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
3117     return mState.mExecutable->getShaderStorageBlocks()[index];
3118 }
3119 
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)3120 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
3121 {
3122     ASSERT(!mLinkingState);
3123     mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding;
3124     mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value,
3125                                                         uniformBlockBinding != 0);
3126     mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value);
3127 }
3128 
getUniformBlockBinding(GLuint uniformBlockIndex) const3129 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
3130 {
3131     ASSERT(!mLinkingState);
3132     return mState.getUniformBlockBinding(uniformBlockIndex);
3133 }
3134 
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const3135 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
3136 {
3137     ASSERT(!mLinkingState);
3138     return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
3139 }
3140 
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)3141 void Program::setTransformFeedbackVaryings(GLsizei count,
3142                                            const GLchar *const *varyings,
3143                                            GLenum bufferMode)
3144 {
3145     ASSERT(!mLinkingState);
3146     mState.mTransformFeedbackVaryingNames.resize(count);
3147     for (GLsizei i = 0; i < count; i++)
3148     {
3149         mState.mTransformFeedbackVaryingNames[i] = varyings[i];
3150     }
3151 
3152     mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
3153 }
3154 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const3155 void Program::getTransformFeedbackVarying(GLuint index,
3156                                           GLsizei bufSize,
3157                                           GLsizei *length,
3158                                           GLsizei *size,
3159                                           GLenum *type,
3160                                           GLchar *name) const
3161 {
3162     ASSERT(!mLinkingState);
3163     if (mLinked)
3164     {
3165         ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3166         const auto &var     = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3167         std::string varName = var.nameWithArrayIndex();
3168         GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
3169         if (length)
3170         {
3171             *length = lastNameIdx;
3172         }
3173         if (size)
3174         {
3175             *size = var.size();
3176         }
3177         if (type)
3178         {
3179             *type = var.type;
3180         }
3181         if (name)
3182         {
3183             memcpy(name, varName.c_str(), lastNameIdx);
3184             name[lastNameIdx] = '\0';
3185         }
3186     }
3187 }
3188 
getTransformFeedbackVaryingCount() const3189 GLsizei Program::getTransformFeedbackVaryingCount() const
3190 {
3191     ASSERT(!mLinkingState);
3192     if (mLinked)
3193     {
3194         return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3195     }
3196     else
3197     {
3198         return 0;
3199     }
3200 }
3201 
getTransformFeedbackVaryingMaxLength() const3202 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
3203 {
3204     ASSERT(!mLinkingState);
3205     if (mLinked)
3206     {
3207         GLsizei maxSize = 0;
3208         for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
3209         {
3210             maxSize =
3211                 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
3212         }
3213 
3214         return maxSize;
3215     }
3216     else
3217     {
3218         return 0;
3219     }
3220 }
3221 
getTransformFeedbackBufferMode() const3222 GLenum Program::getTransformFeedbackBufferMode() const
3223 {
3224     ASSERT(!mLinkingState);
3225     return mState.mExecutable->getTransformFeedbackBufferMode();
3226 }
3227 
linkValidateShaders(InfoLog & infoLog)3228 bool Program::linkValidateShaders(InfoLog &infoLog)
3229 {
3230     const ShaderMap<Shader *> &shaders = mState.mAttachedShaders;
3231 
3232     bool isComputeShaderAttached  = shaders[ShaderType::Compute] != nullptr;
3233     bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] ||
3234                                     shaders[ShaderType::TessControl] ||
3235                                     shaders[ShaderType::TessEvaluation] ||
3236                                     shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment];
3237     // Check whether we both have a compute and non-compute shaders attached.
3238     // If there are of both types attached, then linking should fail.
3239     // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
3240     if (isComputeShaderAttached && isGraphicsShaderAttached)
3241     {
3242         infoLog << "Both compute and graphics shaders are attached to the same program.";
3243         return false;
3244     }
3245 
3246     Optional<int> version;
3247     for (ShaderType shaderType : kAllGraphicsShaderTypes)
3248     {
3249         Shader *shader = shaders[shaderType];
3250         ASSERT(!shader || shader->getType() == shaderType);
3251         if (!shader)
3252         {
3253             continue;
3254         }
3255 
3256         if (!shader->isCompiled())
3257         {
3258             infoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
3259             return false;
3260         }
3261 
3262         if (!version.valid())
3263         {
3264             version = shader->getShaderVersion();
3265         }
3266         else if (version != shader->getShaderVersion())
3267         {
3268             infoLog << ShaderTypeToString(shaderType)
3269                     << " shader version does not match other shader versions.";
3270             return false;
3271         }
3272     }
3273 
3274     if (isComputeShaderAttached)
3275     {
3276         ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute);
3277 
3278         mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize();
3279 
3280         // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
3281         // If the work group size is not specified, a link time error should occur.
3282         if (!mState.mComputeShaderLocalSize.isDeclared())
3283         {
3284             infoLog << "Work group size is not specified.";
3285             return false;
3286         }
3287     }
3288     else
3289     {
3290         if (!isGraphicsShaderAttached)
3291         {
3292             infoLog << "No compiled shaders.";
3293             return false;
3294         }
3295 
3296         bool hasVertex   = shaders[ShaderType::Vertex] != nullptr;
3297         bool hasFragment = shaders[ShaderType::Fragment] != nullptr;
3298         if (!isSeparable() && (!hasVertex || !hasFragment))
3299         {
3300             infoLog
3301                 << "The program must contain objects to form both a vertex and fragment shader.";
3302             return false;
3303         }
3304 
3305         bool hasTessControl    = shaders[ShaderType::TessControl] != nullptr;
3306         bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr;
3307         if (!isSeparable() && (hasTessControl != hasTessEvaluation))
3308         {
3309             infoLog << "Tessellation control and evaluation shaders must be specified together.";
3310             return false;
3311         }
3312 
3313         Shader *geometryShader = shaders[ShaderType::Geometry];
3314         if (shaders[ShaderType::Geometry])
3315         {
3316             // [GL_EXT_geometry_shader] Chapter 7
3317             // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
3318             // Language Specification, as well as any of the following reasons:
3319             // * One or more of the shader objects attached to <program> are not compiled
3320             //   successfully.
3321             // * The shaders do not use the same shader language version.
3322             // * <program> contains objects to form a geometry shader, and
3323             //   - <program> is not separable and contains no objects to form a vertex shader; or
3324             //   - the input primitive type, output primitive type, or maximum output vertex count
3325             //     is not specified in the compiled geometry shader object.
3326             ASSERT(geometryShader->getType() == ShaderType::Geometry);
3327 
3328             Optional<PrimitiveMode> inputPrimitive =
3329                 geometryShader->getGeometryShaderInputPrimitiveType();
3330             if (!inputPrimitive.valid())
3331             {
3332                 infoLog << "Input primitive type is not specified in the geometry shader.";
3333                 return false;
3334             }
3335 
3336             Optional<PrimitiveMode> outputPrimitive =
3337                 geometryShader->getGeometryShaderOutputPrimitiveType();
3338             if (!outputPrimitive.valid())
3339             {
3340                 infoLog << "Output primitive type is not specified in the geometry shader.";
3341                 return false;
3342             }
3343 
3344             Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
3345             if (!maxVertices.valid())
3346             {
3347                 infoLog << "'max_vertices' is not specified in the geometry shader.";
3348                 return false;
3349             }
3350 
3351             mState.mExecutable->mGeometryShaderInputPrimitiveType  = inputPrimitive.value();
3352             mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
3353             mState.mExecutable->mGeometryShaderMaxVertices         = maxVertices.value();
3354             mState.mExecutable->mGeometryShaderInvocations =
3355                 geometryShader->getGeometryShaderInvocations();
3356         }
3357 
3358         Shader *tessControlShader = shaders[ShaderType::TessControl];
3359         if (tessControlShader)
3360         {
3361             int tcsShaderVertices = tessControlShader->getTessControlShaderVertices();
3362             if (tcsShaderVertices == 0)
3363             {
3364                 // In tessellation control shader, output vertices should be specified at least
3365                 // once.
3366                 // > GLSL ES Version 3.20.6 spec:
3367                 // > 4.4.2. Output Layout Qualifiers
3368                 // > Tessellation Control Outputs
3369                 // > ...
3370                 // > There must be at least one layout qualifier specifying an output patch vertex
3371                 // > count in any program containing a tessellation control shader.
3372                 infoLog << "In Tessellation Control Shader, at least one layout qualifier "
3373                            "specifying an output patch vertex count must exist.";
3374                 return false;
3375             }
3376 
3377             mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
3378         }
3379 
3380         Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
3381         if (tessEvaluationShader)
3382         {
3383             GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode();
3384             if (tesPrimitiveMode == 0)
3385             {
3386                 // In tessellation evaluation shader, a primitive mode should be specified at least
3387                 // once.
3388                 // > GLSL ES Version 3.20.6 spec:
3389                 // > 4.4.1. Input Layout Qualifiers
3390                 // > Tessellation Evaluation Inputs
3391                 // > ...
3392                 // > The tessellation evaluation shader object in a program must declare a primitive
3393                 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
3394                 // > identifiers is optional.
3395                 infoLog << "The Tessellation Evaluation Shader object in a program must declare a "
3396                            "primitive mode in its input layout.";
3397                 return false;
3398             }
3399 
3400             mState.mExecutable->mTessGenMode        = tesPrimitiveMode;
3401             mState.mExecutable->mTessGenSpacing     = tessEvaluationShader->getTessGenSpacing();
3402             mState.mExecutable->mTessGenVertexOrder = tessEvaluationShader->getTessGenVertexOrder();
3403             mState.mExecutable->mTessGenPointMode   = tessEvaluationShader->getTessGenPointMode();
3404         }
3405     }
3406 
3407     return true;
3408 }
3409 
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const3410 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
3411 {
3412     ASSERT(!mLinkingState);
3413     for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
3414          ++tfIndex)
3415     {
3416         const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
3417         if (tf.nameWithArrayIndex() == name)
3418         {
3419             return tfIndex;
3420         }
3421     }
3422     return GL_INVALID_INDEX;
3423 }
3424 
getTransformFeedbackVaryingResource(GLuint index) const3425 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
3426 {
3427     ASSERT(!mLinkingState);
3428     ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3429     return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3430 }
3431 
hasDrawIDUniform() const3432 bool Program::hasDrawIDUniform() const
3433 {
3434     ASSERT(!mLinkingState);
3435     return mState.mDrawIDLocation >= 0;
3436 }
3437 
setDrawIDUniform(GLint drawid)3438 void Program::setDrawIDUniform(GLint drawid)
3439 {
3440     ASSERT(!mLinkingState);
3441     ASSERT(mState.mDrawIDLocation >= 0);
3442     mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
3443 }
3444 
hasBaseVertexUniform() const3445 bool Program::hasBaseVertexUniform() const
3446 {
3447     ASSERT(!mLinkingState);
3448     return mState.mBaseVertexLocation >= 0;
3449 }
3450 
setBaseVertexUniform(GLint baseVertex)3451 void Program::setBaseVertexUniform(GLint baseVertex)
3452 {
3453     ASSERT(!mLinkingState);
3454     ASSERT(mState.mBaseVertexLocation >= 0);
3455     if (baseVertex == mState.mCachedBaseVertex)
3456     {
3457         return;
3458     }
3459     mState.mCachedBaseVertex = baseVertex;
3460     mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
3461 }
3462 
hasBaseInstanceUniform() const3463 bool Program::hasBaseInstanceUniform() const
3464 {
3465     ASSERT(!mLinkingState);
3466     return mState.mBaseInstanceLocation >= 0;
3467 }
3468 
setBaseInstanceUniform(GLuint baseInstance)3469 void Program::setBaseInstanceUniform(GLuint baseInstance)
3470 {
3471     ASSERT(!mLinkingState);
3472     ASSERT(mState.mBaseInstanceLocation >= 0);
3473     if (baseInstance == mState.mCachedBaseInstance)
3474     {
3475         return;
3476     }
3477     mState.mCachedBaseInstance = baseInstance;
3478     GLint baseInstanceInt      = baseInstance;
3479     mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
3480 }
3481 
linkVaryings(InfoLog & infoLog) const3482 bool Program::linkVaryings(InfoLog &infoLog) const
3483 {
3484     ShaderType previousShaderType = ShaderType::InvalidEnum;
3485     for (ShaderType shaderType : kAllGraphicsShaderTypes)
3486     {
3487         Shader *currentShader = mState.mAttachedShaders[shaderType];
3488         if (!currentShader)
3489         {
3490             continue;
3491         }
3492 
3493         if (previousShaderType != ShaderType::InvalidEnum)
3494         {
3495             Shader *previousShader = mState.mAttachedShaders[previousShaderType];
3496             const std::vector<sh::ShaderVariable> &outputVaryings =
3497                 previousShader->getOutputVaryings();
3498 
3499             if (!LinkValidateShaderInterfaceMatching(
3500                     outputVaryings, currentShader->getInputVaryings(), previousShaderType,
3501                     currentShader->getType(), previousShader->getShaderVersion(),
3502                     currentShader->getShaderVersion(), isSeparable(), infoLog))
3503             {
3504                 return false;
3505             }
3506         }
3507         previousShaderType = currentShader->getType();
3508     }
3509 
3510     // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
3511     // Need to move logic of validating builtin varyings inside the for-loop above.
3512     // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
3513     // can be redeclared in Geometry or Tessellation shaders as well.
3514     Shader *vertexShader   = mState.mAttachedShaders[ShaderType::Vertex];
3515     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
3516     if (vertexShader && fragmentShader &&
3517         !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
3518                                      fragmentShader->getInputVaryings(), vertexShader->getType(),
3519                                      fragmentShader->getType(), vertexShader->getShaderVersion(),
3520                                      fragmentShader->getShaderVersion(), infoLog))
3521     {
3522         return false;
3523     }
3524 
3525     return true;
3526 }
3527 
linkUniforms(const Caps & caps,const Version & version,InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings,GLuint * combinedImageUniformsCount,std::vector<UnusedUniform> * unusedUniforms)3528 bool Program::linkUniforms(const Caps &caps,
3529                            const Version &version,
3530                            InfoLog &infoLog,
3531                            const ProgramAliasedBindings &uniformLocationBindings,
3532                            GLuint *combinedImageUniformsCount,
3533                            std::vector<UnusedUniform> *unusedUniforms)
3534 {
3535     UniformLinker linker(mState);
3536     if (!linker.link(caps, infoLog, uniformLocationBindings))
3537     {
3538         return false;
3539     }
3540 
3541     linker.getResults(&mState.mExecutable->mUniforms, unusedUniforms, &mState.mUniformLocations);
3542 
3543     linkSamplerAndImageBindings(combinedImageUniformsCount);
3544 
3545     if (!linkAtomicCounterBuffers())
3546     {
3547         return false;
3548     }
3549 
3550     if (version >= Version(3, 1))
3551     {
3552         GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size());
3553 
3554         if (locationSize > caps.maxUniformLocations)
3555         {
3556             infoLog << "Exceeded maximum uniform location size";
3557             return false;
3558         }
3559     }
3560 
3561     return true;
3562 }
3563 
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)3564 void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
3565 {
3566     ASSERT(combinedImageUniforms);
3567 
3568     // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
3569     // atomic counters, images and samplers in that order.
3570     auto highIter = mState.mExecutable->getUniforms().rbegin();
3571     auto lowIter  = highIter;
3572 
3573     unsigned int high = static_cast<unsigned int>(mState.mExecutable->getUniforms().size());
3574     unsigned int low  = high;
3575 
3576     // Note that uniform block uniforms are not yet appended to this list.
3577     ASSERT(mState.mExecutable->getUniforms().size() == 0 || highIter->isAtomicCounter() ||
3578            highIter->isImage() || highIter->isSampler() || highIter->isInDefaultBlock() ||
3579            highIter->isFragmentInOut);
3580 
3581     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isFragmentInOut;
3582          ++lowIter)
3583     {
3584         --low;
3585     }
3586 
3587     mState.mExecutable->mFragmentInoutRange = RangeUI(low, high);
3588 
3589     highIter = lowIter;
3590     high     = low;
3591 
3592     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isAtomicCounter();
3593          ++lowIter)
3594     {
3595         --low;
3596     }
3597 
3598     mState.mAtomicCounterUniformRange = RangeUI(low, high);
3599 
3600     highIter = lowIter;
3601     high     = low;
3602 
3603     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isImage(); ++lowIter)
3604     {
3605         --low;
3606     }
3607 
3608     mState.mExecutable->mImageUniformRange = RangeUI(low, high);
3609     *combinedImageUniforms                 = 0u;
3610     // The Program is still linking, so getExecutable().isCompute() isn't accurate yet.
3611     bool hasComputeShader = mState.mAttachedShaders[ShaderType::Compute] != nullptr;
3612     std::vector<ImageBinding> &imageBindings = hasComputeShader
3613                                                    ? mState.mExecutable->mComputeImageBindings
3614                                                    : mState.mExecutable->mGraphicsImageBindings;
3615     // If uniform is a image type, insert it into the mImageBindings array.
3616     for (unsigned int imageIndex : mState.mExecutable->getImageUniformRange())
3617     {
3618         // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
3619         // cannot load values into a uniform defined as an image. if declare without a
3620         // binding qualifier, any uniform image variable (include all elements of
3621         // unbound image array) shoud be bound to unit zero.
3622         auto &imageUniform      = mState.mExecutable->getUniforms()[imageIndex];
3623         TextureType textureType = ImageTypeToTextureType(imageUniform.type);
3624         const GLuint arraySize  = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
3625 
3626         if (imageUniform.binding == -1)
3627         {
3628             imageBindings.emplace_back(
3629                 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
3630         }
3631         else
3632         {
3633             // The arrays of arrays are flattened to arrays, it needs to record the array offset for
3634             // the correct binding image unit.
3635             imageBindings.emplace_back(
3636                 ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize,
3637                              imageUniform.getBasicTypeElementCount(), textureType));
3638         }
3639 
3640         *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
3641     }
3642 
3643     highIter = lowIter;
3644     high     = low;
3645 
3646     for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isSampler(); ++lowIter)
3647     {
3648         --low;
3649     }
3650 
3651     mState.mExecutable->mSamplerUniformRange = RangeUI(low, high);
3652 
3653     // If uniform is a sampler type, insert it into the mSamplerBindings array.
3654     for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
3655     {
3656         const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
3657         TextureType textureType    = SamplerTypeToTextureType(samplerUniform.type);
3658         GLenum samplerType         = samplerUniform.typeInfo->type;
3659         unsigned int elementCount  = samplerUniform.getBasicTypeElementCount();
3660         SamplerFormat format       = samplerUniform.typeInfo->samplerFormat;
3661         mState.mExecutable->mSamplerBindings.emplace_back(textureType, samplerType, format,
3662                                                           elementCount);
3663     }
3664 
3665     // Whatever is left constitutes the default uniforms.
3666     mState.mExecutable->mDefaultUniformRange = RangeUI(0, low);
3667 }
3668 
linkAtomicCounterBuffers()3669 bool Program::linkAtomicCounterBuffers()
3670 {
3671     for (unsigned int index : mState.mAtomicCounterUniformRange)
3672     {
3673         auto &uniform                      = mState.mExecutable->mUniforms[index];
3674         uniform.blockInfo.offset           = uniform.offset;
3675         uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
3676         uniform.blockInfo.matrixStride     = 0;
3677         uniform.blockInfo.isRowMajorMatrix = false;
3678 
3679         bool found = false;
3680         for (unsigned int bufferIndex = 0;
3681              bufferIndex < mState.mExecutable->getActiveAtomicCounterBufferCount(); ++bufferIndex)
3682         {
3683             auto &buffer = mState.mExecutable->mAtomicCounterBuffers[bufferIndex];
3684             if (buffer.binding == uniform.binding)
3685             {
3686                 buffer.memberIndexes.push_back(index);
3687                 uniform.bufferIndex = bufferIndex;
3688                 found               = true;
3689                 buffer.unionReferencesWith(uniform);
3690                 break;
3691             }
3692         }
3693         if (!found)
3694         {
3695             AtomicCounterBuffer atomicCounterBuffer;
3696             atomicCounterBuffer.binding = uniform.binding;
3697             atomicCounterBuffer.memberIndexes.push_back(index);
3698             atomicCounterBuffer.unionReferencesWith(uniform);
3699             mState.mExecutable->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
3700             uniform.bufferIndex =
3701                 static_cast<int>(mState.mExecutable->getActiveAtomicCounterBufferCount() - 1);
3702         }
3703     }
3704     // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
3705     // gl_Max[Vertex|Fragment|Compute|Geometry|Combined]AtomicCounterBuffers.
3706 
3707     return true;
3708 }
3709 
3710 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3711 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3712 {
3713     const Caps &caps               = context->getCaps();
3714     const Limitations &limitations = context->getLimitations();
3715     bool webglCompatibility        = context->getExtensions().webglCompatibility;
3716     int shaderVersion              = -1;
3717     unsigned int usedLocations     = 0;
3718 
3719     Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
3720 
3721     if (!vertexShader)
3722     {
3723         // No vertex shader, so no attributes, so nothing to do
3724         return true;
3725     }
3726 
3727     shaderVersion = vertexShader->getShaderVersion();
3728     if (shaderVersion >= 300)
3729     {
3730         // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
3731         // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
3732         // aliasing checks.
3733         mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes();
3734     }
3735     else
3736     {
3737         // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3738         mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes();
3739     }
3740 
3741     GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
3742     std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
3743 
3744     // Assign locations to attributes that have a binding location and check for attribute aliasing.
3745     for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3746     {
3747         // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3748         // structures, so we don't need to worry about adjusting their names or generating entries
3749         // for each member/element (unlike uniforms for example).
3750         ASSERT(!attribute.isArray() && !attribute.isStruct());
3751 
3752         int bindingLocation = mAttributeBindings.getBinding(attribute);
3753         if (attribute.location == -1 && bindingLocation != -1)
3754         {
3755             attribute.location = bindingLocation;
3756         }
3757 
3758         if (attribute.location != -1)
3759         {
3760             // Location is set by glBindAttribLocation or by location layout qualifier
3761             const int regs = VariableRegisterCount(attribute.type);
3762 
3763             if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3764             {
3765                 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3766                         << " is too big to fit";
3767 
3768                 return false;
3769             }
3770 
3771             for (int reg = 0; reg < regs; reg++)
3772             {
3773                 const int regLocation               = attribute.location + reg;
3774                 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3775 
3776                 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3777                 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3778                 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3779                 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3780                 if (linkedAttribute)
3781                 {
3782                     if (shaderVersion >= 300 || webglCompatibility ||
3783                         limitations.noVertexAttributeAliasing)
3784                     {
3785                         infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3786                                 << linkedAttribute->name << "' at location " << regLocation;
3787                         return false;
3788                     }
3789                 }
3790                 else
3791                 {
3792                     usedAttribMap[regLocation] = &attribute;
3793                 }
3794 
3795                 usedLocations |= 1 << regLocation;
3796             }
3797         }
3798     }
3799 
3800     // Assign locations to attributes that don't have a binding location.
3801     for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3802     {
3803         // Not set by glBindAttribLocation or by location layout qualifier
3804         if (attribute.location == -1)
3805         {
3806             int regs           = VariableRegisterCount(attribute.type);
3807             int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3808 
3809             if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3810             {
3811                 infoLog << "Too many attributes (" << attribute.name << ")";
3812                 return false;
3813             }
3814 
3815             attribute.location = availableIndex;
3816         }
3817     }
3818 
3819     ASSERT(mState.mExecutable->mAttributesTypeMask.none());
3820     ASSERT(mState.mExecutable->mAttributesMask.none());
3821 
3822     // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3823     // shader versions we're only processing active attributes to begin with.
3824     if (shaderVersion >= 300)
3825     {
3826         for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
3827              attributeIter != mState.mExecutable->getProgramInputs().end();)
3828         {
3829             if (attributeIter->active)
3830             {
3831                 ++attributeIter;
3832             }
3833             else
3834             {
3835                 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
3836             }
3837         }
3838     }
3839 
3840     for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
3841     {
3842         ASSERT(attribute.active);
3843         ASSERT(attribute.location != -1);
3844         unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3845 
3846         unsigned int location = static_cast<unsigned int>(attribute.location);
3847         for (unsigned int r = 0; r < regs; r++)
3848         {
3849             // Built-in active program inputs don't have a bound attribute.
3850             if (!attribute.isBuiltIn())
3851             {
3852                 mState.mExecutable->mActiveAttribLocationsMask.set(location);
3853                 mState.mExecutable->mMaxActiveAttribLocation =
3854                     std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
3855 
3856                 ComponentType componentType =
3857                     GLenumToComponentType(VariableComponentType(attribute.type));
3858 
3859                 SetComponentTypeMask(componentType, location,
3860                                      &mState.mExecutable->mAttributesTypeMask);
3861                 mState.mExecutable->mAttributesMask.set(location);
3862 
3863                 location++;
3864             }
3865         }
3866     }
3867 
3868     return true;
3869 }
3870 
linkInterfaceBlocks(const Caps & caps,const Version & version,bool webglCompatibility,InfoLog & infoLog,GLuint * combinedShaderStorageBlocksCount)3871 bool Program::linkInterfaceBlocks(const Caps &caps,
3872                                   const Version &version,
3873                                   bool webglCompatibility,
3874                                   InfoLog &infoLog,
3875                                   GLuint *combinedShaderStorageBlocksCount)
3876 {
3877     ASSERT(combinedShaderStorageBlocksCount);
3878 
3879     GLuint combinedUniformBlocksCount                                         = 0u;
3880     GLuint numShadersHasUniformBlocks                                         = 0u;
3881     ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
3882     InterfaceBlockMap instancelessInterfaceBlocksFields;
3883 
3884     for (ShaderType shaderType : AllShaderTypes())
3885     {
3886         Shader *shader = mState.mAttachedShaders[shaderType];
3887         if (!shader)
3888         {
3889             continue;
3890         }
3891 
3892         const auto &uniformBlocks = shader->getUniformBlocks();
3893         if (!uniformBlocks.empty())
3894         {
3895             if (!ValidateInterfaceBlocksCount(
3896                     static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks,
3897                     shaderType, sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
3898             {
3899                 return false;
3900             }
3901 
3902             allShaderUniformBlocks[shaderType] = &uniformBlocks;
3903             ++numShadersHasUniformBlocks;
3904         }
3905     }
3906 
3907     if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks))
3908     {
3909         infoLog << "The sum of the number of active uniform blocks exceeds "
3910                    "MAX_COMBINED_UNIFORM_BLOCKS ("
3911                 << caps.maxCombinedUniformBlocks << ").";
3912         return false;
3913     }
3914 
3915     if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
3916                                       webglCompatibility, &instancelessInterfaceBlocksFields))
3917     {
3918         return false;
3919     }
3920 
3921     if (version >= Version(3, 1))
3922     {
3923         *combinedShaderStorageBlocksCount                                         = 0u;
3924         GLuint numShadersHasShaderStorageBlocks                                   = 0u;
3925         ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
3926         for (ShaderType shaderType : AllShaderTypes())
3927         {
3928             Shader *shader = mState.mAttachedShaders[shaderType];
3929             if (!shader)
3930             {
3931                 continue;
3932             }
3933 
3934             const auto &shaderStorageBlocks = shader->getShaderStorageBlocks();
3935             if (!shaderStorageBlocks.empty())
3936             {
3937                 if (!ValidateInterfaceBlocksCount(
3938                         static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]),
3939                         shaderStorageBlocks, shaderType, sh::BlockType::BLOCK_BUFFER,
3940                         combinedShaderStorageBlocksCount, infoLog))
3941                 {
3942                     return false;
3943                 }
3944 
3945                 allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
3946                 ++numShadersHasShaderStorageBlocks;
3947             }
3948         }
3949 
3950         if (*combinedShaderStorageBlocksCount >
3951             static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks))
3952         {
3953             infoLog << "The sum of the number of active shader storage blocks exceeds "
3954                        "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
3955                     << caps.maxCombinedShaderStorageBlocks << ").";
3956             return false;
3957         }
3958 
3959         if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
3960                                           infoLog, webglCompatibility,
3961                                           &instancelessInterfaceBlocksFields))
3962         {
3963             return false;
3964         }
3965     }
3966 
3967     return true;
3968 }
3969 
getOutputLocationForLink(const sh::ShaderVariable & outputVariable) const3970 int Program::getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const
3971 {
3972     if (outputVariable.location != -1)
3973     {
3974         return outputVariable.location;
3975     }
3976     int apiLocation = mFragmentOutputLocations.getBinding(outputVariable);
3977     if (apiLocation != -1)
3978     {
3979         return apiLocation;
3980     }
3981     return -1;
3982 }
3983 
isOutputSecondaryForLink(const sh::ShaderVariable & outputVariable) const3984 bool Program::isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const
3985 {
3986     if (outputVariable.index != -1)
3987     {
3988         ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
3989         return (outputVariable.index == 1);
3990     }
3991     int apiIndex = mFragmentOutputIndexes.getBinding(outputVariable);
3992     if (apiIndex != -1)
3993     {
3994         // Index layout qualifier from the shader takes precedence, so the index from the API is
3995         // checked only if the index was not set in the shader. This is not specified in the EXT
3996         // spec, but is specified in desktop OpenGL specs.
3997         return (apiIndex == 1);
3998     }
3999     // EXT_blend_func_extended: Outputs get index 0 by default.
4000     return false;
4001 }
4002 
4003 namespace
4004 {
4005 
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)4006 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
4007                             unsigned int baseLocation,
4008                             unsigned int elementCount,
4009                             const std::vector<VariableLocation> &reservedLocations,
4010                             unsigned int variableIndex)
4011 {
4012     if (baseLocation + elementCount > outputLocations.size())
4013     {
4014         elementCount = baseLocation < outputLocations.size()
4015                            ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
4016                            : 0;
4017     }
4018     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4019     {
4020         const unsigned int location = baseLocation + elementIndex;
4021         if (outputLocations[location].used())
4022         {
4023             VariableLocation locationInfo(elementIndex, variableIndex);
4024             if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4025                 reservedLocations.end())
4026             {
4027                 return true;
4028             }
4029         }
4030     }
4031     return false;
4032 }
4033 
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex,sh::ShaderVariable & outputVariable)4034 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
4035                            unsigned int baseLocation,
4036                            unsigned int elementCount,
4037                            const std::vector<VariableLocation> &reservedLocations,
4038                            unsigned int variableIndex,
4039                            sh::ShaderVariable &outputVariable)
4040 {
4041     if (baseLocation + elementCount > outputLocations.size())
4042     {
4043         outputLocations.resize(baseLocation + elementCount);
4044     }
4045     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4046     {
4047         VariableLocation locationInfo(elementIndex, variableIndex);
4048         if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4049             reservedLocations.end())
4050         {
4051             outputVariable.location     = baseLocation;
4052             const unsigned int location = baseLocation + elementIndex;
4053             outputLocations[location]   = locationInfo;
4054         }
4055     }
4056 }
4057 
4058 }  // anonymous namespace
4059 
linkOutputVariables(const Caps & caps,const Extensions & extensions,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount)4060 bool Program::linkOutputVariables(const Caps &caps,
4061                                   const Extensions &extensions,
4062                                   const Version &version,
4063                                   GLuint combinedImageUniformsCount,
4064                                   GLuint combinedShaderStorageBlocksCount)
4065 {
4066     InfoLog &infoLog       = mState.mExecutable->getInfoLog();
4067     Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
4068 
4069     ASSERT(mState.mOutputVariableTypes.empty());
4070     ASSERT(mState.mActiveOutputVariables.none());
4071     ASSERT(mState.mDrawBufferTypeMask.none());
4072     ASSERT(!mState.mYUVOutput);
4073 
4074     if (!fragmentShader)
4075     {
4076         // No fragment shader, so nothing to link
4077         return true;
4078     }
4079 
4080     const std::vector<sh::ShaderVariable> &outputVariables =
4081         fragmentShader->getActiveOutputVariables();
4082 
4083     // Gather output variable types
4084     for (const sh::ShaderVariable &outputVariable : outputVariables)
4085     {
4086         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
4087             outputVariable.name != "gl_FragData")
4088         {
4089             continue;
4090         }
4091 
4092         unsigned int baseLocation =
4093             (outputVariable.location == -1 ? 0u
4094                                            : static_cast<unsigned int>(outputVariable.location));
4095 
4096         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4097         // structures, so we may use getBasicTypeElementCount().
4098         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4099         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4100         {
4101             const unsigned int location = baseLocation + elementIndex;
4102             if (location >= mState.mOutputVariableTypes.size())
4103             {
4104                 mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
4105             }
4106             ASSERT(location < mState.mActiveOutputVariables.size());
4107             mState.mActiveOutputVariables.set(location);
4108             mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
4109             ComponentType componentType =
4110                 GLenumToComponentType(mState.mOutputVariableTypes[location]);
4111             SetComponentTypeMask(componentType, location, &mState.mDrawBufferTypeMask);
4112         }
4113 
4114         if (outputVariable.yuv)
4115         {
4116             ASSERT(outputVariables.size() == 1);
4117             mState.mYUVOutput = true;
4118         }
4119     }
4120 
4121     if (version >= ES_3_1)
4122     {
4123         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
4124         // A link error will be generated if the sum of the number of active image uniforms used in
4125         // all shaders, the number of active shader storage blocks, and the number of active
4126         // fragment shader outputs exceeds the implementation-dependent value of
4127         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
4128         if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
4129                 mState.mActiveOutputVariables.count() >
4130             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
4131         {
4132             infoLog
4133                 << "The sum of the number of active image uniforms, active shader storage blocks "
4134                    "and active fragment shader outputs exceeds "
4135                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
4136                 << caps.maxCombinedShaderOutputResources << ")";
4137             return false;
4138         }
4139     }
4140 
4141     // Skip this step for GLES2 shaders.
4142     if (fragmentShader && fragmentShader->getShaderVersion() == 100)
4143         return true;
4144 
4145     mState.mExecutable->mOutputVariables = outputVariables;
4146     mState.mExecutable->mYUVOutput       = mState.mYUVOutput;
4147     // TODO(jmadill): any caps validation here?
4148 
4149     // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
4150     // output array in explicit terms.
4151     //
4152     // Assuming fragData is an output array, you can defend the position that:
4153     // P1) you must support binding "fragData" because it's specified
4154     // P2) you must support querying "fragData[x]" because it's specified
4155     // P3) you must support binding "fragData[0]" because it's a frequently used pattern
4156     //
4157     // Then you can make the leap of faith:
4158     // P4) you must support binding "fragData[x]" because you support "fragData[0]"
4159     // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
4160     //
4161     // The spec brings in the "world of arrays" when it mentions binding the arrays and the
4162     // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
4163     // must infer the only possible interpretation (?). Note again: this need of interpretation
4164     // might be completely off of what GL spec logic is.
4165     //
4166     // The other complexity is that unless you implement this feature, it's hard to understand what
4167     // should happen when the client invokes the feature. You cannot add an additional error as it
4168     // is not specified. One can ignore it, but obviously it creates the discrepancies...
4169 
4170     std::vector<VariableLocation> reservedLocations;
4171 
4172     // Process any output API bindings for arrays that don't alias to the first element.
4173     for (const auto &binding : mFragmentOutputLocations)
4174     {
4175         size_t nameLengthWithoutArrayIndex;
4176         unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
4177         if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
4178         {
4179             continue;
4180         }
4181         for (unsigned int outputVariableIndex = 0;
4182              outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4183              outputVariableIndex++)
4184         {
4185             const sh::ShaderVariable &outputVariable =
4186                 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4187             // Check that the binding corresponds to an output array and its array index fits.
4188             if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
4189                 !angle::BeginsWith(outputVariable.name, binding.first,
4190                                    nameLengthWithoutArrayIndex) ||
4191                 arrayIndex >= outputVariable.getOutermostArraySize())
4192             {
4193                 continue;
4194             }
4195 
4196             // Get the API index that corresponds to this exact binding.
4197             // This index may differ from the index used for the array's base.
4198             auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1
4199                                         ? mState.mExecutable->mSecondaryOutputLocations
4200                                         : mState.mExecutable->mOutputLocations;
4201             unsigned int location = binding.second.location;
4202             VariableLocation locationInfo(arrayIndex, outputVariableIndex);
4203             if (location >= outputLocations.size())
4204             {
4205                 outputLocations.resize(location + 1);
4206             }
4207             if (outputLocations[location].used())
4208             {
4209                 infoLog << "Location of variable " << outputVariable.name
4210                         << " conflicts with another variable.";
4211                 return false;
4212             }
4213             outputLocations[location] = locationInfo;
4214 
4215             // Note the array binding location so that it can be skipped later.
4216             reservedLocations.push_back(locationInfo);
4217         }
4218     }
4219 
4220     // Reserve locations for output variables whose location is fixed in the shader or through the
4221     // API. Otherwise, the remaining unallocated outputs will be processed later.
4222     for (unsigned int outputVariableIndex = 0;
4223          outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4224          outputVariableIndex++)
4225     {
4226         const sh::ShaderVariable &outputVariable =
4227             mState.mExecutable->getOutputVariables()[outputVariableIndex];
4228 
4229         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4230         if (outputVariable.isBuiltIn())
4231             continue;
4232 
4233         int fixedLocation = getOutputLocationForLink(outputVariable);
4234         if (fixedLocation == -1)
4235         {
4236             // Here we're only reserving locations for variables whose location is fixed.
4237             continue;
4238         }
4239         unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
4240 
4241         auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4242                                     ? mState.mExecutable->mSecondaryOutputLocations
4243                                     : mState.mExecutable->mOutputLocations;
4244 
4245         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4246         // structures, so we may use getBasicTypeElementCount().
4247         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4248         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
4249                                    outputVariableIndex))
4250         {
4251             infoLog << "Location of variable " << outputVariable.name
4252                     << " conflicts with another variable.";
4253             return false;
4254         }
4255         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4256                               outputVariableIndex,
4257                               mState.mExecutable->mOutputVariables[outputVariableIndex]);
4258     }
4259 
4260     // Here we assign locations for the output variables that don't yet have them. Note that we're
4261     // not necessarily able to fit the variables optimally, since then we might have to try
4262     // different arrangements of output arrays. Now we just assign the locations in the order that
4263     // we got the output variables. The spec isn't clear on what kind of algorithm is required for
4264     // finding locations for the output variables, so this should be acceptable at least for now.
4265     GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
4266     if (!mState.mExecutable->getSecondaryOutputLocations().empty())
4267     {
4268         // EXT_blend_func_extended: Program outputs will be validated against
4269         // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
4270         maxLocation = extensions.maxDualSourceDrawBuffers;
4271     }
4272 
4273     for (unsigned int outputVariableIndex = 0;
4274          outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4275          outputVariableIndex++)
4276     {
4277         const sh::ShaderVariable &outputVariable =
4278             mState.mExecutable->getOutputVariables()[outputVariableIndex];
4279 
4280         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4281         if (outputVariable.isBuiltIn())
4282             continue;
4283 
4284         int fixedLocation     = getOutputLocationForLink(outputVariable);
4285         auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4286                                     ? mState.mExecutable->mSecondaryOutputLocations
4287                                     : mState.mExecutable->mOutputLocations;
4288         unsigned int baseLocation = 0;
4289         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4290         if (fixedLocation != -1)
4291         {
4292             // Secondary inputs might have caused the max location to drop below what has already
4293             // been explicitly assigned locations. Check for any fixed locations above the max
4294             // that should cause linking to fail.
4295             baseLocation = static_cast<unsigned int>(fixedLocation);
4296         }
4297         else
4298         {
4299             // No fixed location, so try to fit the output in unassigned locations.
4300             // Try baseLocations starting from 0 one at a time and see if the variable fits.
4301             while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
4302                                           reservedLocations, outputVariableIndex))
4303             {
4304                 baseLocation++;
4305             }
4306             AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4307                                   outputVariableIndex,
4308                                   mState.mExecutable->mOutputVariables[outputVariableIndex]);
4309         }
4310 
4311         // Check for any elements assigned above the max location that are actually used.
4312         if (baseLocation + elementCount > maxLocation &&
4313             (baseLocation >= maxLocation ||
4314              FindUsedOutputLocation(outputLocations, maxLocation,
4315                                     baseLocation + elementCount - maxLocation, reservedLocations,
4316                                     outputVariableIndex)))
4317         {
4318             // EXT_blend_func_extended: Linking can fail:
4319             // "if the explicit binding assignments do not leave enough space for the linker to
4320             // automatically assign a location for a varying out array, which requires multiple
4321             // contiguous locations."
4322             infoLog << "Could not fit output variable into available locations: "
4323                     << outputVariable.name;
4324             return false;
4325         }
4326     }
4327 
4328     return true;
4329 }
4330 
setUniformValuesFromBindingQualifiers()4331 void Program::setUniformValuesFromBindingQualifiers()
4332 {
4333     for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
4334     {
4335         const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
4336         if (samplerUniform.binding != -1)
4337         {
4338             UniformLocation location = getUniformLocation(samplerUniform.name);
4339             ASSERT(location.value != -1);
4340             std::vector<GLint> boundTextureUnits;
4341             for (unsigned int elementIndex = 0;
4342                  elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
4343             {
4344                 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
4345             }
4346 
4347             // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
4348             // We know it's safe not to notify the Context because this is only called after link.
4349             setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
4350                           boundTextureUnits.data());
4351         }
4352     }
4353 }
4354 
initInterfaceBlockBindings()4355 void Program::initInterfaceBlockBindings()
4356 {
4357     // Set initial bindings from shader.
4358     for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
4359          blockIndex++)
4360     {
4361         InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
4362         bindUniformBlock({blockIndex}, uniformBlock.binding);
4363     }
4364 }
4365 
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)4366 void Program::updateSamplerUniform(Context *context,
4367                                    const VariableLocation &locationInfo,
4368                                    GLsizei clampedCount,
4369                                    const GLint *v)
4370 {
4371     ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
4372     GLuint samplerIndex            = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
4373     SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
4374     std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
4375 
4376     if (locationInfo.arrayIndex >= boundTextureUnits.size())
4377     {
4378         return;
4379     }
4380     GLsizei safeUniformCount = std::min(
4381         clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
4382 
4383     // Update the sampler uniforms.
4384     for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
4385     {
4386         GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
4387         GLint newTextureUnit = v[arrayIndex];
4388 
4389         if (oldTextureUnit == newTextureUnit)
4390         {
4391             continue;
4392         }
4393 
4394         boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
4395 
4396         // Update the reference counts.
4397         uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
4398         uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit];
4399         ASSERT(oldRefCount > 0);
4400         ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
4401         oldRefCount--;
4402         newRefCount++;
4403 
4404         // Check for binding type change.
4405         TextureType &newSamplerType     = mState.mExecutable->mActiveSamplerTypes[newTextureUnit];
4406         TextureType &oldSamplerType     = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit];
4407         SamplerFormat &newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit];
4408         SamplerFormat &oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit];
4409 
4410         if (newRefCount == 1)
4411         {
4412             newSamplerType   = samplerBinding.textureType;
4413             newSamplerFormat = samplerBinding.format;
4414             mState.mExecutable->mActiveSamplersMask.set(newTextureUnit);
4415             mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] =
4416                 mState.mExecutable->getUniforms()[locationInfo.index].activeShaders();
4417         }
4418         else
4419         {
4420             if (newSamplerType != samplerBinding.textureType)
4421             {
4422                 // Conflict detected. Ensure we reset it properly.
4423                 newSamplerType = TextureType::InvalidEnum;
4424             }
4425             if (newSamplerFormat != samplerBinding.format)
4426             {
4427                 newSamplerFormat = SamplerFormat::InvalidEnum;
4428             }
4429         }
4430 
4431         // Unset previously active sampler.
4432         if (oldRefCount == 0)
4433         {
4434             oldSamplerType   = TextureType::InvalidEnum;
4435             oldSamplerFormat = SamplerFormat::InvalidEnum;
4436             mState.mExecutable->mActiveSamplersMask.reset(oldTextureUnit);
4437         }
4438         else
4439         {
4440             if (oldSamplerType == TextureType::InvalidEnum ||
4441                 oldSamplerFormat == SamplerFormat::InvalidEnum)
4442             {
4443                 // Previous conflict. Check if this new change fixed the conflict.
4444                 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
4445             }
4446         }
4447 
4448         // Update the observing PPO's executable, if any.
4449         // Do this before any of the Context work, since that uses the current ProgramExecutable,
4450         // which will be the PPO's if this Program is bound to it, rather than this Program's.
4451         if (isSeparable())
4452         {
4453             onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
4454         }
4455 
4456         // Notify context.
4457         if (context)
4458         {
4459             context->onSamplerUniformChange(newTextureUnit);
4460             context->onSamplerUniformChange(oldTextureUnit);
4461         }
4462     }
4463 
4464     // Invalidate the validation cache.
4465     getExecutable().resetCachedValidateSamplersResult();
4466     // Inform any PPOs this Program may be bound to.
4467     onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
4468 }
4469 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)4470 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
4471 {
4472     mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
4473                                                        mExecutable->mSamplerBindings);
4474 }
4475 
4476 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)4477 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
4478                                    GLsizei count,
4479                                    int vectorSize,
4480                                    const T *v)
4481 {
4482     if (count == 1)
4483         return 1;
4484 
4485     const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4486 
4487     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4488     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4489     unsigned int remainingElements =
4490         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4491     GLsizei maxElementCount =
4492         static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
4493 
4494     if (count * vectorSize > maxElementCount)
4495     {
4496         return maxElementCount / vectorSize;
4497     }
4498 
4499     return count;
4500 }
4501 
4502 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)4503 GLsizei Program::clampMatrixUniformCount(UniformLocation location,
4504                                          GLsizei count,
4505                                          GLboolean transpose,
4506                                          const T *v)
4507 {
4508     const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
4509 
4510     if (!transpose)
4511     {
4512         return clampUniformCount(locationInfo, count, cols * rows, v);
4513     }
4514 
4515     const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4516 
4517     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4518     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4519     unsigned int remainingElements =
4520         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4521     return std::min(count, static_cast<GLsizei>(remainingElements));
4522 }
4523 
4524 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
4525 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
4526 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const4527 void Program::getUniformInternal(const Context *context,
4528                                  DestT *dataOut,
4529                                  UniformLocation location,
4530                                  GLenum nativeType,
4531                                  int components) const
4532 {
4533     switch (nativeType)
4534     {
4535         case GL_BOOL:
4536         {
4537             GLint tempValue[16] = {0};
4538             mProgram->getUniformiv(context, location.value, tempValue);
4539             UniformStateQueryCastLoop<GLboolean>(
4540                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4541             break;
4542         }
4543         case GL_INT:
4544         {
4545             GLint tempValue[16] = {0};
4546             mProgram->getUniformiv(context, location.value, tempValue);
4547             UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4548                                              components);
4549             break;
4550         }
4551         case GL_UNSIGNED_INT:
4552         {
4553             GLuint tempValue[16] = {0};
4554             mProgram->getUniformuiv(context, location.value, tempValue);
4555             UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4556                                               components);
4557             break;
4558         }
4559         case GL_FLOAT:
4560         {
4561             GLfloat tempValue[16] = {0};
4562             mProgram->getUniformfv(context, location.value, tempValue);
4563             UniformStateQueryCastLoop<GLfloat>(
4564                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4565             break;
4566         }
4567         default:
4568             UNREACHABLE();
4569             break;
4570     }
4571 }
4572 
syncState(const Context * context)4573 angle::Result Program::syncState(const Context *context)
4574 {
4575     if (mDirtyBits.any())
4576     {
4577         ASSERT(!mLinkingState);
4578         ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
4579         mDirtyBits.reset();
4580     }
4581 
4582     return angle::Result::Continue;
4583 }
4584 
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const4585 angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
4586 {
4587     BinaryOutputStream stream;
4588 
4589     stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
4590                       ANGLE_COMMIT_HASH_SIZE);
4591 
4592     // nullptr context is supported when computing binary length.
4593     if (context)
4594     {
4595         stream.writeInt(context->getClientVersion().major);
4596         stream.writeInt(context->getClientVersion().minor);
4597     }
4598     else
4599     {
4600         stream.writeInt(2);
4601         stream.writeInt(0);
4602     }
4603 
4604     // Must be before mExecutable->save(), since it uses the value.
4605     stream.writeBool(mState.mSeparable);
4606 
4607     mState.mExecutable->save(mState.mSeparable, &stream);
4608 
4609     const auto &computeLocalSize = mState.getComputeShaderLocalSize();
4610 
4611     stream.writeInt(computeLocalSize[0]);
4612     stream.writeInt(computeLocalSize[1]);
4613     stream.writeInt(computeLocalSize[2]);
4614 
4615     stream.writeInt(mState.mNumViews);
4616     stream.writeBool(mState.mEarlyFramentTestsOptimization);
4617     stream.writeInt(mState.mSpecConstUsageBits.bits());
4618 
4619     stream.writeInt(mState.getUniformLocations().size());
4620     for (const auto &variable : mState.getUniformLocations())
4621     {
4622         stream.writeInt(variable.arrayIndex);
4623         stream.writeIntOrNegOne(variable.index);
4624         stream.writeBool(variable.ignored);
4625     }
4626 
4627     stream.writeInt(mState.getBufferVariables().size());
4628     for (const BufferVariable &bufferVariable : mState.getBufferVariables())
4629     {
4630         WriteBufferVariable(&stream, bufferVariable);
4631     }
4632 
4633     // Warn the app layer if saving a binary with unsupported transform feedback.
4634     if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
4635         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4636     {
4637         WARN() << "Saving program binary with transform feedback, which is not supported on this "
4638                   "driver.";
4639     }
4640 
4641     stream.writeInt(mState.mOutputVariableTypes.size());
4642     for (const auto &outputVariableType : mState.mOutputVariableTypes)
4643     {
4644         stream.writeInt(outputVariableType);
4645     }
4646 
4647     static_assert(
4648         IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4649         "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
4650     stream.writeInt(static_cast<int>(mState.mDrawBufferTypeMask.to_ulong()));
4651     stream.writeInt(static_cast<int>(mState.mActiveOutputVariables.to_ulong()));
4652 
4653     stream.writeBool(mState.isYUVOutput());
4654 
4655     stream.writeInt(mState.getAtomicCounterUniformRange().low());
4656     stream.writeInt(mState.getAtomicCounterUniformRange().high());
4657 
4658     mProgram->save(context, &stream);
4659 
4660     ASSERT(binaryOut);
4661     if (!binaryOut->resize(stream.length()))
4662     {
4663         WARN() << "Failed to allocate enough memory to serialize a program. (" << stream.length()
4664                << " bytes )";
4665         return angle::Result::Incomplete;
4666     }
4667     memcpy(binaryOut->data(), stream.data(), stream.length());
4668     return angle::Result::Continue;
4669 }
4670 
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)4671 angle::Result Program::deserialize(const Context *context,
4672                                    BinaryInputStream &stream,
4673                                    InfoLog &infoLog)
4674 {
4675     unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
4676     stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
4677     if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
4678         0)
4679     {
4680         infoLog << "Invalid program binary version.";
4681         return angle::Result::Stop;
4682     }
4683 
4684     int majorVersion = stream.readInt<int>();
4685     int minorVersion = stream.readInt<int>();
4686     if (majorVersion != context->getClientMajorVersion() ||
4687         minorVersion != context->getClientMinorVersion())
4688     {
4689         infoLog << "Cannot load program binaries across different ES context versions.";
4690         return angle::Result::Stop;
4691     }
4692 
4693     // Must be before mExecutable->load(), since it uses the value.
4694     mState.mSeparable = stream.readBool();
4695 
4696     mState.mExecutable->load(mState.mSeparable, &stream);
4697 
4698     mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
4699     mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
4700     mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
4701 
4702     mState.mNumViews                      = stream.readInt<int>();
4703     mState.mEarlyFramentTestsOptimization = stream.readBool();
4704     mState.mSpecConstUsageBits            = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
4705 
4706     const size_t uniformIndexCount = stream.readInt<size_t>();
4707     ASSERT(mState.mUniformLocations.empty());
4708     for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex)
4709     {
4710         VariableLocation variable;
4711         stream.readInt(&variable.arrayIndex);
4712         stream.readInt(&variable.index);
4713         stream.readBool(&variable.ignored);
4714 
4715         mState.mUniformLocations.push_back(variable);
4716     }
4717 
4718     size_t bufferVariableCount = stream.readInt<size_t>();
4719     ASSERT(mState.mBufferVariables.empty());
4720     for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
4721     {
4722         BufferVariable bufferVariable;
4723         LoadBufferVariable(&stream, &bufferVariable);
4724         mState.mBufferVariables.push_back(bufferVariable);
4725     }
4726 
4727     size_t outputTypeCount = stream.readInt<size_t>();
4728     for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
4729     {
4730         mState.mOutputVariableTypes.push_back(stream.readInt<GLenum>());
4731     }
4732 
4733     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4734                   "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
4735                   "into 32 bits each");
4736     mState.mDrawBufferTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4737     mState.mActiveOutputVariables =
4738         gl::DrawBufferMask(stream.readInt<gl::DrawBufferMask::value_type>());
4739 
4740     stream.readBool(&mState.mYUVOutput);
4741 
4742     unsigned int atomicCounterRangeLow  = stream.readInt<unsigned int>();
4743     unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
4744     mState.mAtomicCounterUniformRange   = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
4745 
4746     static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
4747                   "Too many shader types");
4748 
4749     // Reject programs that use transform feedback varyings if the hardware cannot support them.
4750     if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
4751         context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4752     {
4753         infoLog << "Current driver does not support transform feedback in binary programs.";
4754         return angle::Result::Stop;
4755     }
4756 
4757     if (!mState.mAttachedShaders[ShaderType::Compute])
4758     {
4759         mState.mExecutable->updateTransformFeedbackStrides();
4760     }
4761 
4762     postResolveLink(context);
4763     mState.mExecutable->updateCanDrawWith();
4764 
4765     return angle::Result::Continue;
4766 }
4767 
postResolveLink(const gl::Context * context)4768 void Program::postResolveLink(const gl::Context *context)
4769 {
4770     mState.updateActiveSamplers();
4771     mState.mExecutable->mActiveImageShaderBits.fill({});
4772     mState.mExecutable->updateActiveImages(getExecutable());
4773 
4774     setUniformValuesFromBindingQualifiers();
4775 
4776     if (context->getExtensions().multiDraw)
4777     {
4778         mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value;
4779     }
4780 
4781     if (context->getExtensions().baseVertexBaseInstance)
4782     {
4783         mState.mBaseVertexLocation   = getUniformLocation("gl_BaseVertex").value;
4784         mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value;
4785     }
4786 }
4787 
4788 // HasAttachedShaders implementation.
getTransformFeedbackStage() const4789 ShaderType HasAttachedShaders::getTransformFeedbackStage() const
4790 {
4791     if (getAttachedShader(ShaderType::Geometry))
4792     {
4793         return ShaderType::Geometry;
4794     }
4795     if (getAttachedShader(ShaderType::TessEvaluation))
4796     {
4797         return ShaderType::TessEvaluation;
4798     }
4799     return ShaderType::Vertex;
4800 }
4801 }  // namespace gl
4802