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