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