xref: /aosp_15_r20/external/angle/src/libANGLE/ProgramExecutable.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2020 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 // ProgramExecutable.cpp: Collects the interfaces common to both Programs and
7 // ProgramPipelines in order to execute/draw with either.
8 
9 #include "libANGLE/ProgramExecutable.h"
10 
11 #include "common/string_utils.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Program.h"
14 #include "libANGLE/Shader.h"
15 #include "libANGLE/queryconversions.h"
16 #include "libANGLE/renderer/GLImplFactory.h"
17 #include "libANGLE/renderer/ProgramExecutableImpl.h"
18 #include "libANGLE/renderer/ProgramImpl.h"
19 
20 namespace gl
21 {
22 namespace
23 {
24 ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
25 // A placeholder struct just to ensure sh::BlockMemberInfo is tightly packed since vulkan backend
26 // uses it and memcpy the entire vector which requires it tightly packed to make msan happy.
27 struct BlockMemberInfoPaddingTest
28 {
29     sh::BlockMemberInfo blockMemberInfo;
30 };
31 ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
32 
IncludeSameArrayElement(const std::set<std::string> & nameSet,const std::string & name)33 bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
34 {
35     std::vector<unsigned int> subscripts;
36     std::string baseName = ParseResourceName(name, &subscripts);
37     for (const std::string &nameInSet : nameSet)
38     {
39         std::vector<unsigned int> arrayIndices;
40         std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
41         if (baseName == arrayName &&
42             (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
43         {
44             return true;
45         }
46     }
47     return false;
48 }
49 
50 // Find the matching varying or field by name.
FindOutputVaryingOrField(const ProgramMergedVaryings & varyings,ShaderType stage,const std::string & name)51 const sh::ShaderVariable *FindOutputVaryingOrField(const ProgramMergedVaryings &varyings,
52                                                    ShaderType stage,
53                                                    const std::string &name)
54 {
55     const sh::ShaderVariable *var = nullptr;
56     for (const ProgramVaryingRef &ref : varyings)
57     {
58         if (ref.frontShaderStage != stage)
59         {
60             continue;
61         }
62 
63         const sh::ShaderVariable *varying = ref.get(stage);
64         if (varying->name == name)
65         {
66             var = varying;
67             break;
68         }
69         GLuint fieldIndex = 0;
70         var               = varying->findField(name, &fieldIndex);
71         if (var != nullptr)
72         {
73             break;
74         }
75     }
76     return var;
77 }
78 
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)79 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
80                             unsigned int baseLocation,
81                             unsigned int elementCount,
82                             const std::vector<VariableLocation> &reservedLocations,
83                             unsigned int variableIndex)
84 {
85     if (baseLocation + elementCount > outputLocations.size())
86     {
87         elementCount = baseLocation < outputLocations.size()
88                            ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
89                            : 0;
90     }
91     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
92     {
93         const unsigned int location = baseLocation + elementIndex;
94         if (outputLocations[location].used())
95         {
96             VariableLocation locationInfo(elementIndex, variableIndex);
97             if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
98                 reservedLocations.end())
99             {
100                 return true;
101             }
102         }
103     }
104     return false;
105 }
106 
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex,bool locationAssignedByApi,ProgramOutput & outputVariable)107 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
108                            unsigned int baseLocation,
109                            unsigned int elementCount,
110                            const std::vector<VariableLocation> &reservedLocations,
111                            unsigned int variableIndex,
112                            bool locationAssignedByApi,
113                            ProgramOutput &outputVariable)
114 {
115     if (baseLocation + elementCount > outputLocations.size())
116     {
117         outputLocations.resize(baseLocation + elementCount);
118     }
119     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
120     {
121         VariableLocation locationInfo(elementIndex, variableIndex);
122         if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
123             reservedLocations.end())
124         {
125             outputVariable.pod.location = baseLocation;
126             const unsigned int location = baseLocation + elementIndex;
127             outputLocations[location]   = locationInfo;
128         }
129     }
130     outputVariable.pod.hasApiAssignedLocation = locationAssignedByApi;
131 }
132 
GetOutputLocationForLink(const ProgramAliasedBindings & fragmentOutputLocations,const ProgramOutput & outputVariable)133 int GetOutputLocationForLink(const ProgramAliasedBindings &fragmentOutputLocations,
134                              const ProgramOutput &outputVariable)
135 {
136     if (outputVariable.pod.location != -1)
137     {
138         return outputVariable.pod.location;
139     }
140     int apiLocation = fragmentOutputLocations.getBinding(outputVariable);
141     if (apiLocation != -1)
142     {
143         return apiLocation;
144     }
145     return -1;
146 }
147 
AssignOutputIndex(const ProgramAliasedBindings & fragmentOutputIndexes,ProgramOutput & outputVariable)148 void AssignOutputIndex(const ProgramAliasedBindings &fragmentOutputIndexes,
149                        ProgramOutput &outputVariable)
150 {
151     if (outputVariable.pod.hasShaderAssignedLocation)
152     {
153         // Already assigned through a layout qualifier
154         ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1);
155         return;
156     }
157 
158     int apiIndex = fragmentOutputIndexes.getBinding(outputVariable);
159     if (apiIndex != -1)
160     {
161         // Index layout qualifier from the shader takes precedence, so the index from the API is
162         // checked only if the index was not set in the shader. This is not specified in the EXT
163         // spec, but is specified in desktop OpenGL specs.
164         ASSERT(apiIndex == 0 || apiIndex == 1);
165         outputVariable.pod.index = apiIndex;
166         return;
167     }
168 
169     // EXT_blend_func_extended: Outputs get index 0 by default.
170     outputVariable.pod.index = 0;
171 }
172 
AddUniforms(const ShaderMap<SharedProgramExecutable> & executables,ShaderBitSet activeShaders,std::vector<LinkedUniform> * outputUniforms,std::vector<std::string> * outputUniformNames,std::vector<std::string> * outputUniformMappedNames,const std::function<RangeUI (const ProgramExecutable &)> & getRange)173 RangeUI AddUniforms(const ShaderMap<SharedProgramExecutable> &executables,
174                     ShaderBitSet activeShaders,
175                     std::vector<LinkedUniform> *outputUniforms,
176                     std::vector<std::string> *outputUniformNames,
177                     std::vector<std::string> *outputUniformMappedNames,
178                     const std::function<RangeUI(const ProgramExecutable &)> &getRange)
179 {
180     unsigned int startRange = static_cast<unsigned int>(outputUniforms->size());
181     for (ShaderType shaderType : activeShaders)
182     {
183         const ProgramExecutable &executable = *executables[shaderType];
184         const RangeUI uniformRange          = getRange(executable);
185 
186         const std::vector<LinkedUniform> &programUniforms = executable.getUniforms();
187         outputUniforms->insert(outputUniforms->end(), programUniforms.begin() + uniformRange.low(),
188                                programUniforms.begin() + uniformRange.high());
189 
190         const std::vector<std::string> &uniformNames = executable.getUniformNames();
191         outputUniformNames->insert(outputUniformNames->end(),
192                                    uniformNames.begin() + uniformRange.low(),
193                                    uniformNames.begin() + uniformRange.high());
194 
195         const std::vector<std::string> &uniformMappedNames = executable.getUniformMappedNames();
196         outputUniformMappedNames->insert(outputUniformMappedNames->end(),
197                                          uniformMappedNames.begin() + uniformRange.low(),
198                                          uniformMappedNames.begin() + uniformRange.high());
199     }
200     return RangeUI(startRange, static_cast<unsigned int>(outputUniforms->size()));
201 }
202 
203 template <typename BlockT>
AppendActiveBlocks(ShaderType shaderType,const std::vector<BlockT> & blocksIn,std::vector<BlockT> & blocksOut,ProgramUniformBlockArray<GLuint> * ppoBlockMap)204 void AppendActiveBlocks(ShaderType shaderType,
205                         const std::vector<BlockT> &blocksIn,
206                         std::vector<BlockT> &blocksOut,
207                         ProgramUniformBlockArray<GLuint> *ppoBlockMap)
208 {
209     for (size_t index = 0; index < blocksIn.size(); ++index)
210     {
211         const BlockT &block = blocksIn[index];
212         if (block.isActive(shaderType))
213         {
214             // Have a way for the PPO to know how to map the program's UBO index into its own UBO
215             // array.  This is used to propagate changes to the program's UBOs to the PPO's UBO
216             // list.
217             if (ppoBlockMap != nullptr)
218             {
219                 (*ppoBlockMap)[static_cast<uint32_t>(index)] =
220                     static_cast<uint32_t>(blocksOut.size());
221             }
222 
223             blocksOut.push_back(block);
224         }
225     }
226 }
227 
SaveProgramInputs(BinaryOutputStream * stream,const std::vector<ProgramInput> & programInputs)228 void SaveProgramInputs(BinaryOutputStream *stream, const std::vector<ProgramInput> &programInputs)
229 {
230     stream->writeInt(programInputs.size());
231     for (const ProgramInput &attrib : programInputs)
232     {
233         stream->writeString(attrib.name);
234         stream->writeString(attrib.mappedName);
235         stream->writeStruct(attrib.pod);
236     }
237 }
LoadProgramInputs(BinaryInputStream * stream,std::vector<ProgramInput> * programInputs)238 void LoadProgramInputs(BinaryInputStream *stream, std::vector<ProgramInput> *programInputs)
239 {
240     size_t attribCount = stream->readInt<size_t>();
241     ASSERT(programInputs->empty());
242     if (attribCount > 0)
243     {
244         programInputs->resize(attribCount);
245         for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
246         {
247             ProgramInput &attrib = (*programInputs)[attribIndex];
248             stream->readString(&attrib.name);
249             stream->readString(&attrib.mappedName);
250             stream->readStruct(&attrib.pod);
251         }
252     }
253 }
254 
SaveUniforms(BinaryOutputStream * stream,const std::vector<LinkedUniform> & uniforms,const std::vector<std::string> & uniformNames,const std::vector<std::string> & uniformMappedNames,const std::vector<VariableLocation> & uniformLocations)255 void SaveUniforms(BinaryOutputStream *stream,
256                   const std::vector<LinkedUniform> &uniforms,
257                   const std::vector<std::string> &uniformNames,
258                   const std::vector<std::string> &uniformMappedNames,
259                   const std::vector<VariableLocation> &uniformLocations)
260 {
261     stream->writeVector(uniforms);
262     ASSERT(uniforms.size() == uniformNames.size());
263     ASSERT(uniforms.size() == uniformMappedNames.size());
264     for (const std::string &name : uniformNames)
265     {
266         stream->writeString(name);
267     }
268     for (const std::string &name : uniformMappedNames)
269     {
270         stream->writeString(name);
271     }
272     stream->writeVector(uniformLocations);
273 }
LoadUniforms(BinaryInputStream * stream,std::vector<LinkedUniform> * uniforms,std::vector<std::string> * uniformNames,std::vector<std::string> * uniformMappedNames,std::vector<VariableLocation> * uniformLocations)274 void LoadUniforms(BinaryInputStream *stream,
275                   std::vector<LinkedUniform> *uniforms,
276                   std::vector<std::string> *uniformNames,
277                   std::vector<std::string> *uniformMappedNames,
278                   std::vector<VariableLocation> *uniformLocations)
279 {
280     stream->readVector(uniforms);
281     if (!uniforms->empty())
282     {
283         uniformNames->resize(uniforms->size());
284         for (size_t uniformIndex = 0; uniformIndex < uniforms->size(); ++uniformIndex)
285         {
286             stream->readString(&(*uniformNames)[uniformIndex]);
287         }
288         uniformMappedNames->resize(uniforms->size());
289         for (size_t uniformIndex = 0; uniformIndex < uniforms->size(); ++uniformIndex)
290         {
291             stream->readString(&(*uniformMappedNames)[uniformIndex]);
292         }
293     }
294     stream->readVector(uniformLocations);
295 }
296 
SaveSamplerBindings(BinaryOutputStream * stream,const std::vector<SamplerBinding> & samplerBindings,const std::vector<GLuint> & samplerBoundTextureUnits)297 void SaveSamplerBindings(BinaryOutputStream *stream,
298                          const std::vector<SamplerBinding> &samplerBindings,
299                          const std::vector<GLuint> &samplerBoundTextureUnits)
300 {
301     stream->writeVector(samplerBindings);
302     stream->writeInt(samplerBoundTextureUnits.size());
303 }
LoadSamplerBindings(BinaryInputStream * stream,std::vector<SamplerBinding> * samplerBindings,std::vector<GLuint> * samplerBoundTextureUnits)304 void LoadSamplerBindings(BinaryInputStream *stream,
305                          std::vector<SamplerBinding> *samplerBindings,
306                          std::vector<GLuint> *samplerBoundTextureUnits)
307 {
308     stream->readVector(samplerBindings);
309     ASSERT(samplerBoundTextureUnits->empty());
310     size_t boundTextureUnitsCount = stream->readInt<size_t>();
311     samplerBoundTextureUnits->resize(boundTextureUnitsCount, 0);
312 }
313 
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)314 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
315 {
316     stream->writeString(var.name);
317     stream->writeString(var.mappedName);
318     stream->writeStruct(var.pod);
319 }
320 
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)321 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
322 {
323     var->name       = stream->readString();
324     var->mappedName = stream->readString();
325     stream->readStruct(&var->pod);
326 }
327 
WriteAtomicCounterBuffer(BinaryOutputStream * stream,const AtomicCounterBuffer & var)328 void WriteAtomicCounterBuffer(BinaryOutputStream *stream, const AtomicCounterBuffer &var)
329 {
330     stream->writeVector(var.memberIndexes);
331     stream->writeStruct(var.pod);
332 }
333 
LoadAtomicCounterBuffer(BinaryInputStream * stream,AtomicCounterBuffer * var)334 void LoadAtomicCounterBuffer(BinaryInputStream *stream, AtomicCounterBuffer *var)
335 {
336     stream->readVector(&var->memberIndexes);
337     stream->readStruct(&var->pod);
338 }
339 
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)340 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
341 {
342     stream->writeString(block.name);
343     stream->writeString(block.mappedName);
344     stream->writeVector(block.memberIndexes);
345     stream->writeStruct(block.pod);
346 }
347 
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)348 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
349 {
350     block->name       = stream->readString();
351     block->mappedName = stream->readString();
352     stream->readVector(&block->memberIndexes);
353     stream->readStruct(&block->pod);
354 }
355 
CopyStringToBuffer(GLchar * buffer,const std::string & string,GLsizei bufSize,GLsizei * lengthOut)356 void CopyStringToBuffer(GLchar *buffer,
357                         const std::string &string,
358                         GLsizei bufSize,
359                         GLsizei *lengthOut)
360 {
361     ASSERT(bufSize > 0);
362     size_t length = std::min<size_t>(bufSize - 1, string.length());
363     memcpy(buffer, string.c_str(), length);
364     buffer[length] = '\0';
365 
366     if (lengthOut)
367     {
368         *lengthOut = static_cast<GLsizei>(length);
369     }
370 }
371 
372 template <typename T>
GetResourceMaxNameSize(const T & resource,GLint max)373 GLuint GetResourceMaxNameSize(const T &resource, GLint max)
374 {
375     if (resource.isArray())
376     {
377         return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
378     }
379     else
380     {
381         return std::max(max, clampCast<GLint>((resource.name).size()));
382     }
383 }
384 
385 template <typename T>
GetResourceLocation(const GLchar * name,const T & variable,GLint location)386 GLuint GetResourceLocation(const GLchar *name, const T &variable, GLint location)
387 {
388     if (variable.isBuiltIn())
389     {
390         return GL_INVALID_INDEX;
391     }
392 
393     if (variable.isArray())
394     {
395         size_t nameLengthWithoutArrayIndexOut;
396         size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
397         // The 'name' string may not contain the array notation "[0]"
398         if (arrayIndex != GL_INVALID_INDEX)
399         {
400             location += arrayIndex;
401         }
402     }
403 
404     return location;
405 }
406 
407 template <typename T>
GetResourceName(const T & resource)408 const std::string GetResourceName(const T &resource)
409 {
410     std::string resourceName = resource.name;
411 
412     if (resource.isArray())
413     {
414         resourceName += "[0]";
415     }
416 
417     return resourceName;
418 }
419 
GetVariableLocation(const std::vector<gl::ProgramOutput> & list,const std::vector<VariableLocation> & locationList,const std::string & name)420 GLint GetVariableLocation(const std::vector<gl::ProgramOutput> &list,
421                           const std::vector<VariableLocation> &locationList,
422                           const std::string &name)
423 {
424     size_t nameLengthWithoutArrayIndex;
425     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
426 
427     for (size_t location = 0u; location < locationList.size(); ++location)
428     {
429         const VariableLocation &variableLocation = locationList[location];
430         if (!variableLocation.used())
431         {
432             continue;
433         }
434 
435         const gl::ProgramOutput &variable = list[variableLocation.index];
436 
437         // Array output variables may be bound out of order, so we need to ensure we only pick the
438         // first element if given the base name.
439         if ((variable.name == name) && (variableLocation.arrayIndex == 0))
440         {
441             return static_cast<GLint>(location);
442         }
443         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
444             angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
445         {
446             return static_cast<GLint>(location);
447         }
448     }
449 
450     return -1;
451 }
452 
453 template <typename VarT>
GetResourceIndexFromName(const std::vector<VarT> & list,const std::string & name)454 GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
455 {
456     std::string nameAsArrayName = name + "[0]";
457     for (size_t index = 0; index < list.size(); index++)
458     {
459         const VarT &resource = list[index];
460         if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
461         {
462             return static_cast<GLuint>(index);
463         }
464     }
465 
466     return GL_INVALID_INDEX;
467 }
468 
GetUniformIndexFromName(const std::vector<LinkedUniform> & uniformList,const std::vector<std::string> & nameList,const std::string & name)469 GLuint GetUniformIndexFromName(const std::vector<LinkedUniform> &uniformList,
470                                const std::vector<std::string> &nameList,
471                                const std::string &name)
472 {
473     std::string nameAsArrayName = name + "[0]";
474     for (size_t index = 0; index < nameList.size(); index++)
475     {
476         const std::string &uniformName = nameList[index];
477         if (uniformName == name || (uniformList[index].isArray() && uniformName == nameAsArrayName))
478         {
479             return static_cast<GLuint>(index);
480         }
481     }
482 
483     return GL_INVALID_INDEX;
484 }
485 
GetUniformLocation(const std::vector<LinkedUniform> & uniformList,const std::vector<std::string> & nameList,const std::vector<VariableLocation> & locationList,const std::string & name)486 GLint GetUniformLocation(const std::vector<LinkedUniform> &uniformList,
487                          const std::vector<std::string> &nameList,
488                          const std::vector<VariableLocation> &locationList,
489                          const std::string &name)
490 {
491     size_t nameLengthWithoutArrayIndex;
492     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
493 
494     for (size_t location = 0u; location < locationList.size(); ++location)
495     {
496         const VariableLocation &variableLocation = locationList[location];
497         if (!variableLocation.used())
498         {
499             continue;
500         }
501 
502         const LinkedUniform &variable  = uniformList[variableLocation.index];
503         const std::string &uniformName = nameList[variableLocation.index];
504 
505         // Array output variables may be bound out of order, so we need to ensure we only pick the
506         // first element if given the base name. Uniforms don't allow this behavior and some code
507         // seemingly depends on the opposite behavior, so only enable it for output variables.
508         if (angle::BeginsWith(uniformName, name) && (variableLocation.arrayIndex == 0))
509         {
510             if (name.length() == uniformName.length())
511             {
512                 ASSERT(name == uniformName);
513                 // GLES 3.1 November 2016 page 87.
514                 // The string exactly matches the name of the active variable.
515                 return static_cast<GLint>(location);
516             }
517             if (name.length() + 3u == uniformName.length() && variable.isArray())
518             {
519                 ASSERT(name + "[0]" == uniformName);
520                 // The string identifies the base name of an active array, where the string would
521                 // exactly match the name of the variable if the suffix "[0]" were appended to the
522                 // string.
523                 return static_cast<GLint>(location);
524             }
525         }
526         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
527             nameLengthWithoutArrayIndex + 3u == uniformName.length() &&
528             angle::BeginsWith(uniformName, name, nameLengthWithoutArrayIndex))
529         {
530             ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == uniformName);
531             // The string identifies an active element of the array, where the string ends with the
532             // concatenation of the "[" character, an integer (with no "+" sign, extra leading
533             // zeroes, or whitespace) identifying an array element, and the "]" character, the
534             // integer is less than the number of active elements of the array variable, and where
535             // the string would exactly match the enumerated name of the array if the decimal
536             // integer were replaced with zero.
537             return static_cast<GLint>(location);
538         }
539     }
540 
541     return -1;
542 }
543 
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)544 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
545 {
546     std::vector<unsigned int> subscripts;
547     std::string baseName = ParseResourceName(name, &subscripts);
548 
549     unsigned int numBlocks = static_cast<unsigned int>(list.size());
550     for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
551     {
552         const auto &block = list[blockIndex];
553         if (block.name == baseName)
554         {
555             const bool arrayElementZero =
556                 (subscripts.empty() && (!block.pod.isArray || block.pod.arrayElement == 0));
557             const bool arrayElementMatches =
558                 (subscripts.size() == 1 && subscripts[0] == block.pod.arrayElement);
559             if (arrayElementMatches || arrayElementZero)
560             {
561                 return blockIndex;
562             }
563         }
564     }
565 
566     return GL_INVALID_INDEX;
567 }
568 
GetInterfaceBlockName(const UniformBlockIndex index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)569 void GetInterfaceBlockName(const UniformBlockIndex index,
570                            const std::vector<InterfaceBlock> &list,
571                            GLsizei bufSize,
572                            GLsizei *length,
573                            GLchar *name)
574 {
575     ASSERT(index.value < list.size());
576 
577     const auto &block = list[index.value];
578 
579     if (bufSize > 0)
580     {
581         std::string blockName = block.name;
582 
583         if (block.pod.isArray)
584         {
585             blockName += ArrayString(block.pod.arrayElement);
586         }
587         CopyStringToBuffer(name, blockName, bufSize, length);
588     }
589 }
590 
591 template <typename T>
GetActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources)592 GLint GetActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources)
593 {
594     int maxLength = 0;
595 
596     for (const T &resource : resources)
597     {
598         if (!resource.name.empty())
599         {
600             int length = static_cast<int>(resource.nameWithArrayIndex().length());
601             maxLength  = std::max(length + 1, maxLength);
602         }
603     }
604 
605     return maxLength;
606 }
607 
608 // This simplified cast function doesn't need to worry about advanced concepts like
609 // depth range values, or casting to bool.
610 template <typename DestT, typename SrcT>
611 DestT UniformStateQueryCast(SrcT value);
612 
613 // From-Float-To-Integer Casts
614 template <>
UniformStateQueryCast(GLfloat value)615 GLint UniformStateQueryCast(GLfloat value)
616 {
617     return clampCast<GLint>(roundf(value));
618 }
619 
620 template <>
UniformStateQueryCast(GLfloat value)621 GLuint UniformStateQueryCast(GLfloat value)
622 {
623     return clampCast<GLuint>(roundf(value));
624 }
625 
626 // From-Integer-to-Integer Casts
627 template <>
UniformStateQueryCast(GLuint value)628 GLint UniformStateQueryCast(GLuint value)
629 {
630     return clampCast<GLint>(value);
631 }
632 
633 template <>
UniformStateQueryCast(GLint value)634 GLuint UniformStateQueryCast(GLint value)
635 {
636     return clampCast<GLuint>(value);
637 }
638 
639 // From-Boolean-to-Anything Casts
640 template <>
UniformStateQueryCast(GLboolean value)641 GLfloat UniformStateQueryCast(GLboolean value)
642 {
643     return (ConvertToBool(value) ? 1.0f : 0.0f);
644 }
645 
646 template <>
UniformStateQueryCast(GLboolean value)647 GLint UniformStateQueryCast(GLboolean value)
648 {
649     return (ConvertToBool(value) ? 1 : 0);
650 }
651 
652 template <>
UniformStateQueryCast(GLboolean value)653 GLuint UniformStateQueryCast(GLboolean value)
654 {
655     return (ConvertToBool(value) ? 1u : 0u);
656 }
657 
658 // Default to static_cast
659 template <typename DestT, typename SrcT>
UniformStateQueryCast(SrcT value)660 DestT UniformStateQueryCast(SrcT value)
661 {
662     return static_cast<DestT>(value);
663 }
664 
665 template <typename SrcT, typename DestT>
UniformStateQueryCastLoop(DestT * dataOut,const uint8_t * srcPointer,int components)666 void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
667 {
668     for (int comp = 0; comp < components; ++comp)
669     {
670         // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
671         // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
672         size_t offset               = comp * 4;
673         const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
674         dataOut[comp]               = UniformStateQueryCast<DestT>(*typedSrcPointer);
675     }
676 }
677 }  // anonymous namespace
678 
679 // ImageBinding implementation.
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)680 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
681     : textureType(textureTypeIn)
682 {
683     for (size_t index = 0; index < count; ++index)
684     {
685         boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
686     }
687 }
688 
689 // ProgramInput implementation.
ProgramInput(const sh::ShaderVariable & var)690 ProgramInput::ProgramInput(const sh::ShaderVariable &var)
691 {
692     ASSERT(!var.isStruct());
693 
694     name       = var.name;
695     mappedName = var.mappedName;
696 
697     SetBitField(pod.type, var.type);
698     pod.location = var.hasImplicitLocation ? -1 : var.location;
699     SetBitField(pod.interpolation, var.interpolation);
700     pod.flagBitsAsUByte              = 0;
701     pod.flagBits.active              = var.active;
702     pod.flagBits.isPatch             = var.isPatch;
703     pod.flagBits.hasImplicitLocation = var.hasImplicitLocation;
704     pod.flagBits.isArray             = var.isArray();
705     pod.flagBits.isBuiltIn           = IsBuiltInName(var.name);
706     SetBitField(pod.basicTypeElementCount, var.getBasicTypeElementCount());
707     pod.id = var.id;
708     SetBitField(pod.arraySizeProduct, var.getArraySizeProduct());
709 }
710 
711 // ProgramOutput implementation.
ProgramOutput(const sh::ShaderVariable & var)712 ProgramOutput::ProgramOutput(const sh::ShaderVariable &var)
713 {
714     name       = var.name;
715     mappedName = var.mappedName;
716 
717     pod.type     = var.type;
718     pod.location = var.location;
719     pod.index    = var.index;
720     pod.id       = var.id;
721 
722     SetBitField(pod.outermostArraySize, var.getOutermostArraySize());
723     SetBitField(pod.basicTypeElementCount, var.getBasicTypeElementCount());
724 
725     SetBitField(pod.isPatch, var.isPatch);
726     SetBitField(pod.yuv, var.yuv);
727     SetBitField(pod.isBuiltIn, IsBuiltInName(var.name));
728     SetBitField(pod.isArray, var.isArray());
729     SetBitField(pod.hasImplicitLocation, var.hasImplicitLocation);
730     SetBitField(pod.hasShaderAssignedLocation, var.location != -1);
731     SetBitField(pod.hasApiAssignedLocation, false);
732     SetBitField(pod.pad, 0);
733 
734     if (pod.hasShaderAssignedLocation && pod.index == -1)
735     {
736         // Location was assigned but index was not. Equivalent to setting index to 0.
737         pod.index = 0;
738     }
739 }
740 
741 // ProgramExecutable implementation.
ProgramExecutable(rx::GLImplFactory * factory,InfoLog * infoLog)742 ProgramExecutable::ProgramExecutable(rx::GLImplFactory *factory, InfoLog *infoLog)
743     : mImplementation(factory->createProgramExecutable(this)),
744       mInfoLog(infoLog),
745       mCachedBaseVertex(0),
746       mCachedBaseInstance(0),
747       mIsPPO(false)
748 {
749     memset(&mPod, 0, sizeof(mPod));
750     reset();
751 }
752 
~ProgramExecutable()753 ProgramExecutable::~ProgramExecutable()
754 {
755     ASSERT(mPostLinkSubTasks.empty());
756     ASSERT(mPostLinkSubTaskWaitableEvents.empty());
757     ASSERT(mImplementation == nullptr);
758 }
759 
destroy(const Context * context)760 void ProgramExecutable::destroy(const Context *context)
761 {
762     ASSERT(mImplementation != nullptr);
763 
764     for (SharedProgramExecutable &executable : mPPOProgramExecutables)
765     {
766         if (executable)
767         {
768             UninstallExecutable(context, &executable);
769         }
770     }
771 
772     mImplementation->destroy(context);
773     SafeDelete(mImplementation);
774 }
775 
reset()776 void ProgramExecutable::reset()
777 {
778     mPod.activeAttribLocationsMask.reset();
779     mPod.attributesTypeMask.reset();
780     mPod.attributesMask.reset();
781     mPod.maxActiveAttribLocation = 0;
782     mPod.activeOutputVariablesMask.reset();
783     mPod.activeSecondaryOutputVariablesMask.reset();
784 
785     mPod.defaultUniformRange       = RangeUI(0, 0);
786     mPod.samplerUniformRange       = RangeUI(0, 0);
787     mPod.imageUniformRange         = RangeUI(0, 0);
788     mPod.atomicCounterUniformRange = RangeUI(0, 0);
789 
790     mPod.fragmentInoutIndices.reset();
791 
792     mPod.hasClipDistance         = false;
793     mPod.hasDiscard              = false;
794     mPod.enablesPerSampleShading = false;
795     mPod.hasYUVOutput            = false;
796     mPod.hasDepthInputAttachment   = false;
797     mPod.hasStencilInputAttachment = false;
798 
799     mPod.advancedBlendEquations.reset();
800 
801     mPod.geometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
802     mPod.geometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
803     mPod.geometryShaderInvocations         = 1;
804     mPod.geometryShaderMaxVertices         = 0;
805 
806     mPod.transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS;
807 
808     mPod.numViews = -1;
809 
810     mPod.drawIDLocation = -1;
811 
812     mPod.baseVertexLocation   = -1;
813     mPod.baseInstanceLocation = -1;
814 
815     mPod.tessControlShaderVertices = 0;
816     mPod.tessGenMode               = GL_NONE;
817     mPod.tessGenSpacing            = GL_NONE;
818     mPod.tessGenVertexOrder        = GL_NONE;
819     mPod.tessGenPointMode          = GL_NONE;
820     mPod.drawBufferTypeMask.reset();
821     mPod.computeShaderLocalSize.fill(1);
822 
823     mPod.specConstUsageBits.reset();
824 
825     mActiveSamplersMask.reset();
826     mActiveSamplerRefCounts = {};
827     mActiveSamplerTypes.fill(TextureType::InvalidEnum);
828     mActiveSamplerYUV.reset();
829     mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
830 
831     mActiveImagesMask.reset();
832 
833     mUniformBlockIndexToBufferBinding = {};
834 
835     mProgramInputs.clear();
836     mLinkedTransformFeedbackVaryings.clear();
837     mTransformFeedbackStrides.clear();
838     mUniforms.clear();
839     mUniformNames.clear();
840     mUniformMappedNames.clear();
841     mUniformBlocks.clear();
842     mUniformLocations.clear();
843     mShaderStorageBlocks.clear();
844     mAtomicCounterBuffers.clear();
845     mBufferVariables.clear();
846     mOutputVariables.clear();
847     mOutputLocations.clear();
848     mSecondaryOutputLocations.clear();
849     mSamplerBindings.clear();
850     mSamplerBoundTextureUnits.clear();
851     mImageBindings.clear();
852     mPixelLocalStorageFormats.clear();
853 
854     mPostLinkSubTasks.clear();
855     mPostLinkSubTaskWaitableEvents.clear();
856 }
857 
load(gl::BinaryInputStream * stream)858 void ProgramExecutable::load(gl::BinaryInputStream *stream)
859 {
860     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
861                   "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
862                   "mask fit into 32 bits each");
863     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
864                   "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
865                   "into 32 bits each");
866 
867     stream->readStruct(&mPod);
868 
869     LoadProgramInputs(stream, &mProgramInputs);
870     LoadUniforms(stream, &mUniforms, &mUniformNames, &mUniformMappedNames, &mUniformLocations);
871 
872     size_t uniformBlockCount = stream->readInt<size_t>();
873     ASSERT(getUniformBlocks().empty());
874     mUniformBlocks.resize(uniformBlockCount);
875     for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
876     {
877         InterfaceBlock &uniformBlock = mUniformBlocks[uniformBlockIndex];
878         LoadInterfaceBlock(stream, &uniformBlock);
879     }
880 
881     size_t shaderStorageBlockCount = stream->readInt<size_t>();
882     ASSERT(getShaderStorageBlocks().empty());
883     mShaderStorageBlocks.resize(shaderStorageBlockCount);
884     for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount;
885          ++shaderStorageBlockIndex)
886     {
887         InterfaceBlock &shaderStorageBlock = mShaderStorageBlocks[shaderStorageBlockIndex];
888         LoadInterfaceBlock(stream, &shaderStorageBlock);
889     }
890 
891     size_t atomicCounterBufferCount = stream->readInt<size_t>();
892     ASSERT(getAtomicCounterBuffers().empty());
893     mAtomicCounterBuffers.resize(atomicCounterBufferCount);
894     for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
895     {
896         AtomicCounterBuffer &atomicCounterBuffer = mAtomicCounterBuffers[bufferIndex];
897         LoadAtomicCounterBuffer(stream, &atomicCounterBuffer);
898     }
899 
900     size_t bufferVariableCount = stream->readInt<size_t>();
901     ASSERT(getBufferVariables().empty());
902     mBufferVariables.resize(bufferVariableCount);
903     for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
904     {
905         LoadBufferVariable(stream, &mBufferVariables[bufferVarIndex]);
906     }
907 
908     size_t transformFeedbackVaryingCount = stream->readInt<size_t>();
909     ASSERT(mLinkedTransformFeedbackVaryings.empty());
910     mLinkedTransformFeedbackVaryings.resize(transformFeedbackVaryingCount);
911     for (size_t transformFeedbackVaryingIndex = 0;
912          transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
913          ++transformFeedbackVaryingIndex)
914     {
915         TransformFeedbackVarying &varying =
916             mLinkedTransformFeedbackVaryings[transformFeedbackVaryingIndex];
917         stream->readVector(&varying.arraySizes);
918         stream->readInt(&varying.type);
919         stream->readString(&varying.name);
920         varying.arrayIndex = stream->readInt<GLuint>();
921     }
922 
923     size_t outputCount = stream->readInt<size_t>();
924     ASSERT(getOutputVariables().empty());
925     mOutputVariables.resize(outputCount);
926     for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex)
927     {
928         ProgramOutput &output = mOutputVariables[outputIndex];
929         stream->readString(&output.name);
930         stream->readString(&output.mappedName);
931         stream->readStruct(&output.pod);
932     }
933 
934     stream->readVector(&mOutputLocations);
935     stream->readVector(&mSecondaryOutputLocations);
936     LoadSamplerBindings(stream, &mSamplerBindings, &mSamplerBoundTextureUnits);
937 
938     size_t imageBindingCount = stream->readInt<size_t>();
939     ASSERT(mImageBindings.empty());
940     mImageBindings.resize(imageBindingCount);
941     for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
942     {
943         ImageBinding &imageBinding = mImageBindings[imageIndex];
944         size_t elementCount        = stream->readInt<size_t>();
945         imageBinding.textureType   = static_cast<TextureType>(stream->readInt<unsigned int>());
946         imageBinding.boundImageUnits.resize(elementCount);
947         for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex)
948         {
949             imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>();
950         }
951     }
952 
953     // ANGLE_shader_pixel_local_storage.
954     size_t plsCount = stream->readInt<size_t>();
955     ASSERT(mPixelLocalStorageFormats.empty());
956     mPixelLocalStorageFormats.resize(plsCount);
957     stream->readBytes(reinterpret_cast<uint8_t *>(mPixelLocalStorageFormats.data()), plsCount);
958 
959     // These values are currently only used by PPOs, so only load them when the program is marked
960     // separable to save memory.
961     if (mPod.isSeparable)
962     {
963         for (ShaderType shaderType : getLinkedShaderStages())
964         {
965             mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
966             for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
967             {
968                 LoadShaderVar(stream, &variable);
969             }
970             mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>());
971             for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType])
972             {
973                 LoadShaderVar(stream, &variable);
974             }
975             mLinkedUniforms[shaderType].resize(stream->readInt<size_t>());
976             for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType])
977             {
978                 LoadShaderVar(stream, &variable);
979             }
980             mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>());
981             for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
982             {
983                 LoadShInterfaceBlock(stream, &shaderStorageBlock);
984             }
985         }
986     }
987 }
988 
save(gl::BinaryOutputStream * stream) const989 void ProgramExecutable::save(gl::BinaryOutputStream *stream) const
990 {
991     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
992                   "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
993     static_assert(
994         IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
995         "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
996 
997     ASSERT(mPod.geometryShaderInvocations >= 1 && mPod.geometryShaderMaxVertices >= 0);
998     stream->writeStruct(mPod);
999 
1000     SaveProgramInputs(stream, mProgramInputs);
1001     SaveUniforms(stream, mUniforms, mUniformNames, mUniformMappedNames, mUniformLocations);
1002 
1003     stream->writeInt(getUniformBlocks().size());
1004     for (const InterfaceBlock &uniformBlock : getUniformBlocks())
1005     {
1006         WriteInterfaceBlock(stream, uniformBlock);
1007     }
1008 
1009     stream->writeInt(getShaderStorageBlocks().size());
1010     for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks())
1011     {
1012         WriteInterfaceBlock(stream, shaderStorageBlock);
1013     }
1014 
1015     stream->writeInt(mAtomicCounterBuffers.size());
1016     for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers())
1017     {
1018         WriteAtomicCounterBuffer(stream, atomicCounterBuffer);
1019     }
1020 
1021     stream->writeInt(getBufferVariables().size());
1022     for (const BufferVariable &bufferVariable : getBufferVariables())
1023     {
1024         WriteBufferVariable(stream, bufferVariable);
1025     }
1026 
1027     stream->writeInt(getLinkedTransformFeedbackVaryings().size());
1028     for (const auto &var : getLinkedTransformFeedbackVaryings())
1029     {
1030         stream->writeVector(var.arraySizes);
1031         stream->writeInt(var.type);
1032         stream->writeString(var.name);
1033 
1034         stream->writeIntOrNegOne(var.arrayIndex);
1035     }
1036 
1037     stream->writeInt(getOutputVariables().size());
1038     for (const ProgramOutput &output : getOutputVariables())
1039     {
1040         stream->writeString(output.name);
1041         stream->writeString(output.mappedName);
1042         stream->writeStruct(output.pod);
1043     }
1044 
1045     stream->writeVector(mOutputLocations);
1046     stream->writeVector(mSecondaryOutputLocations);
1047     SaveSamplerBindings(stream, mSamplerBindings, mSamplerBoundTextureUnits);
1048 
1049     stream->writeInt(getImageBindings().size());
1050     for (const auto &imageBinding : getImageBindings())
1051     {
1052         stream->writeInt(imageBinding.boundImageUnits.size());
1053         stream->writeInt(static_cast<unsigned int>(imageBinding.textureType));
1054         for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
1055         {
1056             stream->writeInt(imageBinding.boundImageUnits[i]);
1057         }
1058     }
1059 
1060     // ANGLE_shader_pixel_local_storage.
1061     stream->writeInt<size_t>(mPixelLocalStorageFormats.size());
1062     stream->writeBytes(reinterpret_cast<const uint8_t *>(mPixelLocalStorageFormats.data()),
1063                        mPixelLocalStorageFormats.size());
1064 
1065     // These values are currently only used by PPOs, so only save them when the program is marked
1066     // separable to save memory.
1067     if (mPod.isSeparable)
1068     {
1069         for (ShaderType shaderType : getLinkedShaderStages())
1070         {
1071             stream->writeInt(mLinkedOutputVaryings[shaderType].size());
1072             for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
1073             {
1074                 WriteShaderVar(stream, shaderVariable);
1075             }
1076             stream->writeInt(mLinkedInputVaryings[shaderType].size());
1077             for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType])
1078             {
1079                 WriteShaderVar(stream, shaderVariable);
1080             }
1081             stream->writeInt(mLinkedUniforms[shaderType].size());
1082             for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType])
1083             {
1084                 WriteShaderVar(stream, shaderVariable);
1085             }
1086             stream->writeInt(mLinkedUniformBlocks[shaderType].size());
1087             for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
1088             {
1089                 WriteShInterfaceBlock(stream, shaderStorageBlock);
1090             }
1091         }
1092     }
1093 }
1094 
getInfoLogString() const1095 std::string ProgramExecutable::getInfoLogString() const
1096 {
1097     return mInfoLog->str();
1098 }
1099 
getFirstLinkedShaderStageType() const1100 ShaderType ProgramExecutable::getFirstLinkedShaderStageType() const
1101 {
1102     const ShaderBitSet linkedStages = mPod.linkedShaderStages;
1103     if (linkedStages.none())
1104     {
1105         return ShaderType::InvalidEnum;
1106     }
1107 
1108     return linkedStages.first();
1109 }
1110 
getLastLinkedShaderStageType() const1111 ShaderType ProgramExecutable::getLastLinkedShaderStageType() const
1112 {
1113     const ShaderBitSet linkedStages = mPod.linkedShaderStages;
1114     if (linkedStages.none())
1115     {
1116         return ShaderType::InvalidEnum;
1117     }
1118 
1119     return linkedStages.last();
1120 }
1121 
setActive(size_t textureUnit,const SamplerBinding & samplerBinding,const gl::LinkedUniform & samplerUniform)1122 void ProgramExecutable::setActive(size_t textureUnit,
1123                                   const SamplerBinding &samplerBinding,
1124                                   const gl::LinkedUniform &samplerUniform)
1125 {
1126     mActiveSamplersMask.set(textureUnit);
1127     mActiveSamplerTypes[textureUnit]      = samplerBinding.textureType;
1128     mActiveSamplerYUV[textureUnit]        = IsSamplerYUVType(samplerBinding.samplerType);
1129     mActiveSamplerFormats[textureUnit]    = samplerBinding.format;
1130     mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
1131 }
1132 
setInactive(size_t textureUnit)1133 void ProgramExecutable::setInactive(size_t textureUnit)
1134 {
1135     mActiveSamplersMask.reset(textureUnit);
1136     mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
1137     mActiveSamplerYUV.reset(textureUnit);
1138     mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
1139     mActiveSamplerShaderBits[textureUnit].reset();
1140 }
1141 
hasSamplerTypeConflict(size_t textureUnit)1142 void ProgramExecutable::hasSamplerTypeConflict(size_t textureUnit)
1143 {
1144     // Conflicts are marked with InvalidEnum
1145     mActiveSamplerYUV.reset(textureUnit);
1146     mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
1147 }
1148 
hasSamplerFormatConflict(size_t textureUnit)1149 void ProgramExecutable::hasSamplerFormatConflict(size_t textureUnit)
1150 {
1151     // Conflicts are marked with InvalidEnum
1152     mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
1153 }
1154 
updateActiveSamplers(const ProgramExecutable & executable)1155 void ProgramExecutable::updateActiveSamplers(const ProgramExecutable &executable)
1156 {
1157     const std::vector<SamplerBinding> &samplerBindings = executable.getSamplerBindings();
1158     const std::vector<GLuint> &boundTextureUnits       = executable.getSamplerBoundTextureUnits();
1159 
1160     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
1161     {
1162         const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
1163 
1164         for (uint16_t index = 0; index < samplerBinding.textureUnitsCount; index++)
1165         {
1166             GLint textureUnit = samplerBinding.getTextureUnit(boundTextureUnits, index);
1167             if (++mActiveSamplerRefCounts[textureUnit] == 1)
1168             {
1169                 uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
1170                 setActive(textureUnit, samplerBinding, executable.getUniforms()[uniformIndex]);
1171             }
1172             else
1173             {
1174                 if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType ||
1175                     mActiveSamplerYUV.test(textureUnit) !=
1176                         IsSamplerYUVType(samplerBinding.samplerType))
1177                 {
1178                     hasSamplerTypeConflict(textureUnit);
1179                 }
1180 
1181                 if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
1182                 {
1183                     hasSamplerFormatConflict(textureUnit);
1184                 }
1185             }
1186             mActiveSamplersMask.set(textureUnit);
1187         }
1188     }
1189 
1190     // Invalidate the validation cache.
1191     resetCachedValidateSamplersResult();
1192 }
1193 
updateActiveImages(const ProgramExecutable & executable)1194 void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
1195 {
1196     const std::vector<ImageBinding> &imageBindings = executable.getImageBindings();
1197     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
1198     {
1199         const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex);
1200 
1201         uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex);
1202         const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex];
1203         const ShaderBitSet shaderBits         = imageUniform.activeShaders();
1204         for (GLint imageUnit : imageBinding.boundImageUnits)
1205         {
1206             mActiveImagesMask.set(imageUnit);
1207             mActiveImageShaderBits[imageUnit] |= shaderBits;
1208         }
1209     }
1210 }
1211 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)1212 void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
1213 {
1214     bool foundBinding         = false;
1215     TextureType foundType     = TextureType::InvalidEnum;
1216     bool foundYUV             = false;
1217     SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
1218 
1219     for (uint32_t samplerIndex = 0; samplerIndex < mSamplerBindings.size(); ++samplerIndex)
1220     {
1221         const SamplerBinding &binding = mSamplerBindings[samplerIndex];
1222 
1223         // A conflict exists if samplers of different types are sourced by the same texture unit.
1224         // We need to check all bound textures to detect this error case.
1225         for (uint16_t index = 0; index < binding.textureUnitsCount; index++)
1226         {
1227             GLuint textureUnit = binding.getTextureUnit(mSamplerBoundTextureUnits, index);
1228             if (textureUnit != textureUnitIndex)
1229             {
1230                 continue;
1231             }
1232 
1233             if (!foundBinding)
1234             {
1235                 foundBinding          = true;
1236                 foundType             = binding.textureType;
1237                 foundYUV              = IsSamplerYUVType(binding.samplerType);
1238                 foundFormat           = binding.format;
1239                 uint32_t uniformIndex = getUniformIndexFromSamplerIndex(samplerIndex);
1240                 setActive(textureUnit, binding, mUniforms[uniformIndex]);
1241             }
1242             else
1243             {
1244                 if (foundType != binding.textureType ||
1245                     foundYUV != IsSamplerYUVType(binding.samplerType))
1246                 {
1247                     hasSamplerTypeConflict(textureUnit);
1248                 }
1249 
1250                 if (foundFormat != binding.format)
1251                 {
1252                     hasSamplerFormatConflict(textureUnit);
1253                 }
1254             }
1255         }
1256     }
1257 }
1258 
saveLinkedStateInfo(const ProgramState & state)1259 void ProgramExecutable::saveLinkedStateInfo(const ProgramState &state)
1260 {
1261     for (ShaderType shaderType : getLinkedShaderStages())
1262     {
1263         const SharedCompiledShaderState &shader = state.getAttachedShader(shaderType);
1264         ASSERT(shader);
1265         mPod.linkedShaderVersions[shaderType] = shader->shaderVersion;
1266         mLinkedOutputVaryings[shaderType]     = shader->outputVaryings;
1267         mLinkedInputVaryings[shaderType]      = shader->inputVaryings;
1268         mLinkedUniforms[shaderType]           = shader->uniforms;
1269         mLinkedUniformBlocks[shaderType]      = shader->uniformBlocks;
1270     }
1271 }
1272 
linkMergedVaryings(const Caps & caps,const Limitations & limitations,const Version & clientVersion,bool webglCompatibility,const ProgramMergedVaryings & mergedVaryings,const LinkingVariables & linkingVariables,ProgramVaryingPacking * varyingPacking)1273 bool ProgramExecutable::linkMergedVaryings(const Caps &caps,
1274                                            const Limitations &limitations,
1275                                            const Version &clientVersion,
1276                                            bool webglCompatibility,
1277                                            const ProgramMergedVaryings &mergedVaryings,
1278                                            const LinkingVariables &linkingVariables,
1279                                            ProgramVaryingPacking *varyingPacking)
1280 {
1281     ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset);
1282 
1283     if (!linkValidateTransformFeedback(caps, clientVersion, mergedVaryings, tfStage))
1284     {
1285         return false;
1286     }
1287 
1288     // Map the varyings to the register file
1289     // In WebGL, we use a slightly different handling for packing variables.
1290     gl::PackMode packMode = PackMode::ANGLE_RELAXED;
1291     if (limitations.noFlexibleVaryingPacking)
1292     {
1293         // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
1294         packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
1295     }
1296     else if (webglCompatibility)
1297     {
1298         packMode = PackMode::WEBGL_STRICT;
1299     }
1300 
1301     // Build active shader stage map.
1302     ShaderBitSet activeShadersMask;
1303     for (ShaderType shaderType : kAllGraphicsShaderTypes)
1304     {
1305         // - Check for attached shaders to handle the case of a Program linking the currently
1306         // attached shaders.
1307         // - Check for linked shaders to handle the case of a PPO linking separable programs before
1308         // drawing.
1309         if (linkingVariables.isShaderStageUsedBitset[shaderType] ||
1310             getLinkedShaderStages().test(shaderType))
1311         {
1312             activeShadersMask[shaderType] = true;
1313         }
1314     }
1315 
1316     if (!varyingPacking->collectAndPackUserVaryings(*mInfoLog, caps, packMode, activeShadersMask,
1317                                                     mergedVaryings, mTransformFeedbackVaryingNames,
1318                                                     mPod.isSeparable))
1319     {
1320         return false;
1321     }
1322 
1323     gatherTransformFeedbackVaryings(mergedVaryings, tfStage);
1324     updateTransformFeedbackStrides();
1325 
1326     return true;
1327 }
1328 
linkValidateTransformFeedback(const Caps & caps,const Version & clientVersion,const ProgramMergedVaryings & varyings,ShaderType stage)1329 bool ProgramExecutable::linkValidateTransformFeedback(const Caps &caps,
1330                                                       const Version &clientVersion,
1331                                                       const ProgramMergedVaryings &varyings,
1332                                                       ShaderType stage)
1333 {
1334     // Validate the tf names regardless of the actual program varyings.
1335     std::set<std::string> uniqueNames;
1336     for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
1337     {
1338         if (clientVersion < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
1339         {
1340             *mInfoLog << "Capture of array elements is undefined and not supported.";
1341             return false;
1342         }
1343         if (clientVersion >= Version(3, 1))
1344         {
1345             if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
1346             {
1347                 *mInfoLog << "Two transform feedback varyings include the same array element ("
1348                           << tfVaryingName << ").";
1349                 return false;
1350             }
1351         }
1352         else
1353         {
1354             if (uniqueNames.count(tfVaryingName) > 0)
1355             {
1356                 *mInfoLog << "Two transform feedback varyings specify the same output variable ("
1357                           << tfVaryingName << ").";
1358                 return false;
1359             }
1360         }
1361         uniqueNames.insert(tfVaryingName);
1362     }
1363 
1364     // From OpneGLES spec. 11.1.2.1: A program will fail to link if:
1365     // the count specified by TransformFeedbackVaryings is non-zero, but the
1366     // program object has no vertex, tessellation evaluation, or geometry shader
1367     if (mTransformFeedbackVaryingNames.size() > 0 &&
1368         !gl::ShaderTypeSupportsTransformFeedback(getLinkedTransformFeedbackStage()))
1369     {
1370         *mInfoLog << "Linked transform feedback stage " << getLinkedTransformFeedbackStage()
1371                   << " does not support transform feedback varying.";
1372         return false;
1373     }
1374 
1375     // Validate against program varyings.
1376     size_t totalComponents = 0;
1377     for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
1378     {
1379         std::vector<unsigned int> subscripts;
1380         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1381 
1382         const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName);
1383         if (var == nullptr)
1384         {
1385             *mInfoLog << "Transform feedback varying " << tfVaryingName
1386                       << " does not exist in the vertex shader.";
1387             return false;
1388         }
1389 
1390         // Validate the matching variable.
1391         if (var->isStruct())
1392         {
1393             *mInfoLog << "Struct cannot be captured directly (" << baseName << ").";
1394             return false;
1395         }
1396 
1397         size_t elementCount   = 0;
1398         size_t componentCount = 0;
1399 
1400         if (var->isArray())
1401         {
1402             if (clientVersion < Version(3, 1))
1403             {
1404                 *mInfoLog << "Capture of arrays is undefined and not supported.";
1405                 return false;
1406             }
1407 
1408             // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
1409             ASSERT(!var->isArrayOfArrays());
1410 
1411             if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
1412             {
1413                 *mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
1414                 return false;
1415             }
1416             elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
1417         }
1418         else
1419         {
1420             if (!subscripts.empty())
1421             {
1422                 *mInfoLog << "Varying '" << baseName
1423                           << "' is not an array to be captured by element.";
1424                 return false;
1425             }
1426             elementCount = 1;
1427         }
1428 
1429         componentCount = VariableComponentCount(var->type) * elementCount;
1430         if (mPod.transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
1431             componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
1432         {
1433             *mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
1434                       << componentCount << ") exceed the maximum separate components ("
1435                       << caps.maxTransformFeedbackSeparateComponents << ").";
1436             return false;
1437         }
1438 
1439         totalComponents += componentCount;
1440         if (mPod.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
1441             totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
1442         {
1443             *mInfoLog << "Transform feedback varying total components (" << totalComponents
1444                       << ") exceed the maximum interleaved components ("
1445                       << caps.maxTransformFeedbackInterleavedComponents << ").";
1446             return false;
1447         }
1448     }
1449     return true;
1450 }
1451 
gatherTransformFeedbackVaryings(const ProgramMergedVaryings & varyings,ShaderType stage)1452 void ProgramExecutable::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings,
1453                                                         ShaderType stage)
1454 {
1455     // Gather the linked varyings that are used for transform feedback, they should all exist.
1456     mLinkedTransformFeedbackVaryings.clear();
1457     for (const std::string &tfVaryingName : mTransformFeedbackVaryingNames)
1458     {
1459         std::vector<unsigned int> subscripts;
1460         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1461         size_t subscript     = GL_INVALID_INDEX;
1462         if (!subscripts.empty())
1463         {
1464             subscript = subscripts.back();
1465         }
1466         for (const ProgramVaryingRef &ref : varyings)
1467         {
1468             if (ref.frontShaderStage != stage)
1469             {
1470                 continue;
1471             }
1472 
1473             const sh::ShaderVariable *varying = ref.get(stage);
1474             if (baseName == varying->name)
1475             {
1476                 mLinkedTransformFeedbackVaryings.emplace_back(*varying,
1477                                                               static_cast<GLuint>(subscript));
1478                 break;
1479             }
1480             else if (varying->isStruct())
1481             {
1482                 GLuint fieldIndex = 0;
1483                 const auto *field = varying->findField(tfVaryingName, &fieldIndex);
1484                 if (field != nullptr)
1485                 {
1486                     mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
1487                     break;
1488                 }
1489             }
1490         }
1491     }
1492 }
1493 
updateTransformFeedbackStrides()1494 void ProgramExecutable::updateTransformFeedbackStrides()
1495 {
1496     if (mLinkedTransformFeedbackVaryings.empty())
1497     {
1498         return;
1499     }
1500 
1501     if (mPod.transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
1502     {
1503         mTransformFeedbackStrides.resize(1);
1504         size_t totalSize = 0;
1505         for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
1506         {
1507             totalSize += varying.size() * VariableExternalSize(varying.type);
1508         }
1509         mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
1510     }
1511     else
1512     {
1513         mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
1514         for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
1515         {
1516             TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
1517             mTransformFeedbackStrides[i] =
1518                 static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
1519         }
1520     }
1521 }
1522 
validateSamplersImpl(const Caps & caps) const1523 bool ProgramExecutable::validateSamplersImpl(const Caps &caps) const
1524 {
1525     // if any two active samplers in a program are of different types, but refer to the same
1526     // texture image unit, and this is the current program, then ValidateProgram will fail, and
1527     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
1528     for (size_t textureUnit : mActiveSamplersMask)
1529     {
1530         if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
1531         {
1532             mCachedValidateSamplersResult = false;
1533             return false;
1534         }
1535 
1536         if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
1537         {
1538             mCachedValidateSamplersResult = false;
1539             return false;
1540         }
1541     }
1542 
1543     mCachedValidateSamplersResult = true;
1544     return true;
1545 }
1546 
linkValidateOutputVariables(const Caps & caps,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount,int fragmentShaderVersion,const ProgramAliasedBindings & fragmentOutputLocations,const ProgramAliasedBindings & fragmentOutputIndices)1547 bool ProgramExecutable::linkValidateOutputVariables(
1548     const Caps &caps,
1549     const Version &version,
1550     GLuint combinedImageUniformsCount,
1551     GLuint combinedShaderStorageBlocksCount,
1552     int fragmentShaderVersion,
1553     const ProgramAliasedBindings &fragmentOutputLocations,
1554     const ProgramAliasedBindings &fragmentOutputIndices)
1555 {
1556     ASSERT(mPod.activeOutputVariablesMask.none());
1557     ASSERT(mPod.activeSecondaryOutputVariablesMask.none());
1558     ASSERT(mPod.drawBufferTypeMask.none());
1559     ASSERT(!mPod.hasYUVOutput);
1560 
1561     if (fragmentShaderVersion == 100)
1562     {
1563         return gatherOutputTypes();
1564     }
1565 
1566     // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
1567     // output array in explicit terms.
1568     //
1569     // Assuming fragData is an output array, you can defend the position that:
1570     // P1) you must support binding "fragData" because it's specified
1571     // P2) you must support querying "fragData[x]" because it's specified
1572     // P3) you must support binding "fragData[0]" because it's a frequently used pattern
1573     //
1574     // Then you can make the leap of faith:
1575     // P4) you must support binding "fragData[x]" because you support "fragData[0]"
1576     // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
1577     //
1578     // The spec brings in the "world of arrays" when it mentions binding the arrays and the
1579     // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
1580     // must infer the only possible interpretation (?). Note again: this need of interpretation
1581     // might be completely off of what GL spec logic is.
1582     //
1583     // The other complexity is that unless you implement this feature, it's hard to understand what
1584     // should happen when the client invokes the feature. You cannot add an additional error as it
1585     // is not specified. One can ignore it, but obviously it creates the discrepancies...
1586 
1587     std::vector<VariableLocation> reservedLocations;
1588 
1589     // Process any output API bindings for arrays that don't alias to the first element.
1590     for (const auto &bindingPair : fragmentOutputLocations)
1591     {
1592         const std::string &name       = bindingPair.first;
1593         const ProgramBinding &binding = bindingPair.second;
1594 
1595         size_t nameLengthWithoutArrayIndex;
1596         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1597         if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
1598         {
1599             continue;
1600         }
1601         for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1602              outputVariableIndex++)
1603         {
1604             const ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];
1605             // Check that the binding corresponds to an output array and its array index fits.
1606             if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
1607                 !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) ||
1608                 arrayIndex >= outputVariable.getOutermostArraySize())
1609             {
1610                 continue;
1611             }
1612 
1613             // Get the API index that corresponds to this exact binding.
1614             // This index may differ from the index used for the array's base.
1615             std::vector<VariableLocation> &outputLocations =
1616                 fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations
1617                                                                   : mOutputLocations;
1618             unsigned int location = binding.location;
1619             VariableLocation locationInfo(arrayIndex, outputVariableIndex);
1620             if (location >= outputLocations.size())
1621             {
1622                 outputLocations.resize(location + 1);
1623             }
1624             if (outputLocations[location].used())
1625             {
1626                 *mInfoLog << "Location of variable " << outputVariable.name
1627                           << " conflicts with another variable.";
1628                 return false;
1629             }
1630             outputLocations[location] = locationInfo;
1631 
1632             // Note the array binding location so that it can be skipped later.
1633             reservedLocations.push_back(locationInfo);
1634         }
1635     }
1636 
1637     // Reserve locations for output variables whose location is fixed in the shader or through the
1638     // API. Otherwise, the remaining unallocated outputs will be processed later.
1639     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1640          outputVariableIndex++)
1641     {
1642         ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];
1643 
1644         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1645         if (outputVariable.isBuiltIn())
1646             continue;
1647 
1648         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1649         if (fixedLocation == -1)
1650         {
1651             // Here we're only reserving locations for variables whose location is fixed.
1652             continue;
1653         }
1654         unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
1655 
1656         AssignOutputIndex(fragmentOutputIndices, outputVariable);
1657         ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1);
1658         std::vector<VariableLocation> &outputLocations =
1659             outputVariable.pod.index == 0 ? mOutputLocations : mSecondaryOutputLocations;
1660 
1661         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1662         // structures, so we may use getBasicTypeElementCount().
1663         unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
1664         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
1665                                    outputVariableIndex))
1666         {
1667             *mInfoLog << "Location of variable " << outputVariable.name
1668                       << " conflicts with another variable.";
1669             return false;
1670         }
1671         bool hasApiAssignedLocation = !outputVariable.pod.hasShaderAssignedLocation &&
1672                                       (fragmentOutputLocations.getBinding(outputVariable) != -1);
1673         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1674                               outputVariableIndex, hasApiAssignedLocation, outputVariable);
1675     }
1676 
1677     // Here we assign locations for the output variables that don't yet have them. Note that we're
1678     // not necessarily able to fit the variables optimally, since then we might have to try
1679     // different arrangements of output arrays. Now we just assign the locations in the order that
1680     // we got the output variables. The spec isn't clear on what kind of algorithm is required for
1681     // finding locations for the output variables, so this should be acceptable at least for now.
1682     GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
1683     if (!mSecondaryOutputLocations.empty())
1684     {
1685         // EXT_blend_func_extended: Program outputs will be validated against
1686         // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
1687         maxLocation = caps.maxDualSourceDrawBuffers;
1688     }
1689 
1690     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1691          outputVariableIndex++)
1692     {
1693         ProgramOutput &outputVariable = mOutputVariables[outputVariableIndex];
1694 
1695         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1696         if (outputVariable.isBuiltIn())
1697             continue;
1698 
1699         AssignOutputIndex(fragmentOutputIndices, outputVariable);
1700         ASSERT(outputVariable.pod.index == 0 || outputVariable.pod.index == 1);
1701         std::vector<VariableLocation> &outputLocations =
1702             outputVariable.pod.index == 0 ? mOutputLocations : mSecondaryOutputLocations;
1703 
1704         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1705         unsigned int baseLocation = 0;
1706         unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
1707         if (fixedLocation != -1)
1708         {
1709             // Secondary inputs might have caused the max location to drop below what has already
1710             // been explicitly assigned locations. Check for any fixed locations above the max
1711             // that should cause linking to fail.
1712             baseLocation = static_cast<unsigned int>(fixedLocation);
1713         }
1714         else
1715         {
1716             // No fixed location, so try to fit the output in unassigned locations.
1717             // Try baseLocations starting from 0 one at a time and see if the variable fits.
1718             while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
1719                                           reservedLocations, outputVariableIndex))
1720             {
1721                 baseLocation++;
1722             }
1723             AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1724                                   outputVariableIndex, false, outputVariable);
1725         }
1726 
1727         // Check for any elements assigned above the max location that are actually used.
1728         if (baseLocation + elementCount > maxLocation &&
1729             (baseLocation >= maxLocation ||
1730              FindUsedOutputLocation(outputLocations, maxLocation,
1731                                     baseLocation + elementCount - maxLocation, reservedLocations,
1732                                     outputVariableIndex)))
1733         {
1734             // EXT_blend_func_extended: Linking can fail:
1735             // "if the explicit binding assignments do not leave enough space for the linker to
1736             // automatically assign a location for a varying out array, which requires multiple
1737             // contiguous locations."
1738             *mInfoLog << "Could not fit output variable into available locations: "
1739                       << outputVariable.name;
1740             return false;
1741         }
1742     }
1743 
1744     if (!gatherOutputTypes())
1745     {
1746         return false;
1747     }
1748 
1749     if (version >= ES_3_1)
1750     {
1751         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1752         // A link error will be generated if the sum of the number of active image uniforms used in
1753         // all shaders, the number of active shader storage blocks, and the number of active
1754         // fragment shader outputs exceeds the implementation-dependent value of
1755         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1756         if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
1757                 mPod.activeOutputVariablesMask.count() >
1758             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
1759         {
1760             *mInfoLog
1761                 << "The sum of the number of active image uniforms, active shader storage blocks "
1762                    "and active fragment shader outputs exceeds "
1763                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1764                 << caps.maxCombinedShaderOutputResources << ")";
1765             return false;
1766         }
1767     }
1768 
1769     return true;
1770 }
1771 
gatherOutputTypes()1772 bool ProgramExecutable::gatherOutputTypes()
1773 {
1774     for (const ProgramOutput &outputVariable : mOutputVariables)
1775     {
1776         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
1777             outputVariable.name != "gl_FragData" &&
1778             outputVariable.name != "gl_SecondaryFragColorEXT" &&
1779             outputVariable.name != "gl_SecondaryFragDataEXT")
1780         {
1781             continue;
1782         }
1783 
1784         unsigned int baseLocation = (outputVariable.pod.location == -1
1785                                          ? 0u
1786                                          : static_cast<unsigned int>(outputVariable.pod.location));
1787 
1788         const bool secondary =
1789             outputVariable.pod.index == 1 || (outputVariable.name == "gl_SecondaryFragColorEXT" ||
1790                                               outputVariable.name == "gl_SecondaryFragDataEXT");
1791 
1792         const ComponentType componentType =
1793             GLenumToComponentType(VariableComponentType(outputVariable.pod.type));
1794 
1795         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1796         // structures, so we may use getBasicTypeElementCount().
1797         unsigned int elementCount = outputVariable.pod.basicTypeElementCount;
1798         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
1799         {
1800             const unsigned int location = baseLocation + elementIndex;
1801             ASSERT(location < mPod.activeOutputVariablesMask.size());
1802             ASSERT(location < mPod.activeSecondaryOutputVariablesMask.size());
1803             if (secondary)
1804             {
1805                 mPod.activeSecondaryOutputVariablesMask.set(location);
1806             }
1807             else
1808             {
1809                 mPod.activeOutputVariablesMask.set(location);
1810             }
1811             const ComponentType storedComponentType =
1812                 gl::GetComponentTypeMask(mPod.drawBufferTypeMask, location);
1813             if (storedComponentType == ComponentType::InvalidEnum)
1814             {
1815                 SetComponentTypeMask(componentType, location, &mPod.drawBufferTypeMask);
1816             }
1817             else if (storedComponentType != componentType)
1818             {
1819                 *mInfoLog << "Inconsistent component types for fragment outputs at location "
1820                           << location;
1821                 return false;
1822             }
1823         }
1824 
1825         if (outputVariable.pod.yuv)
1826         {
1827             ASSERT(mOutputVariables.size() == 1);
1828             mPod.hasYUVOutput = true;
1829         }
1830     }
1831 
1832     return true;
1833 }
1834 
linkUniforms(const Caps & caps,const ShaderMap<std::vector<sh::ShaderVariable>> & shaderUniforms,const ProgramAliasedBindings & uniformLocationBindings,GLuint * combinedImageUniformsCountOut,std::vector<UnusedUniform> * unusedUniformsOutOrNull)1835 bool ProgramExecutable::linkUniforms(
1836     const Caps &caps,
1837     const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
1838     const ProgramAliasedBindings &uniformLocationBindings,
1839     GLuint *combinedImageUniformsCountOut,
1840     std::vector<UnusedUniform> *unusedUniformsOutOrNull)
1841 {
1842     UniformLinker linker(mPod.linkedShaderStages, shaderUniforms);
1843     if (!linker.link(caps, *mInfoLog, uniformLocationBindings))
1844     {
1845         return false;
1846     }
1847 
1848     linker.getResults(&mUniforms, &mUniformNames, &mUniformMappedNames, unusedUniformsOutOrNull,
1849                       &mUniformLocations);
1850 
1851     linkSamplerAndImageBindings(combinedImageUniformsCountOut);
1852 
1853     if (!linkAtomicCounterBuffers(caps))
1854     {
1855         return false;
1856     }
1857 
1858     return true;
1859 }
1860 
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)1861 void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
1862 {
1863     ASSERT(combinedImageUniforms);
1864 
1865     // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
1866     // atomic counters, images and samplers in that order.
1867     auto highIter = mUniforms.rbegin();
1868     auto lowIter  = highIter;
1869 
1870     unsigned int high = static_cast<unsigned int>(mUniforms.size());
1871     unsigned int low  = high;
1872 
1873     // Note that uniform block uniforms are not yet appended to this list.
1874     ASSERT(mUniforms.empty() || highIter->isAtomicCounter() || highIter->isImage() ||
1875            highIter->isSampler() || highIter->isInDefaultBlock());
1876 
1877     for (; lowIter != mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter)
1878     {
1879         --low;
1880     }
1881 
1882     mPod.atomicCounterUniformRange = RangeUI(low, high);
1883 
1884     highIter = lowIter;
1885     high     = low;
1886 
1887     for (; lowIter != mUniforms.rend() && lowIter->isImage(); ++lowIter)
1888     {
1889         --low;
1890     }
1891 
1892     mPod.imageUniformRange = RangeUI(low, high);
1893     *combinedImageUniforms = 0u;
1894     // If uniform is a image type, insert it into the mImageBindings array.
1895     for (unsigned int imageIndex : mPod.imageUniformRange)
1896     {
1897         // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
1898         // cannot load values into a uniform defined as an image. if declare without a
1899         // binding qualifier, any uniform image variable (include all elements of
1900         // unbound image array) should be bound to unit zero.
1901         auto &imageUniform      = mUniforms[imageIndex];
1902         TextureType textureType = ImageTypeToTextureType(imageUniform.getType());
1903         const GLuint arraySize  = imageUniform.getBasicTypeElementCount();
1904 
1905         if (imageUniform.getBinding() == -1)
1906         {
1907             mImageBindings.emplace_back(
1908                 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
1909         }
1910         else
1911         {
1912             // The arrays of arrays are flattened to arrays, it needs to record the array offset for
1913             // the correct binding image unit.
1914             mImageBindings.emplace_back(ImageBinding(
1915                 imageUniform.getBinding() + imageUniform.pod.parentArrayIndex * arraySize,
1916                 imageUniform.getBasicTypeElementCount(), textureType));
1917         }
1918 
1919         *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
1920     }
1921 
1922     highIter = lowIter;
1923     high     = low;
1924 
1925     for (; lowIter != mUniforms.rend() && lowIter->isSampler(); ++lowIter)
1926     {
1927         --low;
1928     }
1929 
1930     mPod.samplerUniformRange = RangeUI(low, high);
1931 
1932     // If uniform is a sampler type, insert it into the mSamplerBindings array.
1933     uint16_t totalCount = 0;
1934     for (unsigned int samplerIndex : mPod.samplerUniformRange)
1935     {
1936         const auto &samplerUniform = mUniforms[samplerIndex];
1937         TextureType textureType    = SamplerTypeToTextureType(samplerUniform.getType());
1938         GLenum samplerType         = samplerUniform.getType();
1939         uint16_t elementCount      = samplerUniform.getBasicTypeElementCount();
1940         SamplerFormat format       = GetUniformTypeInfo(samplerType).samplerFormat;
1941         mSamplerBindings.emplace_back(textureType, samplerType, format, totalCount, elementCount);
1942         totalCount += elementCount;
1943     }
1944     mSamplerBoundTextureUnits.resize(totalCount, 0);
1945 
1946     // Whatever is left constitutes the default uniforms.
1947     mPod.defaultUniformRange = RangeUI(0, low);
1948 }
1949 
linkAtomicCounterBuffers(const Caps & caps)1950 bool ProgramExecutable::linkAtomicCounterBuffers(const Caps &caps)
1951 {
1952     for (unsigned int index : mPod.atomicCounterUniformRange)
1953     {
1954         auto &uniform = mUniforms[index];
1955 
1956         uniform.pod.blockOffset                    = uniform.getOffset();
1957         uniform.pod.blockArrayStride               = uniform.isArray() ? 4 : 0;
1958         uniform.pod.blockMatrixStride              = 0;
1959         uniform.pod.flagBits.blockIsRowMajorMatrix = false;
1960         uniform.pod.flagBits.isBlock               = true;
1961 
1962         bool found = false;
1963         for (size_t bufferIndex = 0; bufferIndex < mAtomicCounterBuffers.size(); ++bufferIndex)
1964         {
1965             AtomicCounterBuffer &buffer = mAtomicCounterBuffers[bufferIndex];
1966             if (buffer.pod.inShaderBinding == uniform.getBinding())
1967             {
1968                 buffer.memberIndexes.push_back(index);
1969                 SetBitField(uniform.pod.bufferIndex, bufferIndex);
1970                 found = true;
1971                 buffer.unionReferencesWith(uniform);
1972                 break;
1973             }
1974         }
1975         if (!found)
1976         {
1977             AtomicCounterBuffer atomicCounterBuffer;
1978             atomicCounterBuffer.pod.inShaderBinding = uniform.getBinding();
1979             atomicCounterBuffer.memberIndexes.push_back(index);
1980             atomicCounterBuffer.unionReferencesWith(uniform);
1981             mAtomicCounterBuffers.push_back(atomicCounterBuffer);
1982             SetBitField(uniform.pod.bufferIndex, mAtomicCounterBuffers.size() - 1);
1983         }
1984     }
1985 
1986     // Count each atomic counter buffer to validate against
1987     // per-stage and combined gl_Max*AtomicCounterBuffers.
1988     GLint combinedShaderACBCount           = 0;
1989     gl::ShaderMap<GLint> perShaderACBCount = {};
1990     for (size_t bufferIndex = 0; bufferIndex < mAtomicCounterBuffers.size(); ++bufferIndex)
1991     {
1992         AtomicCounterBuffer &acb        = mAtomicCounterBuffers[bufferIndex];
1993         const ShaderBitSet shaderStages = acb.activeShaders();
1994         for (gl::ShaderType shaderType : shaderStages)
1995         {
1996             ++perShaderACBCount[shaderType];
1997         }
1998         ++combinedShaderACBCount;
1999     }
2000     if (combinedShaderACBCount > caps.maxCombinedAtomicCounterBuffers)
2001     {
2002         *mInfoLog << " combined AtomicCounterBuffers count exceeds limit";
2003         return false;
2004     }
2005     for (gl::ShaderType stage : gl::AllShaderTypes())
2006     {
2007         if (perShaderACBCount[stage] > caps.maxShaderAtomicCounterBuffers[stage])
2008         {
2009             *mInfoLog << GetShaderTypeString(stage)
2010                       << " shader AtomicCounterBuffers count exceeds limit";
2011             return false;
2012         }
2013     }
2014     return true;
2015 }
2016 
copyInputsFromProgram(const ProgramExecutable & executable)2017 void ProgramExecutable::copyInputsFromProgram(const ProgramExecutable &executable)
2018 {
2019     mProgramInputs = executable.getProgramInputs();
2020 }
2021 
copyUniformBuffersFromProgram(const ProgramExecutable & executable,ShaderType shaderType,ProgramUniformBlockArray<GLuint> * ppoUniformBlockMap)2022 void ProgramExecutable::copyUniformBuffersFromProgram(
2023     const ProgramExecutable &executable,
2024     ShaderType shaderType,
2025     ProgramUniformBlockArray<GLuint> *ppoUniformBlockMap)
2026 {
2027     AppendActiveBlocks(shaderType, executable.getUniformBlocks(), mUniformBlocks,
2028                        ppoUniformBlockMap);
2029 
2030     const std::vector<InterfaceBlock> &blocks = executable.getUniformBlocks();
2031     for (size_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
2032     {
2033         if (!blocks[blockIndex].isActive(shaderType))
2034         {
2035             continue;
2036         }
2037         const uint32_t blockIndexInPPO = (*ppoUniformBlockMap)[static_cast<uint32_t>(blockIndex)];
2038         ASSERT(blockIndexInPPO < mUniformBlocks.size());
2039 
2040         // Set the block buffer binding in the PPO to the same binding as the program's.
2041         remapUniformBlockBinding({blockIndexInPPO}, executable.getUniformBlockBinding(blockIndex));
2042     }
2043 }
2044 
copyStorageBuffersFromProgram(const ProgramExecutable & executable,ShaderType shaderType)2045 void ProgramExecutable::copyStorageBuffersFromProgram(const ProgramExecutable &executable,
2046                                                       ShaderType shaderType)
2047 {
2048     AppendActiveBlocks(shaderType, executable.getShaderStorageBlocks(), mShaderStorageBlocks,
2049                        nullptr);
2050     AppendActiveBlocks(shaderType, executable.getAtomicCounterBuffers(), mAtomicCounterBuffers,
2051                        nullptr);
2052 
2053     // Buffer variable info is queried through the program, and program pipelines don't access it.
2054     ASSERT(mBufferVariables.empty());
2055 }
2056 
clearSamplerBindings()2057 void ProgramExecutable::clearSamplerBindings()
2058 {
2059     mSamplerBindings.clear();
2060     mSamplerBoundTextureUnits.clear();
2061 }
2062 
copySamplerBindingsFromProgram(const ProgramExecutable & executable)2063 void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramExecutable &executable)
2064 {
2065     const std::vector<SamplerBinding> &bindings = executable.getSamplerBindings();
2066     const std::vector<GLuint> &textureUnits     = executable.getSamplerBoundTextureUnits();
2067     uint16_t adjustedStartIndex                 = mSamplerBoundTextureUnits.size();
2068     mSamplerBoundTextureUnits.insert(mSamplerBoundTextureUnits.end(), textureUnits.begin(),
2069                                      textureUnits.end());
2070     for (const SamplerBinding &binding : bindings)
2071     {
2072         mSamplerBindings.push_back(binding);
2073         mSamplerBindings.back().textureUnitsStartIndex += adjustedStartIndex;
2074     }
2075 }
2076 
copyImageBindingsFromProgram(const ProgramExecutable & executable)2077 void ProgramExecutable::copyImageBindingsFromProgram(const ProgramExecutable &executable)
2078 {
2079     const std::vector<ImageBinding> &bindings = executable.getImageBindings();
2080     mImageBindings.insert(mImageBindings.end(), bindings.begin(), bindings.end());
2081 }
2082 
copyOutputsFromProgram(const ProgramExecutable & executable)2083 void ProgramExecutable::copyOutputsFromProgram(const ProgramExecutable &executable)
2084 {
2085     mOutputVariables          = executable.getOutputVariables();
2086     mOutputLocations          = executable.getOutputLocations();
2087     mSecondaryOutputLocations = executable.getSecondaryOutputLocations();
2088 }
2089 
copyUniformsFromProgramMap(const ShaderMap<SharedProgramExecutable> & executables)2090 void ProgramExecutable::copyUniformsFromProgramMap(
2091     const ShaderMap<SharedProgramExecutable> &executables)
2092 {
2093     // Merge default uniforms.
2094     auto getDefaultRange = [](const ProgramExecutable &state) {
2095         return state.getDefaultUniformRange();
2096     };
2097     mPod.defaultUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
2098                                            &mUniformNames, &mUniformMappedNames, getDefaultRange);
2099 
2100     // Merge sampler uniforms.
2101     auto getSamplerRange = [](const ProgramExecutable &state) {
2102         return state.getSamplerUniformRange();
2103     };
2104     mPod.samplerUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
2105                                            &mUniformNames, &mUniformMappedNames, getSamplerRange);
2106 
2107     // Merge image uniforms.
2108     auto getImageRange = [](const ProgramExecutable &state) {
2109         return state.getImageUniformRange();
2110     };
2111     mPod.imageUniformRange = AddUniforms(executables, mPod.linkedShaderStages, &mUniforms,
2112                                          &mUniformNames, &mUniformMappedNames, getImageRange);
2113 
2114     // Merge atomic counter uniforms.
2115     auto getAtomicRange = [](const ProgramExecutable &state) {
2116         return state.getAtomicCounterUniformRange();
2117     };
2118     mPod.atomicCounterUniformRange =
2119         AddUniforms(executables, mPod.linkedShaderStages, &mUniforms, &mUniformNames,
2120                     &mUniformMappedNames, getAtomicRange);
2121 
2122     // Note: uniforms are set through the program, and the program pipeline never needs it.
2123     ASSERT(mUniformLocations.empty());
2124 }
2125 
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2126 void ProgramExecutable::getResourceName(const std::string name,
2127                                         GLsizei bufSize,
2128                                         GLsizei *length,
2129                                         GLchar *dest) const
2130 {
2131     if (length)
2132     {
2133         *length = 0;
2134     }
2135 
2136     if (bufSize > 0)
2137     {
2138         CopyStringToBuffer(dest, name, bufSize, length);
2139     }
2140 }
2141 
getInputResourceIndex(const GLchar * name) const2142 GLuint ProgramExecutable::getInputResourceIndex(const GLchar *name) const
2143 {
2144     const std::string nameString = StripLastArrayIndex(name);
2145 
2146     for (size_t index = 0; index < mProgramInputs.size(); index++)
2147     {
2148         if (mProgramInputs[index].name == nameString)
2149         {
2150             return static_cast<GLuint>(index);
2151         }
2152     }
2153 
2154     return GL_INVALID_INDEX;
2155 }
2156 
getInputResourceMaxNameSize() const2157 GLuint ProgramExecutable::getInputResourceMaxNameSize() const
2158 {
2159     GLint max = 0;
2160 
2161     for (const ProgramInput &resource : mProgramInputs)
2162     {
2163         max = GetResourceMaxNameSize(resource, max);
2164     }
2165 
2166     return max;
2167 }
2168 
getOutputResourceMaxNameSize() const2169 GLuint ProgramExecutable::getOutputResourceMaxNameSize() const
2170 {
2171     GLint max = 0;
2172 
2173     for (const gl::ProgramOutput &resource : mOutputVariables)
2174     {
2175         max = GetResourceMaxNameSize(resource, max);
2176     }
2177 
2178     return max;
2179 }
2180 
getInputResourceLocation(const GLchar * name) const2181 GLuint ProgramExecutable::getInputResourceLocation(const GLchar *name) const
2182 {
2183     const GLuint index = getInputResourceIndex(name);
2184     if (index == GL_INVALID_INDEX)
2185     {
2186         return index;
2187     }
2188 
2189     const ProgramInput &variable = getInputResource(index);
2190 
2191     return GetResourceLocation(name, variable, variable.getLocation());
2192 }
2193 
getOutputResourceLocation(const GLchar * name) const2194 GLuint ProgramExecutable::getOutputResourceLocation(const GLchar *name) const
2195 {
2196     const GLuint index = getOutputResourceIndex(name);
2197     if (index == GL_INVALID_INDEX)
2198     {
2199         return index;
2200     }
2201 
2202     const gl::ProgramOutput &variable = getOutputResource(index);
2203 
2204     return GetResourceLocation(name, variable, variable.pod.location);
2205 }
2206 
getOutputResourceIndex(const GLchar * name) const2207 GLuint ProgramExecutable::getOutputResourceIndex(const GLchar *name) const
2208 {
2209     const std::string nameString = StripLastArrayIndex(name);
2210 
2211     for (size_t index = 0; index < mOutputVariables.size(); index++)
2212     {
2213         if (mOutputVariables[index].name == nameString)
2214         {
2215             return static_cast<GLuint>(index);
2216         }
2217     }
2218 
2219     return GL_INVALID_INDEX;
2220 }
2221 
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2222 void ProgramExecutable::getInputResourceName(GLuint index,
2223                                              GLsizei bufSize,
2224                                              GLsizei *length,
2225                                              GLchar *name) const
2226 {
2227     getResourceName(getInputResourceName(index), bufSize, length, name);
2228 }
2229 
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2230 void ProgramExecutable::getOutputResourceName(GLuint index,
2231                                               GLsizei bufSize,
2232                                               GLsizei *length,
2233                                               GLchar *name) const
2234 {
2235     getResourceName(getOutputResourceName(index), bufSize, length, name);
2236 }
2237 
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2238 void ProgramExecutable::getUniformResourceName(GLuint index,
2239                                                GLsizei bufSize,
2240                                                GLsizei *length,
2241                                                GLchar *name) const
2242 {
2243     getResourceName(getUniformNameByIndex(index), bufSize, length, name);
2244 }
2245 
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2246 void ProgramExecutable::getBufferVariableResourceName(GLuint index,
2247                                                       GLsizei bufSize,
2248                                                       GLsizei *length,
2249                                                       GLchar *name) const
2250 {
2251     ASSERT(index < mBufferVariables.size());
2252     getResourceName(mBufferVariables[index].name, bufSize, length, name);
2253 }
2254 
getInputResourceName(GLuint index) const2255 const std::string ProgramExecutable::getInputResourceName(GLuint index) const
2256 {
2257     return GetResourceName(getInputResource(index));
2258 }
2259 
getOutputResourceName(GLuint index) const2260 const std::string ProgramExecutable::getOutputResourceName(GLuint index) const
2261 {
2262     return GetResourceName(getOutputResource(index));
2263 }
2264 
getFragDataLocation(const std::string & name) const2265 GLint ProgramExecutable::getFragDataLocation(const std::string &name) const
2266 {
2267     const GLint primaryLocation = GetVariableLocation(mOutputVariables, mOutputLocations, name);
2268     if (primaryLocation != -1)
2269     {
2270         return primaryLocation;
2271     }
2272     return GetVariableLocation(mOutputVariables, mSecondaryOutputLocations, name);
2273 }
2274 
getFragDataIndex(const std::string & name) const2275 GLint ProgramExecutable::getFragDataIndex(const std::string &name) const
2276 {
2277     if (GetVariableLocation(mOutputVariables, mOutputLocations, name) != -1)
2278     {
2279         return 0;
2280     }
2281     if (GetVariableLocation(mOutputVariables, mSecondaryOutputLocations, name) != -1)
2282     {
2283         return 1;
2284     }
2285     return -1;
2286 }
2287 
getTransformFeedbackVaryingMaxLength() const2288 GLsizei ProgramExecutable::getTransformFeedbackVaryingMaxLength() const
2289 {
2290     GLsizei maxSize = 0;
2291     for (const TransformFeedbackVarying &var : mLinkedTransformFeedbackVaryings)
2292     {
2293         maxSize = std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
2294     }
2295 
2296     return maxSize;
2297 }
2298 
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const2299 GLuint ProgramExecutable::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
2300 {
2301     for (GLuint tfIndex = 0; tfIndex < mLinkedTransformFeedbackVaryings.size(); ++tfIndex)
2302     {
2303         if (mLinkedTransformFeedbackVaryings[tfIndex].nameWithArrayIndex() == name)
2304         {
2305             return tfIndex;
2306         }
2307     }
2308     return GL_INVALID_INDEX;
2309 }
2310 
getTransformFeedbackVaryingResource(GLuint index) const2311 const TransformFeedbackVarying &ProgramExecutable::getTransformFeedbackVaryingResource(
2312     GLuint index) const
2313 {
2314     ASSERT(index < mLinkedTransformFeedbackVaryings.size());
2315     return mLinkedTransformFeedbackVaryings[index];
2316 }
2317 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2318 void ProgramExecutable::getTransformFeedbackVarying(GLuint index,
2319                                                     GLsizei bufSize,
2320                                                     GLsizei *length,
2321                                                     GLsizei *size,
2322                                                     GLenum *type,
2323                                                     GLchar *name) const
2324 {
2325     if (mLinkedTransformFeedbackVaryings.empty())
2326     {
2327         // Program is not successfully linked
2328         return;
2329     }
2330 
2331     ASSERT(index < mLinkedTransformFeedbackVaryings.size());
2332     const auto &var     = mLinkedTransformFeedbackVaryings[index];
2333     std::string varName = var.nameWithArrayIndex();
2334     GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
2335     if (length)
2336     {
2337         *length = lastNameIdx;
2338     }
2339     if (size)
2340     {
2341         *size = var.size();
2342     }
2343     if (type)
2344     {
2345         *type = var.type;
2346     }
2347     if (name)
2348     {
2349         memcpy(name, varName.c_str(), lastNameIdx);
2350         name[lastNameIdx] = '\0';
2351     }
2352 }
2353 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2354 void ProgramExecutable::getActiveAttribute(GLuint index,
2355                                            GLsizei bufsize,
2356                                            GLsizei *length,
2357                                            GLint *size,
2358                                            GLenum *type,
2359                                            GLchar *name) const
2360 {
2361     if (mProgramInputs.empty())
2362     {
2363         // Program is not successfully linked
2364         if (bufsize > 0)
2365         {
2366             name[0] = '\0';
2367         }
2368 
2369         if (length)
2370         {
2371             *length = 0;
2372         }
2373 
2374         *type = GL_NONE;
2375         *size = 1;
2376         return;
2377     }
2378 
2379     ASSERT(index < mProgramInputs.size());
2380     const ProgramInput &attrib = mProgramInputs[index];
2381 
2382     if (bufsize > 0)
2383     {
2384         CopyStringToBuffer(name, attrib.name, bufsize, length);
2385     }
2386 
2387     // Always a single 'type' instance
2388     *size = 1;
2389     *type = attrib.getType();
2390 }
2391 
getActiveAttributeMaxLength() const2392 GLint ProgramExecutable::getActiveAttributeMaxLength() const
2393 {
2394     size_t maxLength = 0;
2395 
2396     for (const ProgramInput &attrib : mProgramInputs)
2397     {
2398         maxLength = std::max(attrib.name.length() + 1, maxLength);
2399     }
2400 
2401     return static_cast<GLint>(maxLength);
2402 }
2403 
getAttributeLocation(const std::string & name) const2404 GLuint ProgramExecutable::getAttributeLocation(const std::string &name) const
2405 {
2406     for (const ProgramInput &attribute : mProgramInputs)
2407     {
2408         if (attribute.name == name)
2409         {
2410             return attribute.getLocation();
2411         }
2412     }
2413 
2414     return static_cast<GLuint>(-1);
2415 }
2416 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2417 void ProgramExecutable::getActiveUniform(GLuint index,
2418                                          GLsizei bufsize,
2419                                          GLsizei *length,
2420                                          GLint *size,
2421                                          GLenum *type,
2422                                          GLchar *name) const
2423 {
2424     if (mUniforms.empty())
2425     {
2426         // Program is not successfully linked
2427         if (bufsize > 0)
2428         {
2429             name[0] = '\0';
2430         }
2431 
2432         if (length)
2433         {
2434             *length = 0;
2435         }
2436 
2437         *size = 0;
2438         *type = GL_NONE;
2439     }
2440 
2441     ASSERT(index < mUniforms.size());
2442     const LinkedUniform &uniform = mUniforms[index];
2443 
2444     if (bufsize > 0)
2445     {
2446         const std::string &string = getUniformNameByIndex(index);
2447         CopyStringToBuffer(name, string, bufsize, length);
2448     }
2449 
2450     *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2451     *type = uniform.getType();
2452 }
2453 
getActiveUniformMaxLength() const2454 GLint ProgramExecutable::getActiveUniformMaxLength() const
2455 {
2456     size_t maxLength = 0;
2457 
2458     for (GLuint index = 0; index < static_cast<size_t>(mUniformNames.size()); index++)
2459     {
2460         const std::string &uniformName = getUniformNameByIndex(index);
2461         if (!uniformName.empty())
2462         {
2463             size_t length = uniformName.length() + 1u;
2464             if (getUniformByIndex(index).isArray())
2465             {
2466                 length += 3;  // Counting in "[0]".
2467             }
2468             maxLength = std::max(length, maxLength);
2469         }
2470     }
2471 
2472     return static_cast<GLint>(maxLength);
2473 }
2474 
isValidUniformLocation(UniformLocation location) const2475 bool ProgramExecutable::isValidUniformLocation(UniformLocation location) const
2476 {
2477     ASSERT(angle::IsValueInRangeForNumericType<GLint>(mUniformLocations.size()));
2478     return location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size() &&
2479            mUniformLocations[location.value].used();
2480 }
2481 
getUniformByLocation(UniformLocation location) const2482 const LinkedUniform &ProgramExecutable::getUniformByLocation(UniformLocation location) const
2483 {
2484     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
2485     return mUniforms[getUniformIndexFromLocation(location)];
2486 }
2487 
getUniformLocation(UniformLocation location) const2488 const VariableLocation &ProgramExecutable::getUniformLocation(UniformLocation location) const
2489 {
2490     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
2491     return mUniformLocations[location.value];
2492 }
2493 
getUniformLocation(const std::string & name) const2494 UniformLocation ProgramExecutable::getUniformLocation(const std::string &name) const
2495 {
2496     return {GetUniformLocation(mUniforms, mUniformNames, mUniformLocations, name)};
2497 }
2498 
getUniformIndex(const std::string & name) const2499 GLuint ProgramExecutable::getUniformIndex(const std::string &name) const
2500 {
2501     return getUniformIndexFromName(name);
2502 }
2503 
shouldIgnoreUniform(UniformLocation location) const2504 bool ProgramExecutable::shouldIgnoreUniform(UniformLocation location) const
2505 {
2506     // Casting to size_t will convert negative values to large positive avoiding double check.
2507     // Adding ERR() log to report out of bound location harms performance on Android.
2508     return ANGLE_UNLIKELY(static_cast<size_t>(location.value) >= mUniformLocations.size() ||
2509                           mUniformLocations[location.value].ignored);
2510 }
2511 
getUniformIndexFromName(const std::string & name) const2512 GLuint ProgramExecutable::getUniformIndexFromName(const std::string &name) const
2513 {
2514     return GetUniformIndexFromName(mUniforms, mUniformNames, name);
2515 }
2516 
getBufferVariableIndexFromName(const std::string & name) const2517 GLuint ProgramExecutable::getBufferVariableIndexFromName(const std::string &name) const
2518 {
2519     return GetResourceIndexFromName(mBufferVariables, name);
2520 }
2521 
getUniformIndexFromLocation(UniformLocation location) const2522 GLuint ProgramExecutable::getUniformIndexFromLocation(UniformLocation location) const
2523 {
2524     ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
2525     return mUniformLocations[location.value].index;
2526 }
2527 
getSamplerIndex(UniformLocation location) const2528 Optional<GLuint> ProgramExecutable::getSamplerIndex(UniformLocation location) const
2529 {
2530     GLuint index = getUniformIndexFromLocation(location);
2531     if (!isSamplerUniformIndex(index))
2532     {
2533         return Optional<GLuint>::Invalid();
2534     }
2535 
2536     return getSamplerIndexFromUniformIndex(index);
2537 }
2538 
isSamplerUniformIndex(GLuint index) const2539 bool ProgramExecutable::isSamplerUniformIndex(GLuint index) const
2540 {
2541     return mPod.samplerUniformRange.contains(index);
2542 }
2543 
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const2544 GLuint ProgramExecutable::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
2545 {
2546     ASSERT(isSamplerUniformIndex(uniformIndex));
2547     return uniformIndex - mPod.samplerUniformRange.low();
2548 }
2549 
isImageUniformIndex(GLuint index) const2550 bool ProgramExecutable::isImageUniformIndex(GLuint index) const
2551 {
2552     return mPod.imageUniformRange.contains(index);
2553 }
2554 
getImageIndexFromUniformIndex(GLuint uniformIndex) const2555 GLuint ProgramExecutable::getImageIndexFromUniformIndex(GLuint uniformIndex) const
2556 {
2557     ASSERT(isImageUniformIndex(uniformIndex));
2558     return uniformIndex - mPod.imageUniformRange.low();
2559 }
2560 
getActiveUniformBlockName(const Context * context,const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2561 void ProgramExecutable::getActiveUniformBlockName(const Context *context,
2562                                                   const UniformBlockIndex blockIndex,
2563                                                   GLsizei bufSize,
2564                                                   GLsizei *length,
2565                                                   GLchar *blockName) const
2566 {
2567     GetInterfaceBlockName(blockIndex, mUniformBlocks, bufSize, length, blockName);
2568 }
2569 
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2570 void ProgramExecutable::getActiveShaderStorageBlockName(const GLuint blockIndex,
2571                                                         GLsizei bufSize,
2572                                                         GLsizei *length,
2573                                                         GLchar *blockName) const
2574 {
2575     GetInterfaceBlockName({blockIndex}, mShaderStorageBlocks, bufSize, length, blockName);
2576 }
2577 
getActiveUniformBlockMaxNameLength() const2578 GLint ProgramExecutable::getActiveUniformBlockMaxNameLength() const
2579 {
2580     return GetActiveInterfaceBlockMaxNameLength(mUniformBlocks);
2581 }
2582 
getActiveShaderStorageBlockMaxNameLength() const2583 GLint ProgramExecutable::getActiveShaderStorageBlockMaxNameLength() const
2584 {
2585     return GetActiveInterfaceBlockMaxNameLength(mShaderStorageBlocks);
2586 }
2587 
getUniformBlockIndex(const std::string & name) const2588 GLuint ProgramExecutable::getUniformBlockIndex(const std::string &name) const
2589 {
2590     return GetInterfaceBlockIndex(mUniformBlocks, name);
2591 }
2592 
getShaderStorageBlockIndex(const std::string & name) const2593 GLuint ProgramExecutable::getShaderStorageBlockIndex(const std::string &name) const
2594 {
2595     return GetInterfaceBlockIndex(mShaderStorageBlocks, name);
2596 }
2597 
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2598 GLuint ProgramExecutable::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2599 {
2600     GLuint samplerIndex                  = getSamplerIndexFromUniformIndex(uniformLocation.index);
2601     const SamplerBinding &samplerBinding = mSamplerBindings[samplerIndex];
2602     if (uniformLocation.arrayIndex >= samplerBinding.textureUnitsCount)
2603     {
2604         return 0;
2605     }
2606 
2607     const std::vector<GLuint> &boundTextureUnits = mSamplerBoundTextureUnits;
2608     return samplerBinding.getTextureUnit(boundTextureUnits, uniformLocation.arrayIndex);
2609 }
2610 
getImageUniformBinding(const VariableLocation & uniformLocation) const2611 GLuint ProgramExecutable::getImageUniformBinding(const VariableLocation &uniformLocation) const
2612 {
2613     GLuint imageIndex = getImageIndexFromUniformIndex(uniformLocation.index);
2614 
2615     const std::vector<GLuint> &boundImageUnits = mImageBindings[imageIndex].boundImageUnits;
2616     return boundImageUnits[uniformLocation.arrayIndex];
2617 }
2618 
2619 template <typename UniformT,
2620           GLint UniformSize,
2621           void (rx::ProgramExecutableImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
setUniformGeneric(UniformLocation location,GLsizei count,const UniformT * v)2622 void ProgramExecutable::setUniformGeneric(UniformLocation location,
2623                                           GLsizei count,
2624                                           const UniformT *v)
2625 {
2626     if (shouldIgnoreUniform(location))
2627     {
2628         return;
2629     }
2630 
2631     const VariableLocation &locationInfo = mUniformLocations[location.value];
2632     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, UniformSize, v);
2633     (mImplementation->*SetUniformFunc)(location.value, clampedCount, v);
2634 }
2635 
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2636 void ProgramExecutable::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2637 {
2638     setUniformGeneric<GLfloat, 1, &rx::ProgramExecutableImpl::setUniform1fv>(location, count, v);
2639 }
2640 
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2641 void ProgramExecutable::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2642 {
2643     setUniformGeneric<GLfloat, 2, &rx::ProgramExecutableImpl::setUniform2fv>(location, count, v);
2644 }
2645 
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2646 void ProgramExecutable::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2647 {
2648     setUniformGeneric<GLfloat, 3, &rx::ProgramExecutableImpl::setUniform3fv>(location, count, v);
2649 }
2650 
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2651 void ProgramExecutable::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2652 {
2653     setUniformGeneric<GLfloat, 4, &rx::ProgramExecutableImpl::setUniform4fv>(location, count, v);
2654 }
2655 
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2656 void ProgramExecutable::setUniform1iv(Context *context,
2657                                       UniformLocation location,
2658                                       GLsizei count,
2659                                       const GLint *v)
2660 {
2661     if (shouldIgnoreUniform(location))
2662     {
2663         return;
2664     }
2665 
2666     const VariableLocation &locationInfo = mUniformLocations[location.value];
2667     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
2668 
2669     mImplementation->setUniform1iv(location.value, clampedCount, v);
2670 
2671     if (isSamplerUniformIndex(locationInfo.index))
2672     {
2673         updateSamplerUniform(context, locationInfo, clampedCount, v);
2674     }
2675 }
2676 
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2677 void ProgramExecutable::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2678 {
2679     setUniformGeneric<GLint, 2, &rx::ProgramExecutableImpl::setUniform2iv>(location, count, v);
2680 }
2681 
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2682 void ProgramExecutable::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2683 {
2684     setUniformGeneric<GLint, 3, &rx::ProgramExecutableImpl::setUniform3iv>(location, count, v);
2685 }
2686 
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2687 void ProgramExecutable::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2688 {
2689     setUniformGeneric<GLint, 4, &rx::ProgramExecutableImpl::setUniform4iv>(location, count, v);
2690 }
2691 
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2692 void ProgramExecutable::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2693 {
2694     setUniformGeneric<GLuint, 1, &rx::ProgramExecutableImpl::setUniform1uiv>(location, count, v);
2695 }
2696 
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2697 void ProgramExecutable::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2698 {
2699     setUniformGeneric<GLuint, 2, &rx::ProgramExecutableImpl::setUniform2uiv>(location, count, v);
2700 }
2701 
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2702 void ProgramExecutable::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2703 {
2704     setUniformGeneric<GLuint, 3, &rx::ProgramExecutableImpl::setUniform3uiv>(location, count, v);
2705 }
2706 
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2707 void ProgramExecutable::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2708 {
2709     setUniformGeneric<GLuint, 4, &rx::ProgramExecutableImpl::setUniform4uiv>(location, count, v);
2710 }
2711 
2712 template <typename UniformT,
2713           GLint MatrixC,
2714           GLint MatrixR,
2715           void (rx::ProgramExecutableImpl::*
2716                     SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
setUniformMatrixGeneric(UniformLocation location,GLsizei count,GLboolean transpose,const UniformT * v)2717 void ProgramExecutable::setUniformMatrixGeneric(UniformLocation location,
2718                                                 GLsizei count,
2719                                                 GLboolean transpose,
2720                                                 const UniformT *v)
2721 {
2722     if (shouldIgnoreUniform(location))
2723     {
2724         return;
2725     }
2726 
2727     GLsizei clampedCount = clampMatrixUniformCount<MatrixC, MatrixR>(location, count, transpose, v);
2728     (mImplementation->*SetUniformMatrixFunc)(location.value, clampedCount, transpose, v);
2729 }
2730 
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2731 void ProgramExecutable::setUniformMatrix2fv(UniformLocation location,
2732                                             GLsizei count,
2733                                             GLboolean transpose,
2734                                             const GLfloat *v)
2735 {
2736     setUniformMatrixGeneric<GLfloat, 2, 2, &rx::ProgramExecutableImpl::setUniformMatrix2fv>(
2737         location, count, transpose, v);
2738 }
2739 
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2740 void ProgramExecutable::setUniformMatrix3fv(UniformLocation location,
2741                                             GLsizei count,
2742                                             GLboolean transpose,
2743                                             const GLfloat *v)
2744 {
2745     setUniformMatrixGeneric<GLfloat, 3, 3, &rx::ProgramExecutableImpl::setUniformMatrix3fv>(
2746         location, count, transpose, v);
2747 }
2748 
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2749 void ProgramExecutable::setUniformMatrix4fv(UniformLocation location,
2750                                             GLsizei count,
2751                                             GLboolean transpose,
2752                                             const GLfloat *v)
2753 {
2754     setUniformMatrixGeneric<GLfloat, 4, 4, &rx::ProgramExecutableImpl::setUniformMatrix4fv>(
2755         location, count, transpose, v);
2756 }
2757 
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2758 void ProgramExecutable::setUniformMatrix2x3fv(UniformLocation location,
2759                                               GLsizei count,
2760                                               GLboolean transpose,
2761                                               const GLfloat *v)
2762 {
2763     setUniformMatrixGeneric<GLfloat, 2, 3, &rx::ProgramExecutableImpl::setUniformMatrix2x3fv>(
2764         location, count, transpose, v);
2765 }
2766 
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2767 void ProgramExecutable::setUniformMatrix2x4fv(UniformLocation location,
2768                                               GLsizei count,
2769                                               GLboolean transpose,
2770                                               const GLfloat *v)
2771 {
2772     setUniformMatrixGeneric<GLfloat, 2, 4, &rx::ProgramExecutableImpl::setUniformMatrix2x4fv>(
2773         location, count, transpose, v);
2774 }
2775 
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2776 void ProgramExecutable::setUniformMatrix3x2fv(UniformLocation location,
2777                                               GLsizei count,
2778                                               GLboolean transpose,
2779                                               const GLfloat *v)
2780 {
2781     setUniformMatrixGeneric<GLfloat, 3, 2, &rx::ProgramExecutableImpl::setUniformMatrix3x2fv>(
2782         location, count, transpose, v);
2783 }
2784 
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2785 void ProgramExecutable::setUniformMatrix3x4fv(UniformLocation location,
2786                                               GLsizei count,
2787                                               GLboolean transpose,
2788                                               const GLfloat *v)
2789 {
2790     setUniformMatrixGeneric<GLfloat, 3, 4, &rx::ProgramExecutableImpl::setUniformMatrix3x4fv>(
2791         location, count, transpose, v);
2792 }
2793 
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2794 void ProgramExecutable::setUniformMatrix4x2fv(UniformLocation location,
2795                                               GLsizei count,
2796                                               GLboolean transpose,
2797                                               const GLfloat *v)
2798 {
2799     setUniformMatrixGeneric<GLfloat, 4, 2, &rx::ProgramExecutableImpl::setUniformMatrix4x2fv>(
2800         location, count, transpose, v);
2801 }
2802 
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2803 void ProgramExecutable::setUniformMatrix4x3fv(UniformLocation location,
2804                                               GLsizei count,
2805                                               GLboolean transpose,
2806                                               const GLfloat *v)
2807 {
2808     setUniformMatrixGeneric<GLfloat, 4, 3, &rx::ProgramExecutableImpl::setUniformMatrix4x3fv>(
2809         location, count, transpose, v);
2810 }
2811 
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2812 void ProgramExecutable::getUniformfv(const Context *context,
2813                                      UniformLocation location,
2814                                      GLfloat *v) const
2815 {
2816     const VariableLocation &uniformLocation = mUniformLocations[location.value];
2817     const LinkedUniform &uniform            = mUniforms[uniformLocation.index];
2818 
2819     if (uniform.isSampler())
2820     {
2821         *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2822         return;
2823     }
2824     else if (uniform.isImage())
2825     {
2826         *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2827         return;
2828     }
2829 
2830     const GLenum nativeType = VariableComponentType(uniform.getType());
2831     if (nativeType == GL_FLOAT)
2832     {
2833         mImplementation->getUniformfv(context, location.value, v);
2834     }
2835     else
2836     {
2837         getUniformInternal(context, v, location, nativeType,
2838                            VariableComponentCount(uniform.getType()));
2839     }
2840 }
2841 
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2842 void ProgramExecutable::getUniformiv(const Context *context,
2843                                      UniformLocation location,
2844                                      GLint *v) const
2845 {
2846     const VariableLocation &uniformLocation = mUniformLocations[location.value];
2847     const LinkedUniform &uniform            = mUniforms[uniformLocation.index];
2848 
2849     if (uniform.isSampler())
2850     {
2851         *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2852         return;
2853     }
2854     else if (uniform.isImage())
2855     {
2856         *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2857         return;
2858     }
2859 
2860     const GLenum nativeType = VariableComponentType(uniform.getType());
2861     if (nativeType == GL_INT || nativeType == GL_BOOL)
2862     {
2863         mImplementation->getUniformiv(context, location.value, v);
2864     }
2865     else
2866     {
2867         getUniformInternal(context, v, location, nativeType,
2868                            VariableComponentCount(uniform.getType()));
2869     }
2870 }
2871 
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2872 void ProgramExecutable::getUniformuiv(const Context *context,
2873                                       UniformLocation location,
2874                                       GLuint *v) const
2875 {
2876     const VariableLocation &uniformLocation = mUniformLocations[location.value];
2877     const LinkedUniform &uniform            = mUniforms[uniformLocation.index];
2878 
2879     if (uniform.isSampler())
2880     {
2881         *v = getSamplerUniformBinding(uniformLocation);
2882         return;
2883     }
2884     else if (uniform.isImage())
2885     {
2886         *v = getImageUniformBinding(uniformLocation);
2887         return;
2888     }
2889 
2890     const GLenum nativeType = VariableComponentType(uniform.getType());
2891     if (nativeType == GL_UNSIGNED_INT)
2892     {
2893         mImplementation->getUniformuiv(context, location.value, v);
2894     }
2895     else
2896     {
2897         getUniformInternal(context, v, location, nativeType,
2898                            VariableComponentCount(uniform.getType()));
2899     }
2900 }
2901 
initInterfaceBlockBindings()2902 void ProgramExecutable::initInterfaceBlockBindings()
2903 {
2904     // Set initial bindings from shader.
2905     for (size_t blockIndex = 0; blockIndex < mUniformBlocks.size(); blockIndex++)
2906     {
2907         InterfaceBlock &uniformBlock = mUniformBlocks[blockIndex];
2908         // All interface blocks either have |binding| defined, or default to binding 0.
2909         ASSERT(uniformBlock.pod.inShaderBinding >= 0);
2910         remapUniformBlockBinding({static_cast<uint32_t>(blockIndex)},
2911                                  uniformBlock.pod.inShaderBinding);
2912 
2913         // This is called on program link/binary, which means the executable has changed.  There is
2914         // no need to send any additional notifications to the contexts (where the program may be
2915         // current) or program pipeline objects (that have this program attached), because they
2916         // already assume all blocks are dirty.
2917     }
2918 }
2919 
remapUniformBlockBinding(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)2920 void ProgramExecutable::remapUniformBlockBinding(UniformBlockIndex uniformBlockIndex,
2921                                                  GLuint uniformBlockBinding)
2922 {
2923     // Remove previous binding
2924     const GLuint previousBinding = mUniformBlockIndexToBufferBinding[uniformBlockIndex.value];
2925     mUniformBufferBindingToUniformBlocks[previousBinding].reset(uniformBlockIndex.value);
2926 
2927     // Set new binding
2928     mUniformBlockIndexToBufferBinding[uniformBlockIndex.value] = uniformBlockBinding;
2929     mUniformBufferBindingToUniformBlocks[uniformBlockBinding].set(uniformBlockIndex.value);
2930 }
2931 
setUniformValuesFromBindingQualifiers()2932 void ProgramExecutable::setUniformValuesFromBindingQualifiers()
2933 {
2934     for (unsigned int samplerIndex : mPod.samplerUniformRange)
2935     {
2936         const auto &samplerUniform = mUniforms[samplerIndex];
2937         if (samplerUniform.getBinding() != -1)
2938         {
2939             const std::string &uniformName = getUniformNameByIndex(samplerIndex);
2940             UniformLocation location       = getUniformLocation(uniformName);
2941             ASSERT(location.value != -1);
2942             std::vector<GLint> boundTextureUnits;
2943             for (unsigned int elementIndex = 0;
2944                  elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
2945             {
2946                 boundTextureUnits.push_back(samplerUniform.getBinding() + elementIndex);
2947             }
2948 
2949             // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
2950             // We know it's safe not to notify the Context because this is only called after link.
2951             setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
2952                           boundTextureUnits.data());
2953         }
2954     }
2955 }
2956 
2957 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)2958 GLsizei ProgramExecutable::clampUniformCount(const VariableLocation &locationInfo,
2959                                              GLsizei count,
2960                                              int vectorSize,
2961                                              const T *v)
2962 {
2963     if (count == 1)
2964         return 1;
2965 
2966     const LinkedUniform &linkedUniform = mUniforms[locationInfo.index];
2967 
2968     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
2969     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
2970     unsigned int remainingElements =
2971         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
2972     GLsizei maxElementCount =
2973         static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
2974 
2975     if (count * vectorSize > maxElementCount)
2976     {
2977         return maxElementCount / vectorSize;
2978     }
2979 
2980     return count;
2981 }
2982 
2983 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)2984 GLsizei ProgramExecutable::clampMatrixUniformCount(UniformLocation location,
2985                                                    GLsizei count,
2986                                                    GLboolean transpose,
2987                                                    const T *v)
2988 {
2989     const VariableLocation &locationInfo = mUniformLocations[location.value];
2990 
2991     if (!transpose)
2992     {
2993         return clampUniformCount(locationInfo, count, cols * rows, v);
2994     }
2995 
2996     const LinkedUniform &linkedUniform = mUniforms[locationInfo.index];
2997 
2998     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
2999     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
3000     unsigned int remainingElements =
3001         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
3002     return std::min(count, static_cast<GLsizei>(remainingElements));
3003 }
3004 
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)3005 void ProgramExecutable::updateSamplerUniform(Context *context,
3006                                              const VariableLocation &locationInfo,
3007                                              GLsizei clampedCount,
3008                                              const GLint *v)
3009 {
3010     ASSERT(isSamplerUniformIndex(locationInfo.index));
3011     GLuint samplerIndex                    = getSamplerIndexFromUniformIndex(locationInfo.index);
3012     const SamplerBinding &samplerBinding   = mSamplerBindings[samplerIndex];
3013     std::vector<GLuint> &boundTextureUnits = mSamplerBoundTextureUnits;
3014 
3015     if (locationInfo.arrayIndex >= samplerBinding.textureUnitsCount)
3016     {
3017         return;
3018     }
3019     GLsizei safeUniformCount =
3020         std::min(clampedCount,
3021                  static_cast<GLsizei>(samplerBinding.textureUnitsCount - locationInfo.arrayIndex));
3022 
3023     // Update the sampler uniforms.
3024     for (uint16_t arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
3025     {
3026         GLint oldTextureUnit =
3027             samplerBinding.getTextureUnit(boundTextureUnits, arrayIndex + locationInfo.arrayIndex);
3028         GLint newTextureUnit = v[arrayIndex];
3029 
3030         if (oldTextureUnit == newTextureUnit)
3031         {
3032             continue;
3033         }
3034 
3035         // Update sampler's bound textureUnit
3036         boundTextureUnits[samplerBinding.textureUnitsStartIndex + arrayIndex +
3037                           locationInfo.arrayIndex] = newTextureUnit;
3038 
3039         // Update the reference counts.
3040         uint32_t &oldRefCount = mActiveSamplerRefCounts[oldTextureUnit];
3041         uint32_t &newRefCount = mActiveSamplerRefCounts[newTextureUnit];
3042         ASSERT(oldRefCount > 0);
3043         ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
3044         oldRefCount--;
3045         newRefCount++;
3046 
3047         // Check for binding type change.
3048         TextureType newSamplerType     = mActiveSamplerTypes[newTextureUnit];
3049         TextureType oldSamplerType     = mActiveSamplerTypes[oldTextureUnit];
3050         SamplerFormat newSamplerFormat = mActiveSamplerFormats[newTextureUnit];
3051         SamplerFormat oldSamplerFormat = mActiveSamplerFormats[oldTextureUnit];
3052         bool newSamplerYUV             = mActiveSamplerYUV.test(newTextureUnit);
3053 
3054         if (newRefCount == 1)
3055         {
3056             setActive(newTextureUnit, samplerBinding, mUniforms[locationInfo.index]);
3057         }
3058         else
3059         {
3060             if (newSamplerType != samplerBinding.textureType ||
3061                 newSamplerYUV != IsSamplerYUVType(samplerBinding.samplerType))
3062             {
3063                 hasSamplerTypeConflict(newTextureUnit);
3064             }
3065 
3066             if (newSamplerFormat != samplerBinding.format)
3067             {
3068                 hasSamplerFormatConflict(newTextureUnit);
3069             }
3070         }
3071 
3072         // Unset previously active sampler.
3073         if (oldRefCount == 0)
3074         {
3075             setInactive(oldTextureUnit);
3076         }
3077         else
3078         {
3079             if (oldSamplerType == TextureType::InvalidEnum ||
3080                 oldSamplerFormat == SamplerFormat::InvalidEnum)
3081             {
3082                 // Previous conflict. Check if this new change fixed the conflict.
3083                 setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
3084             }
3085         }
3086 
3087         // Update the observing PPO's executable, if any.
3088         // Do this before any of the Context work, since that uses the current ProgramExecutable,
3089         // which will be the PPO's if this Program is bound to it, rather than this Program's.
3090         if (mPod.isSeparable)
3091         {
3092             onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3093         }
3094 
3095         // Notify context.
3096         if (context)
3097         {
3098             context->onSamplerUniformChange(newTextureUnit);
3099             context->onSamplerUniformChange(oldTextureUnit);
3100         }
3101     }
3102 
3103     // Invalidate the validation cache.
3104     resetCachedValidateSamplersResult();
3105     // Inform any PPOs this Program may be bound to.
3106     onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
3107 }
3108 
3109 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
3110 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
3111 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const3112 void ProgramExecutable::getUniformInternal(const Context *context,
3113                                            DestT *dataOut,
3114                                            UniformLocation location,
3115                                            GLenum nativeType,
3116                                            int components) const
3117 {
3118     switch (nativeType)
3119     {
3120         case GL_BOOL:
3121         {
3122             GLint tempValue[16] = {0};
3123             mImplementation->getUniformiv(context, location.value, tempValue);
3124             UniformStateQueryCastLoop<GLboolean>(
3125                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3126             break;
3127         }
3128         case GL_INT:
3129         {
3130             GLint tempValue[16] = {0};
3131             mImplementation->getUniformiv(context, location.value, tempValue);
3132             UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3133                                              components);
3134             break;
3135         }
3136         case GL_UNSIGNED_INT:
3137         {
3138             GLuint tempValue[16] = {0};
3139             mImplementation->getUniformuiv(context, location.value, tempValue);
3140             UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3141                                               components);
3142             break;
3143         }
3144         case GL_FLOAT:
3145         {
3146             GLfloat tempValue[16] = {0};
3147             mImplementation->getUniformfv(context, location.value, tempValue);
3148             UniformStateQueryCastLoop<GLfloat>(
3149                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3150             break;
3151         }
3152         default:
3153             UNREACHABLE();
3154             break;
3155     }
3156 }
3157 
setDrawIDUniform(GLint drawid)3158 void ProgramExecutable::setDrawIDUniform(GLint drawid)
3159 {
3160     ASSERT(hasDrawIDUniform());
3161     mImplementation->setUniform1iv(mPod.drawIDLocation, 1, &drawid);
3162 }
3163 
setBaseVertexUniform(GLint baseVertex)3164 void ProgramExecutable::setBaseVertexUniform(GLint baseVertex)
3165 {
3166     ASSERT(hasBaseVertexUniform());
3167     if (baseVertex == mCachedBaseVertex)
3168     {
3169         return;
3170     }
3171     mCachedBaseVertex = baseVertex;
3172     mImplementation->setUniform1iv(mPod.baseVertexLocation, 1, &baseVertex);
3173 }
3174 
setBaseInstanceUniform(GLuint baseInstance)3175 void ProgramExecutable::setBaseInstanceUniform(GLuint baseInstance)
3176 {
3177     ASSERT(hasBaseInstanceUniform());
3178     if (baseInstance == mCachedBaseInstance)
3179     {
3180         return;
3181     }
3182     mCachedBaseInstance   = baseInstance;
3183     GLint baseInstanceInt = baseInstance;
3184     mImplementation->setUniform1iv(mPod.baseInstanceLocation, 1, &baseInstanceInt);
3185 }
3186 
waitForPostLinkTasks(const Context * context)3187 void ProgramExecutable::waitForPostLinkTasks(const Context *context)
3188 {
3189     if (mPostLinkSubTasks.empty())
3190     {
3191         return;
3192     }
3193 
3194     mImplementation->waitForPostLinkTasks(context);
3195 
3196     // Implementation is expected to call |onPostLinkTasksComplete|.
3197     ASSERT(mPostLinkSubTasks.empty());
3198 }
3199 
InstallExecutable(const Context * context,const SharedProgramExecutable & toInstall,SharedProgramExecutable * executable)3200 void InstallExecutable(const Context *context,
3201                        const SharedProgramExecutable &toInstall,
3202                        SharedProgramExecutable *executable)
3203 {
3204     // There should never be a need to re-install the same executable.
3205     ASSERT(toInstall.get() != executable->get());
3206 
3207     // Destroy the old executable before it gets deleted.
3208     UninstallExecutable(context, executable);
3209 
3210     // Install the new executable.
3211     *executable = toInstall;
3212 }
3213 
UninstallExecutable(const Context * context,SharedProgramExecutable * executable)3214 void UninstallExecutable(const Context *context, SharedProgramExecutable *executable)
3215 {
3216     if (executable->use_count() == 1)
3217     {
3218         (*executable)->destroy(context);
3219     }
3220 
3221     executable->reset();
3222 }
3223 
3224 }  // namespace gl
3225