• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 namespace gl
17 {
18 namespace
19 {
IncludeSameArrayElement(const std::set<std::string> & nameSet,const std::string & name)20 bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
21 {
22     std::vector<unsigned int> subscripts;
23     std::string baseName = ParseResourceName(name, &subscripts);
24     for (const std::string &nameInSet : nameSet)
25     {
26         std::vector<unsigned int> arrayIndices;
27         std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
28         if (baseName == arrayName &&
29             (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
30         {
31             return true;
32         }
33     }
34     return false;
35 }
36 
37 // Find the matching varying or field by name.
FindOutputVaryingOrField(const ProgramMergedVaryings & varyings,ShaderType stage,const std::string & name)38 const sh::ShaderVariable *FindOutputVaryingOrField(const ProgramMergedVaryings &varyings,
39                                                    ShaderType stage,
40                                                    const std::string &name)
41 {
42     const sh::ShaderVariable *var = nullptr;
43     for (const ProgramVaryingRef &ref : varyings)
44     {
45         if (ref.frontShaderStage != stage)
46         {
47             continue;
48         }
49 
50         const sh::ShaderVariable *varying = ref.get(stage);
51         if (varying->name == name)
52         {
53             var = varying;
54             break;
55         }
56         GLuint fieldIndex = 0;
57         var               = varying->findField(name, &fieldIndex);
58         if (var != nullptr)
59         {
60             break;
61         }
62     }
63     return var;
64 }
65 
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)66 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
67                             unsigned int baseLocation,
68                             unsigned int elementCount,
69                             const std::vector<VariableLocation> &reservedLocations,
70                             unsigned int variableIndex)
71 {
72     if (baseLocation + elementCount > outputLocations.size())
73     {
74         elementCount = baseLocation < outputLocations.size()
75                            ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
76                            : 0;
77     }
78     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
79     {
80         const unsigned int location = baseLocation + elementIndex;
81         if (outputLocations[location].used())
82         {
83             VariableLocation locationInfo(elementIndex, variableIndex);
84             if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
85                 reservedLocations.end())
86             {
87                 return true;
88             }
89         }
90     }
91     return false;
92 }
93 
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex,sh::ShaderVariable & outputVariable)94 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
95                            unsigned int baseLocation,
96                            unsigned int elementCount,
97                            const std::vector<VariableLocation> &reservedLocations,
98                            unsigned int variableIndex,
99                            sh::ShaderVariable &outputVariable)
100 {
101     if (baseLocation + elementCount > outputLocations.size())
102     {
103         outputLocations.resize(baseLocation + elementCount);
104     }
105     for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
106     {
107         VariableLocation locationInfo(elementIndex, variableIndex);
108         if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
109             reservedLocations.end())
110         {
111             outputVariable.location     = baseLocation;
112             const unsigned int location = baseLocation + elementIndex;
113             outputLocations[location]   = locationInfo;
114         }
115     }
116 }
117 
GetOutputLocationForLink(const ProgramAliasedBindings & fragmentOutputLocations,const sh::ShaderVariable & outputVariable)118 int GetOutputLocationForLink(const ProgramAliasedBindings &fragmentOutputLocations,
119                              const sh::ShaderVariable &outputVariable)
120 {
121     if (outputVariable.location != -1)
122     {
123         return outputVariable.location;
124     }
125     int apiLocation = fragmentOutputLocations.getBinding(outputVariable);
126     if (apiLocation != -1)
127     {
128         return apiLocation;
129     }
130     return -1;
131 }
132 
IsOutputSecondaryForLink(const ProgramAliasedBindings & fragmentOutputIndexes,const sh::ShaderVariable & outputVariable)133 bool IsOutputSecondaryForLink(const ProgramAliasedBindings &fragmentOutputIndexes,
134                               const sh::ShaderVariable &outputVariable)
135 {
136     if (outputVariable.index != -1)
137     {
138         ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
139         return (outputVariable.index == 1);
140     }
141     int apiIndex = fragmentOutputIndexes.getBinding(outputVariable);
142     if (apiIndex != -1)
143     {
144         // Index layout qualifier from the shader takes precedence, so the index from the API is
145         // checked only if the index was not set in the shader. This is not specified in the EXT
146         // spec, but is specified in desktop OpenGL specs.
147         return (apiIndex == 1);
148     }
149     // EXT_blend_func_extended: Outputs get index 0 by default.
150     return false;
151 }
152 
AddUniforms(const ShaderMap<Program * > & programs,ShaderBitSet activeShaders,std::vector<LinkedUniform> & outputUniforms,const std::function<RangeUI (const ProgramState &)> & getRange)153 RangeUI AddUniforms(const ShaderMap<Program *> &programs,
154                     ShaderBitSet activeShaders,
155                     std::vector<LinkedUniform> &outputUniforms,
156                     const std::function<RangeUI(const ProgramState &)> &getRange)
157 {
158     unsigned int startRange = static_cast<unsigned int>(outputUniforms.size());
159     for (ShaderType shaderType : activeShaders)
160     {
161         const ProgramState &programState                  = programs[shaderType]->getState();
162         const std::vector<LinkedUniform> &programUniforms = programState.getUniforms();
163         const RangeUI uniformRange                        = getRange(programState);
164 
165         outputUniforms.insert(outputUniforms.end(), programUniforms.begin() + uniformRange.low(),
166                               programUniforms.begin() + uniformRange.high());
167     }
168     return RangeUI(startRange, static_cast<unsigned int>(outputUniforms.size()));
169 }
170 
171 template <typename BlockT>
AppendActiveBlocks(ShaderType shaderType,const std::vector<BlockT> & blocksIn,std::vector<BlockT> & blocksOut)172 void AppendActiveBlocks(ShaderType shaderType,
173                         const std::vector<BlockT> &blocksIn,
174                         std::vector<BlockT> &blocksOut)
175 {
176     for (const BlockT &block : blocksIn)
177     {
178         if (block.isActive(shaderType))
179         {
180             blocksOut.push_back(block);
181         }
182     }
183 }
184 }  // anonymous namespace
185 
ProgramExecutable()186 ProgramExecutable::ProgramExecutable()
187     : mMaxActiveAttribLocation(0),
188       mAttributesTypeMask(0),
189       mAttributesMask(0),
190       mActiveSamplerRefCounts{},
191       mCanDrawWith(false),
192       mYUVOutput(false),
193       mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
194       mDefaultUniformRange(0, 0),
195       mSamplerUniformRange(0, 0),
196       mImageUniformRange(0, 0),
197       mAtomicCounterUniformRange(0, 0),
198       mFragmentInoutRange(0, 0),
199       mUsesEarlyFragmentTestsOptimization(false),
200       // [GL_EXT_geometry_shader] Table 20.22
201       mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
202       mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
203       mGeometryShaderInvocations(1),
204       mGeometryShaderMaxVertices(0),
205       mTessControlShaderVertices(0),
206       mTessGenMode(GL_NONE),
207       mTessGenSpacing(GL_NONE),
208       mTessGenVertexOrder(GL_NONE),
209       mTessGenPointMode(GL_NONE)
210 {
211     reset();
212 }
213 
ProgramExecutable(const ProgramExecutable & other)214 ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
215     : mLinkedShaderStages(other.mLinkedShaderStages),
216       mActiveAttribLocationsMask(other.mActiveAttribLocationsMask),
217       mMaxActiveAttribLocation(other.mMaxActiveAttribLocation),
218       mAttributesTypeMask(other.mAttributesTypeMask),
219       mAttributesMask(other.mAttributesMask),
220       mActiveSamplersMask(other.mActiveSamplersMask),
221       mActiveSamplerRefCounts(other.mActiveSamplerRefCounts),
222       mActiveSamplerTypes(other.mActiveSamplerTypes),
223       mActiveSamplerYUV(other.mActiveSamplerYUV),
224       mActiveSamplerFormats(other.mActiveSamplerFormats),
225       mActiveSamplerShaderBits(other.mActiveSamplerShaderBits),
226       mActiveImagesMask(other.mActiveImagesMask),
227       mActiveImageShaderBits(other.mActiveImageShaderBits),
228       mCanDrawWith(other.mCanDrawWith),
229       mOutputVariables(other.mOutputVariables),
230       mOutputLocations(other.mOutputLocations),
231       mSecondaryOutputLocations(other.mSecondaryOutputLocations),
232       mYUVOutput(other.mYUVOutput),
233       mProgramInputs(other.mProgramInputs),
234       mLinkedTransformFeedbackVaryings(other.mLinkedTransformFeedbackVaryings),
235       mTransformFeedbackStrides(other.mTransformFeedbackStrides),
236       mTransformFeedbackBufferMode(other.mTransformFeedbackBufferMode),
237       mUniforms(other.mUniforms),
238       mDefaultUniformRange(other.mDefaultUniformRange),
239       mSamplerUniformRange(other.mSamplerUniformRange),
240       mImageUniformRange(other.mImageUniformRange),
241       mAtomicCounterUniformRange(other.mAtomicCounterUniformRange),
242       mUniformBlocks(other.mUniformBlocks),
243       mActiveUniformBlockBindings(other.mActiveUniformBlockBindings),
244       mAtomicCounterBuffers(other.mAtomicCounterBuffers),
245       mShaderStorageBlocks(other.mShaderStorageBlocks),
246       mFragmentInoutRange(other.mFragmentInoutRange),
247       mUsesEarlyFragmentTestsOptimization(other.mUsesEarlyFragmentTestsOptimization),
248       mAdvancedBlendEquations(other.mAdvancedBlendEquations)
249 {
250     reset();
251 }
252 
253 ProgramExecutable::~ProgramExecutable() = default;
254 
reset()255 void ProgramExecutable::reset()
256 {
257     resetInfoLog();
258     mActiveAttribLocationsMask.reset();
259     mAttributesTypeMask.reset();
260     mAttributesMask.reset();
261     mMaxActiveAttribLocation = 0;
262 
263     mActiveSamplersMask.reset();
264     mActiveSamplerRefCounts = {};
265     mActiveSamplerTypes.fill(TextureType::InvalidEnum);
266     mActiveSamplerYUV.reset();
267     mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
268 
269     mActiveImagesMask.reset();
270 
271     mProgramInputs.clear();
272     mLinkedTransformFeedbackVaryings.clear();
273     mTransformFeedbackStrides.clear();
274     mUniforms.clear();
275     mUniformBlocks.clear();
276     mActiveUniformBlockBindings.reset();
277     mShaderStorageBlocks.clear();
278     mAtomicCounterBuffers.clear();
279     mOutputVariables.clear();
280     mOutputLocations.clear();
281     mActiveOutputVariablesMask.reset();
282     mSecondaryOutputLocations.clear();
283     mYUVOutput = false;
284     mSamplerBindings.clear();
285     mImageBindings.clear();
286 
287     mDefaultUniformRange       = RangeUI(0, 0);
288     mSamplerUniformRange       = RangeUI(0, 0);
289     mImageUniformRange         = RangeUI(0, 0);
290     mAtomicCounterUniformRange = RangeUI(0, 0);
291 
292     mFragmentInoutRange                 = RangeUI(0, 0);
293     mUsesEarlyFragmentTestsOptimization = false;
294     mAdvancedBlendEquations.reset();
295 
296     mGeometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
297     mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
298     mGeometryShaderInvocations         = 1;
299     mGeometryShaderMaxVertices         = 0;
300 
301     mTessControlShaderVertices = 0;
302     mTessGenMode               = GL_NONE;
303     mTessGenSpacing            = GL_NONE;
304     mTessGenVertexOrder        = GL_NONE;
305     mTessGenPointMode          = GL_NONE;
306 
307     mOutputVariableTypes.clear();
308     mDrawBufferTypeMask.reset();
309 }
310 
load(bool isSeparable,gl::BinaryInputStream * stream)311 void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
312 {
313     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
314                   "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
315                   "mask fit into 32 bits each");
316     mAttributesTypeMask        = gl::ComponentTypeMask(stream->readInt<uint32_t>());
317     mAttributesMask            = gl::AttributesMask(stream->readInt<uint32_t>());
318     mActiveAttribLocationsMask = gl::AttributesMask(stream->readInt<uint32_t>());
319     mMaxActiveAttribLocation   = stream->readInt<unsigned int>();
320 
321     unsigned int fragmentInoutRangeLow  = stream->readInt<uint32_t>();
322     unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>();
323     mFragmentInoutRange                 = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh);
324 
325     mUsesEarlyFragmentTestsOptimization = stream->readBool();
326 
327     static_assert(sizeof(mAdvancedBlendEquations.bits()) == sizeof(uint32_t));
328     mAdvancedBlendEquations = BlendEquationBitSet(stream->readInt<uint32_t>());
329 
330     mLinkedShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
331 
332     mGeometryShaderInputPrimitiveType  = stream->readEnum<PrimitiveMode>();
333     mGeometryShaderOutputPrimitiveType = stream->readEnum<PrimitiveMode>();
334     mGeometryShaderInvocations         = stream->readInt<int>();
335     mGeometryShaderMaxVertices         = stream->readInt<int>();
336 
337     mTessControlShaderVertices = stream->readInt<int>();
338     mTessGenMode               = stream->readInt<GLenum>();
339     mTessGenSpacing            = stream->readInt<GLenum>();
340     mTessGenVertexOrder        = stream->readInt<GLenum>();
341     mTessGenPointMode          = stream->readInt<GLenum>();
342 
343     size_t attribCount = stream->readInt<size_t>();
344     ASSERT(getProgramInputs().empty());
345     for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
346     {
347         sh::ShaderVariable attrib;
348         LoadShaderVar(stream, &attrib);
349         attrib.location = stream->readInt<int>();
350         mProgramInputs.push_back(attrib);
351     }
352 
353     size_t uniformCount = stream->readInt<size_t>();
354     ASSERT(getUniforms().empty());
355     for (size_t uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
356     {
357         LinkedUniform uniform;
358         LoadShaderVar(stream, &uniform);
359 
360         uniform.bufferIndex = stream->readInt<int>();
361         LoadBlockMemberInfo(stream, &uniform.blockInfo);
362 
363         stream->readIntVector<unsigned int>(&uniform.outerArraySizes);
364         uniform.outerArrayOffset = stream->readInt<unsigned int>();
365 
366         uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
367 
368         // Active shader info
369         for (ShaderType shaderType : gl::AllShaderTypes())
370         {
371             uniform.setActive(shaderType, stream->readBool());
372         }
373 
374         mUniforms.push_back(uniform);
375     }
376 
377     size_t uniformBlockCount = stream->readInt<size_t>();
378     ASSERT(getUniformBlocks().empty());
379     for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
380     {
381         InterfaceBlock uniformBlock;
382         LoadInterfaceBlock(stream, &uniformBlock);
383         mUniformBlocks.push_back(uniformBlock);
384 
385         mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
386     }
387 
388     size_t shaderStorageBlockCount = stream->readInt<size_t>();
389     ASSERT(getShaderStorageBlocks().empty());
390     for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount;
391          ++shaderStorageBlockIndex)
392     {
393         InterfaceBlock shaderStorageBlock;
394         LoadInterfaceBlock(stream, &shaderStorageBlock);
395         mShaderStorageBlocks.push_back(shaderStorageBlock);
396     }
397 
398     size_t atomicCounterBufferCount = stream->readInt<size_t>();
399     ASSERT(getAtomicCounterBuffers().empty());
400     for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
401     {
402         AtomicCounterBuffer atomicCounterBuffer;
403         LoadShaderVariableBuffer(stream, &atomicCounterBuffer);
404 
405         mAtomicCounterBuffers.push_back(atomicCounterBuffer);
406     }
407 
408     size_t transformFeedbackVaryingCount = stream->readInt<size_t>();
409     ASSERT(mLinkedTransformFeedbackVaryings.empty());
410     for (size_t transformFeedbackVaryingIndex = 0;
411          transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
412          ++transformFeedbackVaryingIndex)
413     {
414         sh::ShaderVariable varying;
415         stream->readIntVector<unsigned int>(&varying.arraySizes);
416         stream->readInt(&varying.type);
417         stream->readString(&varying.name);
418 
419         GLuint arrayIndex = stream->readInt<GLuint>();
420 
421         mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
422     }
423 
424     mTransformFeedbackBufferMode = stream->readInt<GLint>();
425 
426     size_t outputCount = stream->readInt<size_t>();
427     ASSERT(getOutputVariables().empty());
428     for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex)
429     {
430         sh::ShaderVariable output;
431         LoadShaderVar(stream, &output);
432         output.location = stream->readInt<int>();
433         output.index    = stream->readInt<int>();
434         mOutputVariables.push_back(output);
435     }
436 
437     size_t outputVarCount = stream->readInt<size_t>();
438     ASSERT(getOutputLocations().empty());
439     for (size_t outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
440     {
441         VariableLocation locationData;
442         stream->readInt(&locationData.arrayIndex);
443         stream->readInt(&locationData.index);
444         stream->readBool(&locationData.ignored);
445         mOutputLocations.push_back(locationData);
446     }
447 
448     mActiveOutputVariablesMask =
449         gl::DrawBufferMask(stream->readInt<gl::DrawBufferMask::value_type>());
450 
451     size_t outputTypeCount = stream->readInt<size_t>();
452     for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
453     {
454         mOutputVariableTypes.push_back(stream->readInt<GLenum>());
455     }
456 
457     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
458                   "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
459                   "into 32 bits each");
460     mDrawBufferTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
461 
462     stream->readBool(&mYUVOutput);
463 
464     size_t secondaryOutputVarCount = stream->readInt<size_t>();
465     ASSERT(getSecondaryOutputLocations().empty());
466     for (size_t outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex)
467     {
468         VariableLocation locationData;
469         stream->readInt(&locationData.arrayIndex);
470         stream->readInt(&locationData.index);
471         stream->readBool(&locationData.ignored);
472         mSecondaryOutputLocations.push_back(locationData);
473     }
474 
475     unsigned int defaultUniformRangeLow  = stream->readInt<unsigned int>();
476     unsigned int defaultUniformRangeHigh = stream->readInt<unsigned int>();
477     mDefaultUniformRange                 = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh);
478 
479     unsigned int samplerRangeLow  = stream->readInt<unsigned int>();
480     unsigned int samplerRangeHigh = stream->readInt<unsigned int>();
481     mSamplerUniformRange          = RangeUI(samplerRangeLow, samplerRangeHigh);
482 
483     size_t samplerCount = stream->readInt<size_t>();
484     for (size_t samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
485     {
486         TextureType textureType = stream->readEnum<TextureType>();
487         GLenum samplerType      = stream->readInt<GLenum>();
488         SamplerFormat format    = stream->readEnum<SamplerFormat>();
489         size_t bindingCount     = stream->readInt<size_t>();
490         mSamplerBindings.emplace_back(textureType, samplerType, format, bindingCount);
491     }
492 
493     unsigned int imageRangeLow  = stream->readInt<unsigned int>();
494     unsigned int imageRangeHigh = stream->readInt<unsigned int>();
495     mImageUniformRange          = RangeUI(imageRangeLow, imageRangeHigh);
496 
497     size_t imageBindingCount = stream->readInt<size_t>();
498     for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
499     {
500         size_t elementCount     = stream->readInt<size_t>();
501         TextureType textureType = static_cast<TextureType>(stream->readInt<unsigned int>());
502         ImageBinding imageBinding(elementCount, textureType);
503         for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex)
504         {
505             imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>();
506         }
507         mImageBindings.emplace_back(imageBinding);
508     }
509 
510     unsigned int atomicCounterRangeLow  = stream->readInt<unsigned int>();
511     unsigned int atomicCounterRangeHigh = stream->readInt<unsigned int>();
512     mAtomicCounterUniformRange          = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
513 
514     // These values are currently only used by PPOs, so only load them when the program is marked
515     // separable to save memory.
516     if (isSeparable)
517     {
518         for (ShaderType shaderType : mLinkedShaderStages)
519         {
520             mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
521             for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
522             {
523                 LoadShaderVar(stream, &variable);
524             }
525             mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>());
526             for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType])
527             {
528                 LoadShaderVar(stream, &variable);
529             }
530             mLinkedUniforms[shaderType].resize(stream->readInt<size_t>());
531             for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType])
532             {
533                 LoadShaderVar(stream, &variable);
534             }
535             mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>());
536             for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
537             {
538                 LoadShInterfaceBlock(stream, &shaderStorageBlock);
539             }
540             mLinkedShaderVersions[shaderType] = stream->readInt<int>();
541         }
542     }
543 }
544 
save(bool isSeparable,gl::BinaryOutputStream * stream) const545 void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) const
546 {
547     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
548                   "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
549     stream->writeInt(static_cast<uint32_t>(mAttributesTypeMask.to_ulong()));
550     stream->writeInt(static_cast<uint32_t>(mAttributesMask.to_ulong()));
551     stream->writeInt(static_cast<uint32_t>(mActiveAttribLocationsMask.to_ulong()));
552     stream->writeInt(mMaxActiveAttribLocation);
553 
554     stream->writeInt(mFragmentInoutRange.low());
555     stream->writeInt(mFragmentInoutRange.high());
556 
557     stream->writeBool(mUsesEarlyFragmentTestsOptimization);
558     stream->writeInt(mAdvancedBlendEquations.bits());
559 
560     stream->writeInt(mLinkedShaderStages.bits());
561 
562     ASSERT(mGeometryShaderInvocations >= 1 && mGeometryShaderMaxVertices >= 0);
563     stream->writeEnum(mGeometryShaderInputPrimitiveType);
564     stream->writeEnum(mGeometryShaderOutputPrimitiveType);
565     stream->writeInt(mGeometryShaderInvocations);
566     stream->writeInt(mGeometryShaderMaxVertices);
567 
568     stream->writeInt(mTessControlShaderVertices);
569     stream->writeInt(mTessGenMode);
570     stream->writeInt(mTessGenSpacing);
571     stream->writeInt(mTessGenVertexOrder);
572     stream->writeInt(mTessGenPointMode);
573 
574     stream->writeInt(getProgramInputs().size());
575     for (const sh::ShaderVariable &attrib : getProgramInputs())
576     {
577         WriteShaderVar(stream, attrib);
578         stream->writeInt(attrib.location);
579     }
580 
581     stream->writeInt(getUniforms().size());
582     for (const LinkedUniform &uniform : getUniforms())
583     {
584         WriteShaderVar(stream, uniform);
585 
586         stream->writeInt(uniform.bufferIndex);
587         WriteBlockMemberInfo(stream, uniform.blockInfo);
588 
589         stream->writeIntVector(uniform.outerArraySizes);
590         stream->writeInt(uniform.outerArrayOffset);
591 
592         // Active shader info
593         for (ShaderType shaderType : gl::AllShaderTypes())
594         {
595             stream->writeBool(uniform.isActive(shaderType));
596         }
597     }
598 
599     stream->writeInt(getUniformBlocks().size());
600     for (const InterfaceBlock &uniformBlock : getUniformBlocks())
601     {
602         WriteInterfaceBlock(stream, uniformBlock);
603     }
604 
605     stream->writeInt(getShaderStorageBlocks().size());
606     for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks())
607     {
608         WriteInterfaceBlock(stream, shaderStorageBlock);
609     }
610 
611     stream->writeInt(mAtomicCounterBuffers.size());
612     for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers())
613     {
614         WriteShaderVariableBuffer(stream, atomicCounterBuffer);
615     }
616 
617     stream->writeInt(getLinkedTransformFeedbackVaryings().size());
618     for (const auto &var : getLinkedTransformFeedbackVaryings())
619     {
620         stream->writeIntVector(var.arraySizes);
621         stream->writeInt(var.type);
622         stream->writeString(var.name);
623 
624         stream->writeIntOrNegOne(var.arrayIndex);
625     }
626 
627     stream->writeInt(getTransformFeedbackBufferMode());
628 
629     stream->writeInt(getOutputVariables().size());
630     for (const sh::ShaderVariable &output : getOutputVariables())
631     {
632         WriteShaderVar(stream, output);
633         stream->writeInt(output.location);
634         stream->writeInt(output.index);
635     }
636 
637     stream->writeInt(getOutputLocations().size());
638     for (const auto &outputVar : getOutputLocations())
639     {
640         stream->writeInt(outputVar.arrayIndex);
641         stream->writeIntOrNegOne(outputVar.index);
642         stream->writeBool(outputVar.ignored);
643     }
644 
645     stream->writeInt(static_cast<int>(mActiveOutputVariablesMask.to_ulong()));
646 
647     stream->writeInt(mOutputVariableTypes.size());
648     for (const auto &outputVariableType : mOutputVariableTypes)
649     {
650         stream->writeInt(outputVariableType);
651     }
652 
653     static_assert(
654         IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
655         "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
656     stream->writeInt(static_cast<int>(mDrawBufferTypeMask.to_ulong()));
657 
658     stream->writeBool(mYUVOutput);
659 
660     stream->writeInt(getSecondaryOutputLocations().size());
661     for (const auto &outputVar : getSecondaryOutputLocations())
662     {
663         stream->writeInt(outputVar.arrayIndex);
664         stream->writeIntOrNegOne(outputVar.index);
665         stream->writeBool(outputVar.ignored);
666     }
667 
668     stream->writeInt(getDefaultUniformRange().low());
669     stream->writeInt(getDefaultUniformRange().high());
670 
671     stream->writeInt(getSamplerUniformRange().low());
672     stream->writeInt(getSamplerUniformRange().high());
673 
674     stream->writeInt(getSamplerBindings().size());
675     for (const auto &samplerBinding : getSamplerBindings())
676     {
677         stream->writeEnum(samplerBinding.textureType);
678         stream->writeInt(samplerBinding.samplerType);
679         stream->writeEnum(samplerBinding.format);
680         stream->writeInt(samplerBinding.boundTextureUnits.size());
681     }
682 
683     stream->writeInt(getImageUniformRange().low());
684     stream->writeInt(getImageUniformRange().high());
685 
686     stream->writeInt(getImageBindings().size());
687     for (const auto &imageBinding : getImageBindings())
688     {
689         stream->writeInt(imageBinding.boundImageUnits.size());
690         stream->writeInt(static_cast<unsigned int>(imageBinding.textureType));
691         for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
692         {
693             stream->writeInt(imageBinding.boundImageUnits[i]);
694         }
695     }
696 
697     stream->writeInt(getAtomicCounterUniformRange().low());
698     stream->writeInt(getAtomicCounterUniformRange().high());
699 
700     // These values are currently only used by PPOs, so only save them when the program is marked
701     // separable to save memory.
702     if (isSeparable)
703     {
704         for (ShaderType shaderType : mLinkedShaderStages)
705         {
706             stream->writeInt(mLinkedOutputVaryings[shaderType].size());
707             for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
708             {
709                 WriteShaderVar(stream, shaderVariable);
710             }
711             stream->writeInt(mLinkedInputVaryings[shaderType].size());
712             for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType])
713             {
714                 WriteShaderVar(stream, shaderVariable);
715             }
716             stream->writeInt(mLinkedUniforms[shaderType].size());
717             for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType])
718             {
719                 WriteShaderVar(stream, shaderVariable);
720             }
721             stream->writeInt(mLinkedUniformBlocks[shaderType].size());
722             for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
723             {
724                 WriteShInterfaceBlock(stream, shaderStorageBlock);
725             }
726             stream->writeInt(mLinkedShaderVersions[shaderType]);
727         }
728     }
729 }
730 
getInfoLogLength() const731 int ProgramExecutable::getInfoLogLength() const
732 {
733     return static_cast<int>(mInfoLog.getLength());
734 }
735 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const736 void ProgramExecutable::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
737 {
738     return mInfoLog.getLog(bufSize, length, infoLog);
739 }
740 
getInfoLogString() const741 std::string ProgramExecutable::getInfoLogString() const
742 {
743     return mInfoLog.str();
744 }
745 
isAttribLocationActive(size_t attribLocation) const746 bool ProgramExecutable::isAttribLocationActive(size_t attribLocation) const
747 {
748     // TODO(timvp): http://anglebug.com/3570: Enable this assert here somehow.
749     //    ASSERT(!mLinkingState);
750     ASSERT(attribLocation < mActiveAttribLocationsMask.size());
751     return mActiveAttribLocationsMask[attribLocation];
752 }
753 
getAttributesMask() const754 AttributesMask ProgramExecutable::getAttributesMask() const
755 {
756     // TODO(timvp): http://anglebug.com/3570: Enable this assert here somehow.
757     //    ASSERT(!mLinkingState);
758     return mAttributesMask;
759 }
760 
hasDefaultUniforms() const761 bool ProgramExecutable::hasDefaultUniforms() const
762 {
763     return !getDefaultUniformRange().empty();
764 }
765 
hasTextures() const766 bool ProgramExecutable::hasTextures() const
767 {
768     return !getSamplerBindings().empty();
769 }
770 
hasUniformBuffers() const771 bool ProgramExecutable::hasUniformBuffers() const
772 {
773     return !mUniformBlocks.empty();
774 }
775 
hasStorageBuffers() const776 bool ProgramExecutable::hasStorageBuffers() const
777 {
778     return !mShaderStorageBlocks.empty();
779 }
780 
hasAtomicCounterBuffers() const781 bool ProgramExecutable::hasAtomicCounterBuffers() const
782 {
783     return !mAtomicCounterBuffers.empty();
784 }
785 
hasImages() const786 bool ProgramExecutable::hasImages() const
787 {
788     return !mImageBindings.empty();
789 }
790 
usesFramebufferFetch() const791 bool ProgramExecutable::usesFramebufferFetch() const
792 {
793     return (mFragmentInoutRange.length() > 0);
794 }
795 
getUniformIndexFromImageIndex(GLuint imageIndex) const796 GLuint ProgramExecutable::getUniformIndexFromImageIndex(GLuint imageIndex) const
797 {
798     ASSERT(imageIndex < mImageUniformRange.length());
799     return imageIndex + mImageUniformRange.low();
800 }
801 
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const802 GLuint ProgramExecutable::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
803 {
804     ASSERT(samplerIndex < mSamplerUniformRange.length());
805     return samplerIndex + mSamplerUniformRange.low();
806 }
807 
updateActiveSamplers(const ProgramState & programState)808 void ProgramExecutable::updateActiveSamplers(const ProgramState &programState)
809 {
810     const std::vector<SamplerBinding> &samplerBindings = programState.getSamplerBindings();
811 
812     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
813     {
814         const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
815         uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(samplerIndex);
816         const gl::LinkedUniform &samplerUniform = programState.getUniforms()[uniformIndex];
817 
818         for (GLint textureUnit : samplerBinding.boundTextureUnits)
819         {
820             if (++mActiveSamplerRefCounts[textureUnit] == 1)
821             {
822                 mActiveSamplerTypes[textureUnit]   = samplerBinding.textureType;
823                 mActiveSamplerYUV[textureUnit]     = IsSamplerYUVType(samplerBinding.samplerType);
824                 mActiveSamplerFormats[textureUnit] = samplerBinding.format;
825                 mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
826             }
827             else
828             {
829                 if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
830                 {
831                     // Conflicts are marked with InvalidEnum
832                     mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
833                 }
834                 if (mActiveSamplerYUV.test(textureUnit) !=
835                     IsSamplerYUVType(samplerBinding.samplerType))
836                 {
837                     mActiveSamplerYUV[textureUnit] = false;
838                 }
839                 if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
840                 {
841                     mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
842                 }
843             }
844             mActiveSamplersMask.set(textureUnit);
845         }
846     }
847 
848     // Invalidate the validation cache.
849     resetCachedValidateSamplersResult();
850 }
851 
updateActiveImages(const ProgramExecutable & executable)852 void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
853 {
854     const std::vector<ImageBinding> &imageBindings = executable.getImageBindings();
855     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
856     {
857         const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex);
858 
859         uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex);
860         const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex];
861         const ShaderBitSet shaderBits         = imageUniform.activeShaders();
862         for (GLint imageUnit : imageBinding.boundImageUnits)
863         {
864             mActiveImagesMask.set(imageUnit);
865             mActiveImageShaderBits[imageUnit] |= shaderBits;
866         }
867     }
868 }
869 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,std::vector<SamplerBinding> & samplerBindings)870 void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
871     size_t textureUnitIndex,
872     std::vector<SamplerBinding> &samplerBindings)
873 {
874     bool foundBinding         = false;
875     TextureType foundType     = TextureType::InvalidEnum;
876     bool foundYUV             = false;
877     SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
878 
879     for (const SamplerBinding &binding : samplerBindings)
880     {
881         // A conflict exists if samplers of different types are sourced by the same texture unit.
882         // We need to check all bound textures to detect this error case.
883         for (GLuint textureUnit : binding.boundTextureUnits)
884         {
885             if (textureUnit == textureUnitIndex)
886             {
887                 if (!foundBinding)
888                 {
889                     foundBinding = true;
890                     foundType    = binding.textureType;
891                     foundYUV     = IsSamplerYUVType(binding.samplerType);
892                     foundFormat  = binding.format;
893                 }
894                 else
895                 {
896                     if (foundType != binding.textureType)
897                     {
898                         foundType = TextureType::InvalidEnum;
899                     }
900                     if (foundYUV != IsSamplerYUVType(binding.samplerType))
901                     {
902                         foundYUV = false;
903                     }
904                     if (foundFormat != binding.format)
905                     {
906                         foundFormat = SamplerFormat::InvalidEnum;
907                     }
908                 }
909             }
910         }
911     }
912 
913     mActiveSamplerTypes[textureUnitIndex]   = foundType;
914     mActiveSamplerYUV[textureUnitIndex]     = foundYUV;
915     mActiveSamplerFormats[textureUnitIndex] = foundFormat;
916 }
917 
updateCanDrawWith()918 void ProgramExecutable::updateCanDrawWith()
919 {
920     mCanDrawWith = hasLinkedShaderStage(ShaderType::Vertex);
921 }
922 
saveLinkedStateInfo(const ProgramState & state)923 void ProgramExecutable::saveLinkedStateInfo(const ProgramState &state)
924 {
925     for (ShaderType shaderType : getLinkedShaderStages())
926     {
927         Shader *shader = state.getAttachedShader(shaderType);
928         ASSERT(shader);
929         mLinkedOutputVaryings[shaderType] = shader->getOutputVaryings();
930         mLinkedInputVaryings[shaderType]  = shader->getInputVaryings();
931         mLinkedShaderVersions[shaderType] = shader->getShaderVersion();
932         mLinkedUniforms[shaderType]       = shader->getUniforms();
933         mLinkedUniformBlocks[shaderType]  = shader->getUniformBlocks();
934     }
935 }
936 
isYUVOutput() const937 bool ProgramExecutable::isYUVOutput() const
938 {
939     return mYUVOutput;
940 }
941 
getLinkedTransformFeedbackStage() const942 ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const
943 {
944     return GetLastPreFragmentStage(mLinkedShaderStages);
945 }
946 
linkMergedVaryings(const Context * context,const ProgramMergedVaryings & mergedVaryings,const std::vector<std::string> & transformFeedbackVaryingNames,const LinkingVariables & linkingVariables,bool isSeparable,ProgramVaryingPacking * varyingPacking)947 bool ProgramExecutable::linkMergedVaryings(
948     const Context *context,
949     const ProgramMergedVaryings &mergedVaryings,
950     const std::vector<std::string> &transformFeedbackVaryingNames,
951     const LinkingVariables &linkingVariables,
952     bool isSeparable,
953     ProgramVaryingPacking *varyingPacking)
954 {
955     ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset);
956 
957     if (!linkValidateTransformFeedback(context, mergedVaryings, tfStage,
958                                        transformFeedbackVaryingNames))
959     {
960         return false;
961     }
962 
963     // Map the varyings to the register file
964     // In WebGL, we use a slightly different handling for packing variables.
965     gl::PackMode packMode = PackMode::ANGLE_RELAXED;
966     if (context->getLimitations().noFlexibleVaryingPacking)
967     {
968         // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
969         packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
970     }
971     else if (context->isWebGL())
972     {
973         packMode = PackMode::WEBGL_STRICT;
974     }
975 
976     // Build active shader stage map.
977     ShaderBitSet activeShadersMask;
978     for (ShaderType shaderType : kAllGraphicsShaderTypes)
979     {
980         // - Check for attached shaders to handle the case of a Program linking the currently
981         // attached shaders.
982         // - Check for linked shaders to handle the case of a PPO linking separable programs before
983         // drawing.
984         if (linkingVariables.isShaderStageUsedBitset[shaderType] ||
985             getLinkedShaderStages().test(shaderType))
986         {
987             activeShadersMask[shaderType] = true;
988         }
989     }
990 
991     if (!varyingPacking->collectAndPackUserVaryings(mInfoLog, context->getCaps(), packMode,
992                                                     activeShadersMask, mergedVaryings,
993                                                     transformFeedbackVaryingNames, isSeparable))
994     {
995         return false;
996     }
997 
998     gatherTransformFeedbackVaryings(mergedVaryings, tfStage, transformFeedbackVaryingNames);
999     updateTransformFeedbackStrides();
1000 
1001     return true;
1002 }
1003 
linkValidateTransformFeedback(const Context * context,const ProgramMergedVaryings & varyings,ShaderType stage,const std::vector<std::string> & transformFeedbackVaryingNames)1004 bool ProgramExecutable::linkValidateTransformFeedback(
1005     const Context *context,
1006     const ProgramMergedVaryings &varyings,
1007     ShaderType stage,
1008     const std::vector<std::string> &transformFeedbackVaryingNames)
1009 {
1010     const Version &version = context->getClientVersion();
1011 
1012     // Validate the tf names regardless of the actual program varyings.
1013     std::set<std::string> uniqueNames;
1014     for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
1015     {
1016         if (version < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
1017         {
1018             mInfoLog << "Capture of array elements is undefined and not supported.";
1019             return false;
1020         }
1021         if (version >= Version(3, 1))
1022         {
1023             if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
1024             {
1025                 mInfoLog << "Two transform feedback varyings include the same array element ("
1026                          << tfVaryingName << ").";
1027                 return false;
1028             }
1029         }
1030         else
1031         {
1032             if (uniqueNames.count(tfVaryingName) > 0)
1033             {
1034                 mInfoLog << "Two transform feedback varyings specify the same output variable ("
1035                          << tfVaryingName << ").";
1036                 return false;
1037             }
1038         }
1039         uniqueNames.insert(tfVaryingName);
1040     }
1041 
1042     // Validate against program varyings.
1043     size_t totalComponents = 0;
1044     for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
1045     {
1046         std::vector<unsigned int> subscripts;
1047         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1048 
1049         const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName);
1050         if (var == nullptr)
1051         {
1052             mInfoLog << "Transform feedback varying " << tfVaryingName
1053                      << " does not exist in the vertex shader.";
1054             return false;
1055         }
1056 
1057         // Validate the matching variable.
1058         if (var->isStruct())
1059         {
1060             mInfoLog << "Struct cannot be captured directly (" << baseName << ").";
1061             return false;
1062         }
1063 
1064         size_t elementCount   = 0;
1065         size_t componentCount = 0;
1066 
1067         if (var->isArray())
1068         {
1069             if (version < Version(3, 1))
1070             {
1071                 mInfoLog << "Capture of arrays is undefined and not supported.";
1072                 return false;
1073             }
1074 
1075             // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
1076             ASSERT(!var->isArrayOfArrays());
1077 
1078             if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
1079             {
1080                 mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
1081                 return false;
1082             }
1083             elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
1084         }
1085         else
1086         {
1087             if (!subscripts.empty())
1088             {
1089                 mInfoLog << "Varying '" << baseName
1090                          << "' is not an array to be captured by element.";
1091                 return false;
1092             }
1093             elementCount = 1;
1094         }
1095 
1096         const Caps &caps = context->getCaps();
1097 
1098         // TODO(jmadill): Investigate implementation limits on D3D11
1099         componentCount = VariableComponentCount(var->type) * elementCount;
1100         if (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
1101             componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
1102         {
1103             mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
1104                      << componentCount << ") exceed the maximum separate components ("
1105                      << caps.maxTransformFeedbackSeparateComponents << ").";
1106             return false;
1107         }
1108 
1109         totalComponents += componentCount;
1110         if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
1111             totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
1112         {
1113             mInfoLog << "Transform feedback varying total components (" << totalComponents
1114                      << ") exceed the maximum interleaved components ("
1115                      << caps.maxTransformFeedbackInterleavedComponents << ").";
1116             return false;
1117         }
1118     }
1119     return true;
1120 }
1121 
gatherTransformFeedbackVaryings(const ProgramMergedVaryings & varyings,ShaderType stage,const std::vector<std::string> & transformFeedbackVaryingNames)1122 void ProgramExecutable::gatherTransformFeedbackVaryings(
1123     const ProgramMergedVaryings &varyings,
1124     ShaderType stage,
1125     const std::vector<std::string> &transformFeedbackVaryingNames)
1126 {
1127     // Gather the linked varyings that are used for transform feedback, they should all exist.
1128     mLinkedTransformFeedbackVaryings.clear();
1129     for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
1130     {
1131         std::vector<unsigned int> subscripts;
1132         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1133         size_t subscript     = GL_INVALID_INDEX;
1134         if (!subscripts.empty())
1135         {
1136             subscript = subscripts.back();
1137         }
1138         for (const ProgramVaryingRef &ref : varyings)
1139         {
1140             if (ref.frontShaderStage != stage)
1141             {
1142                 continue;
1143             }
1144 
1145             const sh::ShaderVariable *varying = ref.get(stage);
1146             if (baseName == varying->name)
1147             {
1148                 mLinkedTransformFeedbackVaryings.emplace_back(*varying,
1149                                                               static_cast<GLuint>(subscript));
1150                 break;
1151             }
1152             else if (varying->isStruct())
1153             {
1154                 GLuint fieldIndex = 0;
1155                 const auto *field = varying->findField(tfVaryingName, &fieldIndex);
1156                 if (field != nullptr)
1157                 {
1158                     mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
1159                     break;
1160                 }
1161             }
1162         }
1163     }
1164 }
1165 
updateTransformFeedbackStrides()1166 void ProgramExecutable::updateTransformFeedbackStrides()
1167 {
1168     if (mLinkedTransformFeedbackVaryings.empty())
1169     {
1170         return;
1171     }
1172 
1173     if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
1174     {
1175         mTransformFeedbackStrides.resize(1);
1176         size_t totalSize = 0;
1177         for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
1178         {
1179             totalSize += varying.size() * VariableExternalSize(varying.type);
1180         }
1181         mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
1182     }
1183     else
1184     {
1185         mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
1186         for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
1187         {
1188             TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
1189             mTransformFeedbackStrides[i] =
1190                 static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
1191         }
1192     }
1193 }
1194 
validateSamplersImpl(InfoLog * infoLog,const Caps & caps) const1195 bool ProgramExecutable::validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const
1196 {
1197     // if any two active samplers in a program are of different types, but refer to the same
1198     // texture image unit, and this is the current program, then ValidateProgram will fail, and
1199     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
1200     for (size_t textureUnit : mActiveSamplersMask)
1201     {
1202         if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
1203         {
1204             if (infoLog)
1205             {
1206                 (*infoLog) << "Samplers of conflicting types refer to the same texture "
1207                               "image unit ("
1208                            << textureUnit << ").";
1209             }
1210 
1211             mCachedValidateSamplersResult = false;
1212             return false;
1213         }
1214 
1215         if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
1216         {
1217             if (infoLog)
1218             {
1219                 (*infoLog) << "Samplers of conflicting formats refer to the same texture "
1220                               "image unit ("
1221                            << textureUnit << ").";
1222             }
1223 
1224             mCachedValidateSamplersResult = false;
1225             return false;
1226         }
1227     }
1228 
1229     mCachedValidateSamplersResult = true;
1230     return true;
1231 }
1232 
linkValidateOutputVariables(const Caps & caps,const Extensions & extensions,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount,const std::vector<sh::ShaderVariable> & outputVariables,int fragmentShaderVersion,const ProgramAliasedBindings & fragmentOutputLocations,const ProgramAliasedBindings & fragmentOutputIndices)1233 bool ProgramExecutable::linkValidateOutputVariables(
1234     const Caps &caps,
1235     const Extensions &extensions,
1236     const Version &version,
1237     GLuint combinedImageUniformsCount,
1238     GLuint combinedShaderStorageBlocksCount,
1239     const std::vector<sh::ShaderVariable> &outputVariables,
1240     int fragmentShaderVersion,
1241     const ProgramAliasedBindings &fragmentOutputLocations,
1242     const ProgramAliasedBindings &fragmentOutputIndices)
1243 {
1244     ASSERT(mOutputVariableTypes.empty());
1245     ASSERT(mActiveOutputVariablesMask.none());
1246     ASSERT(mDrawBufferTypeMask.none());
1247     ASSERT(!mYUVOutput);
1248 
1249     // Gather output variable types
1250     for (const sh::ShaderVariable &outputVariable : outputVariables)
1251     {
1252         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
1253             outputVariable.name != "gl_FragData")
1254         {
1255             continue;
1256         }
1257 
1258         unsigned int baseLocation =
1259             (outputVariable.location == -1 ? 0u
1260                                            : static_cast<unsigned int>(outputVariable.location));
1261 
1262         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1263         // structures, so we may use getBasicTypeElementCount().
1264         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
1265         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
1266         {
1267             const unsigned int location = baseLocation + elementIndex;
1268             if (location >= mOutputVariableTypes.size())
1269             {
1270                 mOutputVariableTypes.resize(location + 1, GL_NONE);
1271             }
1272             ASSERT(location < mActiveOutputVariablesMask.size());
1273             mActiveOutputVariablesMask.set(location);
1274             mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
1275             ComponentType componentType    = GLenumToComponentType(mOutputVariableTypes[location]);
1276             SetComponentTypeMask(componentType, location, &mDrawBufferTypeMask);
1277         }
1278 
1279         if (outputVariable.yuv)
1280         {
1281             ASSERT(outputVariables.size() == 1);
1282             mYUVOutput = true;
1283         }
1284     }
1285 
1286     if (version >= ES_3_1)
1287     {
1288         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1289         // A link error will be generated if the sum of the number of active image uniforms used in
1290         // all shaders, the number of active shader storage blocks, and the number of active
1291         // fragment shader outputs exceeds the implementation-dependent value of
1292         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1293         if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
1294                 mActiveOutputVariablesMask.count() >
1295             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
1296         {
1297             mInfoLog
1298                 << "The sum of the number of active image uniforms, active shader storage blocks "
1299                    "and active fragment shader outputs exceeds "
1300                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1301                 << caps.maxCombinedShaderOutputResources << ")";
1302             return false;
1303         }
1304     }
1305 
1306     mOutputVariables = outputVariables;
1307 
1308     if (fragmentShaderVersion == 100)
1309     {
1310         return true;
1311     }
1312 
1313     // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
1314     // output array in explicit terms.
1315     //
1316     // Assuming fragData is an output array, you can defend the position that:
1317     // P1) you must support binding "fragData" because it's specified
1318     // P2) you must support querying "fragData[x]" because it's specified
1319     // P3) you must support binding "fragData[0]" because it's a frequently used pattern
1320     //
1321     // Then you can make the leap of faith:
1322     // P4) you must support binding "fragData[x]" because you support "fragData[0]"
1323     // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
1324     //
1325     // The spec brings in the "world of arrays" when it mentions binding the arrays and the
1326     // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
1327     // must infer the only possible interpretation (?). Note again: this need of interpretation
1328     // might be completely off of what GL spec logic is.
1329     //
1330     // The other complexity is that unless you implement this feature, it's hard to understand what
1331     // should happen when the client invokes the feature. You cannot add an additional error as it
1332     // is not specified. One can ignore it, but obviously it creates the discrepancies...
1333 
1334     std::vector<VariableLocation> reservedLocations;
1335 
1336     // Process any output API bindings for arrays that don't alias to the first element.
1337     for (const auto &bindingPair : fragmentOutputLocations)
1338     {
1339         const std::string &name       = bindingPair.first;
1340         const ProgramBinding &binding = bindingPair.second;
1341 
1342         size_t nameLengthWithoutArrayIndex;
1343         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1344         if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
1345         {
1346             continue;
1347         }
1348         for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1349              outputVariableIndex++)
1350         {
1351             const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
1352             // Check that the binding corresponds to an output array and its array index fits.
1353             if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
1354                 !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) ||
1355                 arrayIndex >= outputVariable.getOutermostArraySize())
1356             {
1357                 continue;
1358             }
1359 
1360             // Get the API index that corresponds to this exact binding.
1361             // This index may differ from the index used for the array's base.
1362             std::vector<VariableLocation> &outputLocations =
1363                 fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations
1364                                                                   : mOutputLocations;
1365             unsigned int location = binding.location;
1366             VariableLocation locationInfo(arrayIndex, outputVariableIndex);
1367             if (location >= outputLocations.size())
1368             {
1369                 outputLocations.resize(location + 1);
1370             }
1371             if (outputLocations[location].used())
1372             {
1373                 mInfoLog << "Location of variable " << outputVariable.name
1374                          << " conflicts with another variable.";
1375                 return false;
1376             }
1377             outputLocations[location] = locationInfo;
1378 
1379             // Note the array binding location so that it can be skipped later.
1380             reservedLocations.push_back(locationInfo);
1381         }
1382     }
1383 
1384     // Reserve locations for output variables whose location is fixed in the shader or through the
1385     // API. Otherwise, the remaining unallocated outputs will be processed later.
1386     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1387          outputVariableIndex++)
1388     {
1389         const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
1390 
1391         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1392         if (outputVariable.isBuiltIn())
1393             continue;
1394 
1395         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1396         if (fixedLocation == -1)
1397         {
1398             // Here we're only reserving locations for variables whose location is fixed.
1399             continue;
1400         }
1401         unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
1402 
1403         std::vector<VariableLocation> &outputLocations =
1404             IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
1405                 ? mSecondaryOutputLocations
1406                 : mOutputLocations;
1407 
1408         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1409         // structures, so we may use getBasicTypeElementCount().
1410         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
1411         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
1412                                    outputVariableIndex))
1413         {
1414             mInfoLog << "Location of variable " << outputVariable.name
1415                      << " conflicts with another variable.";
1416             return false;
1417         }
1418         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1419                               outputVariableIndex, mOutputVariables[outputVariableIndex]);
1420     }
1421 
1422     // Here we assign locations for the output variables that don't yet have them. Note that we're
1423     // not necessarily able to fit the variables optimally, since then we might have to try
1424     // different arrangements of output arrays. Now we just assign the locations in the order that
1425     // we got the output variables. The spec isn't clear on what kind of algorithm is required for
1426     // finding locations for the output variables, so this should be acceptable at least for now.
1427     GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
1428     if (!mSecondaryOutputLocations.empty())
1429     {
1430         // EXT_blend_func_extended: Program outputs will be validated against
1431         // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
1432         maxLocation = caps.maxDualSourceDrawBuffers;
1433     }
1434 
1435     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1436          outputVariableIndex++)
1437     {
1438         const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
1439 
1440         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1441         if (outputVariable.isBuiltIn())
1442             continue;
1443 
1444         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1445         std::vector<VariableLocation> &outputLocations =
1446             IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
1447                 ? mSecondaryOutputLocations
1448                 : mOutputLocations;
1449         unsigned int baseLocation = 0;
1450         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
1451         if (fixedLocation != -1)
1452         {
1453             // Secondary inputs might have caused the max location to drop below what has already
1454             // been explicitly assigned locations. Check for any fixed locations above the max
1455             // that should cause linking to fail.
1456             baseLocation = static_cast<unsigned int>(fixedLocation);
1457         }
1458         else
1459         {
1460             // No fixed location, so try to fit the output in unassigned locations.
1461             // Try baseLocations starting from 0 one at a time and see if the variable fits.
1462             while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
1463                                           reservedLocations, outputVariableIndex))
1464             {
1465                 baseLocation++;
1466             }
1467             AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1468                                   outputVariableIndex, mOutputVariables[outputVariableIndex]);
1469         }
1470 
1471         // Check for any elements assigned above the max location that are actually used.
1472         if (baseLocation + elementCount > maxLocation &&
1473             (baseLocation >= maxLocation ||
1474              FindUsedOutputLocation(outputLocations, maxLocation,
1475                                     baseLocation + elementCount - maxLocation, reservedLocations,
1476                                     outputVariableIndex)))
1477         {
1478             // EXT_blend_func_extended: Linking can fail:
1479             // "if the explicit binding assignments do not leave enough space for the linker to
1480             // automatically assign a location for a varying out array, which requires multiple
1481             // contiguous locations."
1482             mInfoLog << "Could not fit output variable into available locations: "
1483                      << outputVariable.name;
1484             return false;
1485         }
1486     }
1487 
1488     return true;
1489 }
1490 
linkUniforms(const Context * context,const ShaderMap<std::vector<sh::ShaderVariable>> & shaderUniforms,InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings,GLuint * combinedImageUniformsCountOut,std::vector<UnusedUniform> * unusedUniformsOutOrNull,std::vector<VariableLocation> * uniformLocationsOutOrNull)1491 bool ProgramExecutable::linkUniforms(
1492     const Context *context,
1493     const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
1494     InfoLog &infoLog,
1495     const ProgramAliasedBindings &uniformLocationBindings,
1496     GLuint *combinedImageUniformsCountOut,
1497     std::vector<UnusedUniform> *unusedUniformsOutOrNull,
1498     std::vector<VariableLocation> *uniformLocationsOutOrNull)
1499 {
1500     UniformLinker linker(mLinkedShaderStages, shaderUniforms);
1501     if (!linker.link(context->getCaps(), infoLog, uniformLocationBindings))
1502     {
1503         return false;
1504     }
1505 
1506     linker.getResults(&mUniforms, unusedUniformsOutOrNull, uniformLocationsOutOrNull);
1507 
1508     linkSamplerAndImageBindings(combinedImageUniformsCountOut);
1509 
1510     if (!linkAtomicCounterBuffers(context, infoLog))
1511     {
1512         return false;
1513     }
1514 
1515     return true;
1516 }
1517 
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)1518 void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
1519 {
1520     ASSERT(combinedImageUniforms);
1521 
1522     // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
1523     // atomic counters, images and samplers in that order.
1524     auto highIter = mUniforms.rbegin();
1525     auto lowIter  = highIter;
1526 
1527     unsigned int high = static_cast<unsigned int>(mUniforms.size());
1528     unsigned int low  = high;
1529 
1530     // Note that uniform block uniforms are not yet appended to this list.
1531     ASSERT(mUniforms.empty() || highIter->isAtomicCounter() || highIter->isImage() ||
1532            highIter->isSampler() || highIter->isInDefaultBlock() || highIter->isFragmentInOut);
1533 
1534     for (; lowIter != mUniforms.rend() && lowIter->isFragmentInOut; ++lowIter)
1535     {
1536         --low;
1537     }
1538 
1539     mFragmentInoutRange = RangeUI(low, high);
1540 
1541     highIter = lowIter;
1542     high     = low;
1543 
1544     for (; lowIter != mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter)
1545     {
1546         --low;
1547     }
1548 
1549     mAtomicCounterUniformRange = RangeUI(low, high);
1550 
1551     highIter = lowIter;
1552     high     = low;
1553 
1554     for (; lowIter != mUniforms.rend() && lowIter->isImage(); ++lowIter)
1555     {
1556         --low;
1557     }
1558 
1559     mImageUniformRange     = RangeUI(low, high);
1560     *combinedImageUniforms = 0u;
1561     // If uniform is a image type, insert it into the mImageBindings array.
1562     for (unsigned int imageIndex : mImageUniformRange)
1563     {
1564         // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
1565         // cannot load values into a uniform defined as an image. if declare without a
1566         // binding qualifier, any uniform image variable (include all elements of
1567         // unbound image array) should be bound to unit zero.
1568         auto &imageUniform      = mUniforms[imageIndex];
1569         TextureType textureType = ImageTypeToTextureType(imageUniform.type);
1570         const GLuint arraySize  = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
1571 
1572         if (imageUniform.binding == -1)
1573         {
1574             mImageBindings.emplace_back(
1575                 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
1576         }
1577         else
1578         {
1579             // The arrays of arrays are flattened to arrays, it needs to record the array offset for
1580             // the correct binding image unit.
1581             mImageBindings.emplace_back(
1582                 ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize,
1583                              imageUniform.getBasicTypeElementCount(), textureType));
1584         }
1585 
1586         *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
1587     }
1588 
1589     highIter = lowIter;
1590     high     = low;
1591 
1592     for (; lowIter != mUniforms.rend() && lowIter->isSampler(); ++lowIter)
1593     {
1594         --low;
1595     }
1596 
1597     mSamplerUniformRange = RangeUI(low, high);
1598 
1599     // If uniform is a sampler type, insert it into the mSamplerBindings array.
1600     for (unsigned int samplerIndex : mSamplerUniformRange)
1601     {
1602         const auto &samplerUniform = mUniforms[samplerIndex];
1603         TextureType textureType    = SamplerTypeToTextureType(samplerUniform.type);
1604         GLenum samplerType         = samplerUniform.typeInfo->type;
1605         unsigned int elementCount  = samplerUniform.getBasicTypeElementCount();
1606         SamplerFormat format       = samplerUniform.typeInfo->samplerFormat;
1607         mSamplerBindings.emplace_back(textureType, samplerType, format, elementCount);
1608     }
1609 
1610     // Whatever is left constitutes the default uniforms.
1611     mDefaultUniformRange = RangeUI(0, low);
1612 }
1613 
linkAtomicCounterBuffers(const Context * context,InfoLog & infoLog)1614 bool ProgramExecutable::linkAtomicCounterBuffers(const Context *context, InfoLog &infoLog)
1615 {
1616     for (unsigned int index : mAtomicCounterUniformRange)
1617     {
1618         auto &uniform                      = mUniforms[index];
1619         uniform.blockInfo.offset           = uniform.offset;
1620         uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
1621         uniform.blockInfo.matrixStride     = 0;
1622         uniform.blockInfo.isRowMajorMatrix = false;
1623 
1624         bool found = false;
1625         for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount();
1626              ++bufferIndex)
1627         {
1628             auto &buffer = mAtomicCounterBuffers[bufferIndex];
1629             if (buffer.binding == uniform.binding)
1630             {
1631                 buffer.memberIndexes.push_back(index);
1632                 uniform.bufferIndex = bufferIndex;
1633                 found               = true;
1634                 buffer.unionReferencesWith(uniform);
1635                 break;
1636             }
1637         }
1638         if (!found)
1639         {
1640             AtomicCounterBuffer atomicCounterBuffer;
1641             atomicCounterBuffer.binding = uniform.binding;
1642             atomicCounterBuffer.memberIndexes.push_back(index);
1643             atomicCounterBuffer.unionReferencesWith(uniform);
1644             mAtomicCounterBuffers.push_back(atomicCounterBuffer);
1645             uniform.bufferIndex = static_cast<int>(getActiveAtomicCounterBufferCount() - 1);
1646         }
1647     }
1648 
1649     // Count each atomic counter buffer to validate against
1650     // per-stage and combined gl_Max*AtomicCounterBuffers.
1651     GLint combinedShaderACBCount           = 0;
1652     gl::ShaderMap<GLint> perShaderACBCount = {};
1653     for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount();
1654          ++bufferIndex)
1655     {
1656         AtomicCounterBuffer &acb        = mAtomicCounterBuffers[bufferIndex];
1657         const ShaderBitSet shaderStages = acb.activeShaders();
1658         for (gl::ShaderType shaderType : shaderStages)
1659         {
1660             ++perShaderACBCount[shaderType];
1661         }
1662         ++combinedShaderACBCount;
1663     }
1664     const Caps &caps = context->getCaps();
1665     if (combinedShaderACBCount > caps.maxCombinedAtomicCounterBuffers)
1666     {
1667         infoLog << " combined AtomicCounterBuffers count exceeds limit";
1668         return false;
1669     }
1670     for (gl::ShaderType stage : gl::AllShaderTypes())
1671     {
1672         if (perShaderACBCount[stage] > caps.maxShaderAtomicCounterBuffers[stage])
1673         {
1674             infoLog << GetShaderTypeString(stage)
1675                     << " shader AtomicCounterBuffers count exceeds limit";
1676             return false;
1677         }
1678     }
1679     return true;
1680 }
1681 
copyInputsFromProgram(const ProgramState & programState)1682 void ProgramExecutable::copyInputsFromProgram(const ProgramState &programState)
1683 {
1684     mProgramInputs = programState.getProgramInputs();
1685 }
1686 
copyShaderBuffersFromProgram(const ProgramState & programState,ShaderType shaderType)1687 void ProgramExecutable::copyShaderBuffersFromProgram(const ProgramState &programState,
1688                                                      ShaderType shaderType)
1689 {
1690     AppendActiveBlocks(shaderType, programState.getUniformBlocks(), mUniformBlocks);
1691     AppendActiveBlocks(shaderType, programState.getShaderStorageBlocks(), mShaderStorageBlocks);
1692     AppendActiveBlocks(shaderType, programState.getAtomicCounterBuffers(), mAtomicCounterBuffers);
1693 }
1694 
clearSamplerBindings()1695 void ProgramExecutable::clearSamplerBindings()
1696 {
1697     mSamplerBindings.clear();
1698 }
1699 
copySamplerBindingsFromProgram(const ProgramState & programState)1700 void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramState &programState)
1701 {
1702     const std::vector<SamplerBinding> &bindings = programState.getSamplerBindings();
1703     mSamplerBindings.insert(mSamplerBindings.end(), bindings.begin(), bindings.end());
1704 }
1705 
copyImageBindingsFromProgram(const ProgramState & programState)1706 void ProgramExecutable::copyImageBindingsFromProgram(const ProgramState &programState)
1707 {
1708     const std::vector<ImageBinding> &bindings = programState.getImageBindings();
1709     mImageBindings.insert(mImageBindings.end(), bindings.begin(), bindings.end());
1710 }
1711 
copyOutputsFromProgram(const ProgramState & programState)1712 void ProgramExecutable::copyOutputsFromProgram(const ProgramState &programState)
1713 {
1714     mOutputVariables          = programState.getOutputVariables();
1715     mOutputLocations          = programState.getOutputLocations();
1716     mSecondaryOutputLocations = programState.getSecondaryOutputLocations();
1717 }
1718 
copyUniformsFromProgramMap(const ShaderMap<Program * > & programs)1719 void ProgramExecutable::copyUniformsFromProgramMap(const ShaderMap<Program *> &programs)
1720 {
1721     // Merge default uniforms.
1722     auto getDefaultRange = [](const ProgramState &state) { return state.getDefaultUniformRange(); };
1723     mDefaultUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getDefaultRange);
1724 
1725     // Merge sampler uniforms.
1726     auto getSamplerRange = [](const ProgramState &state) { return state.getSamplerUniformRange(); };
1727     mSamplerUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getSamplerRange);
1728 
1729     // Merge image uniforms.
1730     auto getImageRange = [](const ProgramState &state) { return state.getImageUniformRange(); };
1731     mImageUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getImageRange);
1732 
1733     // Merge atomic counter uniforms.
1734     auto getAtomicRange = [](const ProgramState &state) {
1735         return state.getAtomicCounterUniformRange();
1736     };
1737     mAtomicCounterUniformRange =
1738         AddUniforms(programs, mLinkedShaderStages, mUniforms, getAtomicRange);
1739 
1740     // Merge fragment in/out uniforms.
1741     auto getInoutRange  = [](const ProgramState &state) { return state.getFragmentInoutRange(); };
1742     mFragmentInoutRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getInoutRange);
1743 }
1744 }  // namespace gl
1745