• 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 
153 }  // anonymous namespace
154 
ProgramExecutable()155 ProgramExecutable::ProgramExecutable()
156     : mMaxActiveAttribLocation(0),
157       mAttributesTypeMask(0),
158       mAttributesMask(0),
159       mActiveSamplerRefCounts{},
160       mCanDrawWith(false),
161       mYUVOutput(false),
162       mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
163       mDefaultUniformRange(0, 0),
164       mSamplerUniformRange(0, 0),
165       mImageUniformRange(0, 0),
166       mFragmentInoutRange(0, 0),
167       mPipelineHasUniformBuffers(false),
168       mPipelineHasStorageBuffers(false),
169       mPipelineHasAtomicCounterBuffers(false),
170       mPipelineHasDefaultUniforms(false),
171       mPipelineHasTextures(false),
172       mPipelineHasImages(false),
173       // [GL_EXT_geometry_shader] Table 20.22
174       mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
175       mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
176       mGeometryShaderInvocations(1),
177       mGeometryShaderMaxVertices(0),
178       mTessControlShaderVertices(0),
179       mTessGenMode(GL_NONE),
180       mTessGenSpacing(GL_NONE),
181       mTessGenVertexOrder(GL_NONE),
182       mTessGenPointMode(GL_NONE)
183 {
184     reset();
185 }
186 
ProgramExecutable(const ProgramExecutable & other)187 ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
188     : mLinkedShaderStages(other.mLinkedShaderStages),
189       mActiveAttribLocationsMask(other.mActiveAttribLocationsMask),
190       mMaxActiveAttribLocation(other.mMaxActiveAttribLocation),
191       mAttributesTypeMask(other.mAttributesTypeMask),
192       mAttributesMask(other.mAttributesMask),
193       mActiveSamplersMask(other.mActiveSamplersMask),
194       mActiveSamplerRefCounts(other.mActiveSamplerRefCounts),
195       mActiveSamplerTypes(other.mActiveSamplerTypes),
196       mActiveSamplerYUV(other.mActiveSamplerYUV),
197       mActiveSamplerFormats(other.mActiveSamplerFormats),
198       mActiveSamplerShaderBits(other.mActiveSamplerShaderBits),
199       mActiveImagesMask(other.mActiveImagesMask),
200       mActiveImageShaderBits(other.mActiveImageShaderBits),
201       mCanDrawWith(other.mCanDrawWith),
202       mOutputVariables(other.mOutputVariables),
203       mOutputLocations(other.mOutputLocations),
204       mSecondaryOutputLocations(other.mSecondaryOutputLocations),
205       mYUVOutput(other.mYUVOutput),
206       mProgramInputs(other.mProgramInputs),
207       mLinkedTransformFeedbackVaryings(other.mLinkedTransformFeedbackVaryings),
208       mTransformFeedbackStrides(other.mTransformFeedbackStrides),
209       mTransformFeedbackBufferMode(other.mTransformFeedbackBufferMode),
210       mUniforms(other.mUniforms),
211       mDefaultUniformRange(other.mDefaultUniformRange),
212       mSamplerUniformRange(other.mSamplerUniformRange),
213       mUniformBlocks(other.mUniformBlocks),
214       mActiveUniformBlockBindings(other.mActiveUniformBlockBindings),
215       mAtomicCounterBuffers(other.mAtomicCounterBuffers),
216       mImageUniformRange(other.mImageUniformRange),
217       mShaderStorageBlocks(other.mShaderStorageBlocks),
218       mFragmentInoutRange(other.mFragmentInoutRange),
219       mPipelineHasUniformBuffers(other.mPipelineHasUniformBuffers),
220       mPipelineHasStorageBuffers(other.mPipelineHasStorageBuffers),
221       mPipelineHasAtomicCounterBuffers(other.mPipelineHasAtomicCounterBuffers),
222       mPipelineHasDefaultUniforms(other.mPipelineHasDefaultUniforms),
223       mPipelineHasTextures(other.mPipelineHasTextures),
224       mPipelineHasImages(other.mPipelineHasImages)
225 {
226     reset();
227 }
228 
229 ProgramExecutable::~ProgramExecutable() = default;
230 
reset()231 void ProgramExecutable::reset()
232 {
233     resetInfoLog();
234     mActiveAttribLocationsMask.reset();
235     mAttributesTypeMask.reset();
236     mAttributesMask.reset();
237     mMaxActiveAttribLocation = 0;
238 
239     mActiveSamplersMask.reset();
240     mActiveSamplerRefCounts = {};
241     mActiveSamplerTypes.fill(TextureType::InvalidEnum);
242     mActiveSamplerYUV.reset();
243     mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
244 
245     mActiveImagesMask.reset();
246 
247     mProgramInputs.clear();
248     mLinkedTransformFeedbackVaryings.clear();
249     mTransformFeedbackStrides.clear();
250     mUniforms.clear();
251     mUniformBlocks.clear();
252     mActiveUniformBlockBindings.reset();
253     mShaderStorageBlocks.clear();
254     mAtomicCounterBuffers.clear();
255     mOutputVariables.clear();
256     mOutputLocations.clear();
257     mActiveOutputVariablesMask.reset();
258     mSecondaryOutputLocations.clear();
259     mYUVOutput = false;
260     mSamplerBindings.clear();
261     mImageBindings.clear();
262 
263     mPipelineHasUniformBuffers       = false;
264     mPipelineHasStorageBuffers       = false;
265     mPipelineHasAtomicCounterBuffers = false;
266     mPipelineHasDefaultUniforms      = false;
267     mPipelineHasTextures             = false;
268 
269     mGeometryShaderInputPrimitiveType  = PrimitiveMode::Triangles;
270     mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
271     mGeometryShaderInvocations         = 1;
272     mGeometryShaderMaxVertices         = 0;
273 
274     mTessControlShaderVertices = 0;
275     mTessGenMode               = GL_NONE;
276     mTessGenSpacing            = GL_NONE;
277     mTessGenVertexOrder        = GL_NONE;
278     mTessGenPointMode          = GL_NONE;
279 
280     mOutputVariableTypes.clear();
281     mDrawBufferTypeMask.reset();
282 }
283 
load(bool isSeparable,gl::BinaryInputStream * stream)284 void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
285 {
286     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
287                   "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
288                   "mask fit into 32 bits each");
289     mAttributesTypeMask        = gl::ComponentTypeMask(stream->readInt<uint32_t>());
290     mAttributesMask            = gl::AttributesMask(stream->readInt<uint32_t>());
291     mActiveAttribLocationsMask = gl::AttributesMask(stream->readInt<uint32_t>());
292     mMaxActiveAttribLocation   = stream->readInt<unsigned int>();
293 
294     unsigned int fragmentInoutRangeLow  = stream->readInt<uint32_t>();
295     unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>();
296     mFragmentInoutRange                 = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh);
297 
298     mLinkedShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
299 
300     mPipelineHasUniformBuffers       = stream->readBool();
301     mPipelineHasStorageBuffers       = stream->readBool();
302     mPipelineHasAtomicCounterBuffers = stream->readBool();
303     mPipelineHasDefaultUniforms      = stream->readBool();
304     mPipelineHasTextures             = stream->readBool();
305 
306     mGeometryShaderInputPrimitiveType  = stream->readEnum<PrimitiveMode>();
307     mGeometryShaderOutputPrimitiveType = stream->readEnum<PrimitiveMode>();
308     mGeometryShaderInvocations         = stream->readInt<int>();
309     mGeometryShaderMaxVertices         = stream->readInt<int>();
310 
311     mTessControlShaderVertices = stream->readInt<int>();
312     mTessGenMode               = stream->readInt<GLenum>();
313     mTessGenSpacing            = stream->readInt<GLenum>();
314     mTessGenVertexOrder        = stream->readInt<GLenum>();
315     mTessGenPointMode          = stream->readInt<GLenum>();
316 
317     size_t attribCount = stream->readInt<size_t>();
318     ASSERT(getProgramInputs().empty());
319     for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
320     {
321         sh::ShaderVariable attrib;
322         LoadShaderVar(stream, &attrib);
323         attrib.location = stream->readInt<int>();
324         mProgramInputs.push_back(attrib);
325     }
326 
327     size_t uniformCount = stream->readInt<size_t>();
328     ASSERT(getUniforms().empty());
329     for (size_t uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
330     {
331         LinkedUniform uniform;
332         LoadShaderVar(stream, &uniform);
333 
334         uniform.bufferIndex = stream->readInt<int>();
335         LoadBlockMemberInfo(stream, &uniform.blockInfo);
336 
337         stream->readIntVector<unsigned int>(&uniform.outerArraySizes);
338 
339         uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
340 
341         // Active shader info
342         for (ShaderType shaderType : gl::AllShaderTypes())
343         {
344             uniform.setActive(shaderType, stream->readBool());
345         }
346 
347         mUniforms.push_back(uniform);
348     }
349 
350     size_t uniformBlockCount = stream->readInt<size_t>();
351     ASSERT(getUniformBlocks().empty());
352     for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
353     {
354         InterfaceBlock uniformBlock;
355         LoadInterfaceBlock(stream, &uniformBlock);
356         mUniformBlocks.push_back(uniformBlock);
357 
358         mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
359     }
360 
361     size_t shaderStorageBlockCount = stream->readInt<size_t>();
362     ASSERT(getShaderStorageBlocks().empty());
363     for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount;
364          ++shaderStorageBlockIndex)
365     {
366         InterfaceBlock shaderStorageBlock;
367         LoadInterfaceBlock(stream, &shaderStorageBlock);
368         mShaderStorageBlocks.push_back(shaderStorageBlock);
369     }
370 
371     size_t atomicCounterBufferCount = stream->readInt<size_t>();
372     ASSERT(getAtomicCounterBuffers().empty());
373     for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
374     {
375         AtomicCounterBuffer atomicCounterBuffer;
376         LoadShaderVariableBuffer(stream, &atomicCounterBuffer);
377 
378         mAtomicCounterBuffers.push_back(atomicCounterBuffer);
379     }
380 
381     size_t transformFeedbackVaryingCount = stream->readInt<size_t>();
382     ASSERT(mLinkedTransformFeedbackVaryings.empty());
383     for (size_t transformFeedbackVaryingIndex = 0;
384          transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
385          ++transformFeedbackVaryingIndex)
386     {
387         sh::ShaderVariable varying;
388         stream->readIntVector<unsigned int>(&varying.arraySizes);
389         stream->readInt(&varying.type);
390         stream->readString(&varying.name);
391 
392         GLuint arrayIndex = stream->readInt<GLuint>();
393 
394         mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
395     }
396 
397     mTransformFeedbackBufferMode = stream->readInt<GLint>();
398 
399     size_t outputCount = stream->readInt<size_t>();
400     ASSERT(getOutputVariables().empty());
401     for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex)
402     {
403         sh::ShaderVariable output;
404         LoadShaderVar(stream, &output);
405         output.location = stream->readInt<int>();
406         output.index    = stream->readInt<int>();
407         mOutputVariables.push_back(output);
408     }
409 
410     size_t outputVarCount = stream->readInt<size_t>();
411     ASSERT(getOutputLocations().empty());
412     for (size_t outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
413     {
414         VariableLocation locationData;
415         stream->readInt(&locationData.arrayIndex);
416         stream->readInt(&locationData.index);
417         stream->readBool(&locationData.ignored);
418         mOutputLocations.push_back(locationData);
419     }
420 
421     mActiveOutputVariablesMask =
422         gl::DrawBufferMask(stream->readInt<gl::DrawBufferMask::value_type>());
423 
424     size_t outputTypeCount = stream->readInt<size_t>();
425     for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
426     {
427         mOutputVariableTypes.push_back(stream->readInt<GLenum>());
428     }
429 
430     static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
431                   "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
432                   "into 32 bits each");
433     mDrawBufferTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
434 
435     stream->readBool(&mYUVOutput);
436 
437     size_t secondaryOutputVarCount = stream->readInt<size_t>();
438     ASSERT(getSecondaryOutputLocations().empty());
439     for (size_t outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex)
440     {
441         VariableLocation locationData;
442         stream->readInt(&locationData.arrayIndex);
443         stream->readInt(&locationData.index);
444         stream->readBool(&locationData.ignored);
445         mSecondaryOutputLocations.push_back(locationData);
446     }
447 
448     unsigned int defaultUniformRangeLow  = stream->readInt<unsigned int>();
449     unsigned int defaultUniformRangeHigh = stream->readInt<unsigned int>();
450     mDefaultUniformRange                 = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh);
451 
452     unsigned int samplerRangeLow  = stream->readInt<unsigned int>();
453     unsigned int samplerRangeHigh = stream->readInt<unsigned int>();
454     mSamplerUniformRange          = RangeUI(samplerRangeLow, samplerRangeHigh);
455 
456     size_t samplerCount = stream->readInt<size_t>();
457     for (size_t samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
458     {
459         TextureType textureType = stream->readEnum<TextureType>();
460         GLenum samplerType      = stream->readInt<GLenum>();
461         SamplerFormat format    = stream->readEnum<SamplerFormat>();
462         size_t bindingCount     = stream->readInt<size_t>();
463         mSamplerBindings.emplace_back(textureType, samplerType, format, bindingCount);
464     }
465 
466     unsigned int imageRangeLow  = stream->readInt<unsigned int>();
467     unsigned int imageRangeHigh = stream->readInt<unsigned int>();
468     mImageUniformRange          = RangeUI(imageRangeLow, imageRangeHigh);
469 
470     size_t imageBindingCount = stream->readInt<size_t>();
471     for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
472     {
473         size_t elementCount     = stream->readInt<size_t>();
474         TextureType textureType = static_cast<TextureType>(stream->readInt<unsigned int>());
475         ImageBinding imageBinding(elementCount, textureType);
476         for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex)
477         {
478             imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>();
479         }
480         mImageBindings.emplace_back(imageBinding);
481     }
482 
483     // These values are currently only used by PPOs, so only load them when the program is marked
484     // separable to save memory.
485     if (isSeparable)
486     {
487         for (ShaderType shaderType : mLinkedShaderStages)
488         {
489             mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
490             for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
491             {
492                 LoadShaderVar(stream, &variable);
493             }
494             mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>());
495             for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType])
496             {
497                 LoadShaderVar(stream, &variable);
498             }
499             mLinkedUniforms[shaderType].resize(stream->readInt<size_t>());
500             for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType])
501             {
502                 LoadShaderVar(stream, &variable);
503             }
504             mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>());
505             for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
506             {
507                 LoadShInterfaceBlock(stream, &shaderStorageBlock);
508             }
509             mLinkedShaderVersions[shaderType] = stream->readInt<int>();
510         }
511     }
512 }
513 
save(bool isSeparable,gl::BinaryOutputStream * stream) const514 void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) const
515 {
516     static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
517                   "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
518     stream->writeInt(static_cast<uint32_t>(mAttributesTypeMask.to_ulong()));
519     stream->writeInt(static_cast<uint32_t>(mAttributesMask.to_ulong()));
520     stream->writeInt(static_cast<uint32_t>(mActiveAttribLocationsMask.to_ulong()));
521     stream->writeInt(mMaxActiveAttribLocation);
522 
523     stream->writeInt(mFragmentInoutRange.low());
524     stream->writeInt(mFragmentInoutRange.high());
525 
526     stream->writeInt(mLinkedShaderStages.bits());
527 
528     stream->writeBool(mPipelineHasUniformBuffers);
529     stream->writeBool(mPipelineHasStorageBuffers);
530     stream->writeBool(mPipelineHasAtomicCounterBuffers);
531     stream->writeBool(mPipelineHasDefaultUniforms);
532     stream->writeBool(mPipelineHasTextures);
533 
534     ASSERT(mGeometryShaderInvocations >= 1 && mGeometryShaderMaxVertices >= 0);
535     stream->writeEnum(mGeometryShaderInputPrimitiveType);
536     stream->writeEnum(mGeometryShaderOutputPrimitiveType);
537     stream->writeInt(mGeometryShaderInvocations);
538     stream->writeInt(mGeometryShaderMaxVertices);
539 
540     stream->writeInt(mTessControlShaderVertices);
541     stream->writeInt(mTessGenMode);
542     stream->writeInt(mTessGenSpacing);
543     stream->writeInt(mTessGenVertexOrder);
544     stream->writeInt(mTessGenPointMode);
545 
546     stream->writeInt(getProgramInputs().size());
547     for (const sh::ShaderVariable &attrib : getProgramInputs())
548     {
549         WriteShaderVar(stream, attrib);
550         stream->writeInt(attrib.location);
551     }
552 
553     stream->writeInt(getUniforms().size());
554     for (const LinkedUniform &uniform : getUniforms())
555     {
556         WriteShaderVar(stream, uniform);
557 
558         stream->writeInt(uniform.bufferIndex);
559         WriteBlockMemberInfo(stream, uniform.blockInfo);
560 
561         stream->writeIntVector(uniform.outerArraySizes);
562 
563         // Active shader info
564         for (ShaderType shaderType : gl::AllShaderTypes())
565         {
566             stream->writeBool(uniform.isActive(shaderType));
567         }
568     }
569 
570     stream->writeInt(getUniformBlocks().size());
571     for (const InterfaceBlock &uniformBlock : getUniformBlocks())
572     {
573         WriteInterfaceBlock(stream, uniformBlock);
574     }
575 
576     stream->writeInt(getShaderStorageBlocks().size());
577     for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks())
578     {
579         WriteInterfaceBlock(stream, shaderStorageBlock);
580     }
581 
582     stream->writeInt(mAtomicCounterBuffers.size());
583     for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers())
584     {
585         WriteShaderVariableBuffer(stream, atomicCounterBuffer);
586     }
587 
588     stream->writeInt(getLinkedTransformFeedbackVaryings().size());
589     for (const auto &var : getLinkedTransformFeedbackVaryings())
590     {
591         stream->writeIntVector(var.arraySizes);
592         stream->writeInt(var.type);
593         stream->writeString(var.name);
594 
595         stream->writeIntOrNegOne(var.arrayIndex);
596     }
597 
598     stream->writeInt(getTransformFeedbackBufferMode());
599 
600     stream->writeInt(getOutputVariables().size());
601     for (const sh::ShaderVariable &output : getOutputVariables())
602     {
603         WriteShaderVar(stream, output);
604         stream->writeInt(output.location);
605         stream->writeInt(output.index);
606     }
607 
608     stream->writeInt(getOutputLocations().size());
609     for (const auto &outputVar : getOutputLocations())
610     {
611         stream->writeInt(outputVar.arrayIndex);
612         stream->writeIntOrNegOne(outputVar.index);
613         stream->writeBool(outputVar.ignored);
614     }
615 
616     stream->writeInt(static_cast<int>(mActiveOutputVariablesMask.to_ulong()));
617 
618     stream->writeInt(mOutputVariableTypes.size());
619     for (const auto &outputVariableType : mOutputVariableTypes)
620     {
621         stream->writeInt(outputVariableType);
622     }
623 
624     static_assert(
625         IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
626         "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
627     stream->writeInt(static_cast<int>(mDrawBufferTypeMask.to_ulong()));
628 
629     stream->writeBool(mYUVOutput);
630 
631     stream->writeInt(getSecondaryOutputLocations().size());
632     for (const auto &outputVar : getSecondaryOutputLocations())
633     {
634         stream->writeInt(outputVar.arrayIndex);
635         stream->writeIntOrNegOne(outputVar.index);
636         stream->writeBool(outputVar.ignored);
637     }
638 
639     stream->writeInt(getDefaultUniformRange().low());
640     stream->writeInt(getDefaultUniformRange().high());
641 
642     stream->writeInt(getSamplerUniformRange().low());
643     stream->writeInt(getSamplerUniformRange().high());
644 
645     stream->writeInt(getSamplerBindings().size());
646     for (const auto &samplerBinding : getSamplerBindings())
647     {
648         stream->writeEnum(samplerBinding.textureType);
649         stream->writeInt(samplerBinding.samplerType);
650         stream->writeEnum(samplerBinding.format);
651         stream->writeInt(samplerBinding.boundTextureUnits.size());
652     }
653 
654     stream->writeInt(getImageUniformRange().low());
655     stream->writeInt(getImageUniformRange().high());
656 
657     stream->writeInt(getImageBindings().size());
658     for (const auto &imageBinding : getImageBindings())
659     {
660         stream->writeInt(imageBinding.boundImageUnits.size());
661         stream->writeInt(static_cast<unsigned int>(imageBinding.textureType));
662         for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
663         {
664             stream->writeInt(imageBinding.boundImageUnits[i]);
665         }
666     }
667 
668     // These values are currently only used by PPOs, so only save them when the program is marked
669     // separable to save memory.
670     if (isSeparable)
671     {
672         for (ShaderType shaderType : mLinkedShaderStages)
673         {
674             stream->writeInt(mLinkedOutputVaryings[shaderType].size());
675             for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
676             {
677                 WriteShaderVar(stream, shaderVariable);
678             }
679             stream->writeInt(mLinkedInputVaryings[shaderType].size());
680             for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType])
681             {
682                 WriteShaderVar(stream, shaderVariable);
683             }
684             stream->writeInt(mLinkedUniforms[shaderType].size());
685             for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType])
686             {
687                 WriteShaderVar(stream, shaderVariable);
688             }
689             stream->writeInt(mLinkedUniformBlocks[shaderType].size());
690             for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
691             {
692                 WriteShInterfaceBlock(stream, shaderStorageBlock);
693             }
694             stream->writeInt(mLinkedShaderVersions[shaderType]);
695         }
696     }
697 }
698 
getInfoLogLength() const699 int ProgramExecutable::getInfoLogLength() const
700 {
701     return static_cast<int>(mInfoLog.getLength());
702 }
703 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const704 void ProgramExecutable::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
705 {
706     return mInfoLog.getLog(bufSize, length, infoLog);
707 }
708 
getInfoLogString() const709 std::string ProgramExecutable::getInfoLogString() const
710 {
711     return mInfoLog.str();
712 }
713 
isAttribLocationActive(size_t attribLocation) const714 bool ProgramExecutable::isAttribLocationActive(size_t attribLocation) const
715 {
716     // TODO(timvp): http://anglebug.com/3570: Enable this assert here somehow.
717     //    ASSERT(!mLinkingState);
718     ASSERT(attribLocation < mActiveAttribLocationsMask.size());
719     return mActiveAttribLocationsMask[attribLocation];
720 }
721 
getAttributesMask() const722 AttributesMask ProgramExecutable::getAttributesMask() const
723 {
724     // TODO(timvp): http://anglebug.com/3570: Enable this assert here somehow.
725     //    ASSERT(!mLinkingState);
726     return mAttributesMask;
727 }
728 
hasDefaultUniforms() const729 bool ProgramExecutable::hasDefaultUniforms() const
730 {
731     return !getDefaultUniformRange().empty() || mPipelineHasDefaultUniforms;
732 }
733 
hasTextures() const734 bool ProgramExecutable::hasTextures() const
735 {
736     return !getSamplerBindings().empty() || mPipelineHasTextures;
737 }
738 
739 // TODO: http://anglebug.com/3570: Remove mHas*UniformBuffers once PPO's have valid data in
740 // mUniformBlocks
hasUniformBuffers() const741 bool ProgramExecutable::hasUniformBuffers() const
742 {
743     return !mUniformBlocks.empty() || mPipelineHasUniformBuffers;
744 }
745 
hasStorageBuffers() const746 bool ProgramExecutable::hasStorageBuffers() const
747 {
748     return !mShaderStorageBlocks.empty() || mPipelineHasStorageBuffers;
749 }
750 
hasAtomicCounterBuffers() const751 bool ProgramExecutable::hasAtomicCounterBuffers() const
752 {
753     return !mAtomicCounterBuffers.empty() || mPipelineHasAtomicCounterBuffers;
754 }
755 
hasImages() const756 bool ProgramExecutable::hasImages() const
757 {
758     return !mImageBindings.empty() || mPipelineHasImages;
759 }
760 
usesFramebufferFetch() const761 bool ProgramExecutable::usesFramebufferFetch() const
762 {
763     return (mFragmentInoutRange.length() > 0);
764 }
765 
getUniformIndexFromImageIndex(GLuint imageIndex) const766 GLuint ProgramExecutable::getUniformIndexFromImageIndex(GLuint imageIndex) const
767 {
768     ASSERT(imageIndex < mImageUniformRange.length());
769     return imageIndex + mImageUniformRange.low();
770 }
771 
updateActiveSamplers(const ProgramState & programState)772 void ProgramExecutable::updateActiveSamplers(const ProgramState &programState)
773 {
774     const std::vector<SamplerBinding> &samplerBindings = programState.getSamplerBindings();
775 
776     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
777     {
778         const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
779         uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(samplerIndex);
780         const gl::LinkedUniform &samplerUniform = programState.getUniforms()[uniformIndex];
781 
782         for (GLint textureUnit : samplerBinding.boundTextureUnits)
783         {
784             if (++mActiveSamplerRefCounts[textureUnit] == 1)
785             {
786                 mActiveSamplerTypes[textureUnit]   = samplerBinding.textureType;
787                 mActiveSamplerYUV[textureUnit]     = IsSamplerYUVType(samplerBinding.samplerType);
788                 mActiveSamplerFormats[textureUnit] = samplerBinding.format;
789                 mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
790             }
791             else
792             {
793                 if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
794                 {
795                     // Conflicts are marked with InvalidEnum
796                     mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
797                 }
798                 if (mActiveSamplerYUV.test(textureUnit) !=
799                     IsSamplerYUVType(samplerBinding.samplerType))
800                 {
801                     mActiveSamplerYUV[textureUnit] = false;
802                 }
803                 if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
804                 {
805                     mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
806                 }
807             }
808             mActiveSamplersMask.set(textureUnit);
809         }
810     }
811 
812     // Invalidate the validation cache.
813     resetCachedValidateSamplersResult();
814 }
815 
updateActiveImages(const ProgramExecutable & executable)816 void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
817 {
818     const std::vector<ImageBinding> &imageBindings = executable.getImageBindings();
819     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
820     {
821         const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex);
822 
823         uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex);
824         const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex];
825         const ShaderBitSet shaderBits         = imageUniform.activeShaders();
826         for (GLint imageUnit : imageBinding.boundImageUnits)
827         {
828             mActiveImagesMask.set(imageUnit);
829             mActiveImageShaderBits[imageUnit] |= shaderBits;
830         }
831     }
832 }
833 
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,std::vector<SamplerBinding> & samplerBindings)834 void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
835     size_t textureUnitIndex,
836     std::vector<SamplerBinding> &samplerBindings)
837 {
838     bool foundBinding         = false;
839     TextureType foundType     = TextureType::InvalidEnum;
840     bool foundYUV             = false;
841     SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
842 
843     for (const SamplerBinding &binding : samplerBindings)
844     {
845         // A conflict exists if samplers of different types are sourced by the same texture unit.
846         // We need to check all bound textures to detect this error case.
847         for (GLuint textureUnit : binding.boundTextureUnits)
848         {
849             if (textureUnit == textureUnitIndex)
850             {
851                 if (!foundBinding)
852                 {
853                     foundBinding = true;
854                     foundType    = binding.textureType;
855                     foundYUV     = IsSamplerYUVType(binding.samplerType);
856                     foundFormat  = binding.format;
857                 }
858                 else
859                 {
860                     if (foundType != binding.textureType)
861                     {
862                         foundType = TextureType::InvalidEnum;
863                     }
864                     if (foundYUV != IsSamplerYUVType(binding.samplerType))
865                     {
866                         foundYUV = false;
867                     }
868                     if (foundFormat != binding.format)
869                     {
870                         foundFormat = SamplerFormat::InvalidEnum;
871                     }
872                 }
873             }
874         }
875     }
876 
877     mActiveSamplerTypes[textureUnitIndex]   = foundType;
878     mActiveSamplerYUV[textureUnitIndex]     = foundYUV;
879     mActiveSamplerFormats[textureUnitIndex] = foundFormat;
880 }
881 
updateCanDrawWith()882 void ProgramExecutable::updateCanDrawWith()
883 {
884     mCanDrawWith = hasLinkedShaderStage(ShaderType::Vertex);
885 }
886 
saveLinkedStateInfo(const ProgramState & state)887 void ProgramExecutable::saveLinkedStateInfo(const ProgramState &state)
888 {
889     for (ShaderType shaderType : getLinkedShaderStages())
890     {
891         Shader *shader = state.getAttachedShader(shaderType);
892         ASSERT(shader);
893         mLinkedOutputVaryings[shaderType] = shader->getOutputVaryings();
894         mLinkedInputVaryings[shaderType]  = shader->getInputVaryings();
895         mLinkedShaderVersions[shaderType] = shader->getShaderVersion();
896         mLinkedUniforms[shaderType]       = shader->getUniforms();
897         mLinkedUniformBlocks[shaderType]  = shader->getUniformBlocks();
898     }
899 }
900 
isYUVOutput() const901 bool ProgramExecutable::isYUVOutput() const
902 {
903     return mYUVOutput;
904 }
905 
getLinkedTransformFeedbackStage() const906 ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const
907 {
908     return GetLastPreFragmentStage(mLinkedShaderStages);
909 }
910 
linkMergedVaryings(const Context * context,const ProgramMergedVaryings & mergedVaryings,const std::vector<std::string> & transformFeedbackVaryingNames,const LinkingVariables & linkingVariables,bool isSeparable,ProgramVaryingPacking * varyingPacking)911 bool ProgramExecutable::linkMergedVaryings(
912     const Context *context,
913     const ProgramMergedVaryings &mergedVaryings,
914     const std::vector<std::string> &transformFeedbackVaryingNames,
915     const LinkingVariables &linkingVariables,
916     bool isSeparable,
917     ProgramVaryingPacking *varyingPacking)
918 {
919     ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset);
920 
921     if (!linkValidateTransformFeedback(context, mergedVaryings, tfStage,
922                                        transformFeedbackVaryingNames))
923     {
924         return false;
925     }
926 
927     // Map the varyings to the register file
928     // In WebGL, we use a slightly different handling for packing variables.
929     gl::PackMode packMode = PackMode::ANGLE_RELAXED;
930     if (context->getLimitations().noFlexibleVaryingPacking)
931     {
932         // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
933         packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
934     }
935     else if (context->isWebGL())
936     {
937         packMode = PackMode::WEBGL_STRICT;
938     }
939 
940     // Build active shader stage map.
941     ShaderBitSet activeShadersMask;
942     for (ShaderType shaderType : kAllGraphicsShaderTypes)
943     {
944         // - Check for attached shaders to handle the case of a Program linking the currently
945         // attached shaders.
946         // - Check for linked shaders to handle the case of a PPO linking separable programs before
947         // drawing.
948         if (linkingVariables.isShaderStageUsedBitset[shaderType] ||
949             getLinkedShaderStages().test(shaderType))
950         {
951             activeShadersMask[shaderType] = true;
952         }
953     }
954 
955     if (!varyingPacking->collectAndPackUserVaryings(mInfoLog, context->getCaps(), packMode,
956                                                     activeShadersMask, mergedVaryings,
957                                                     transformFeedbackVaryingNames, isSeparable))
958     {
959         return false;
960     }
961 
962     gatherTransformFeedbackVaryings(mergedVaryings, tfStage, transformFeedbackVaryingNames);
963     updateTransformFeedbackStrides();
964 
965     return true;
966 }
967 
linkValidateTransformFeedback(const Context * context,const ProgramMergedVaryings & varyings,ShaderType stage,const std::vector<std::string> & transformFeedbackVaryingNames)968 bool ProgramExecutable::linkValidateTransformFeedback(
969     const Context *context,
970     const ProgramMergedVaryings &varyings,
971     ShaderType stage,
972     const std::vector<std::string> &transformFeedbackVaryingNames)
973 {
974     const Version &version = context->getClientVersion();
975 
976     // Validate the tf names regardless of the actual program varyings.
977     std::set<std::string> uniqueNames;
978     for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
979     {
980         if (version < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
981         {
982             mInfoLog << "Capture of array elements is undefined and not supported.";
983             return false;
984         }
985         if (version >= Version(3, 1))
986         {
987             if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
988             {
989                 mInfoLog << "Two transform feedback varyings include the same array element ("
990                          << tfVaryingName << ").";
991                 return false;
992             }
993         }
994         else
995         {
996             if (uniqueNames.count(tfVaryingName) > 0)
997             {
998                 mInfoLog << "Two transform feedback varyings specify the same output variable ("
999                          << tfVaryingName << ").";
1000                 return false;
1001             }
1002         }
1003         uniqueNames.insert(tfVaryingName);
1004     }
1005 
1006     // Validate against program varyings.
1007     size_t totalComponents = 0;
1008     for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
1009     {
1010         std::vector<unsigned int> subscripts;
1011         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1012 
1013         const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName);
1014         if (var == nullptr)
1015         {
1016             mInfoLog << "Transform feedback varying " << tfVaryingName
1017                      << " does not exist in the vertex shader.";
1018             return false;
1019         }
1020 
1021         // Validate the matching variable.
1022         if (var->isStruct())
1023         {
1024             mInfoLog << "Struct cannot be captured directly (" << baseName << ").";
1025             return false;
1026         }
1027 
1028         size_t elementCount   = 0;
1029         size_t componentCount = 0;
1030 
1031         if (var->isArray())
1032         {
1033             if (version < Version(3, 1))
1034             {
1035                 mInfoLog << "Capture of arrays is undefined and not supported.";
1036                 return false;
1037             }
1038 
1039             // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
1040             ASSERT(!var->isArrayOfArrays());
1041 
1042             if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
1043             {
1044                 mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
1045                 return false;
1046             }
1047             elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
1048         }
1049         else
1050         {
1051             if (!subscripts.empty())
1052             {
1053                 mInfoLog << "Varying '" << baseName
1054                          << "' is not an array to be captured by element.";
1055                 return false;
1056             }
1057             elementCount = 1;
1058         }
1059 
1060         const Caps &caps = context->getCaps();
1061 
1062         // TODO(jmadill): Investigate implementation limits on D3D11
1063         componentCount = VariableComponentCount(var->type) * elementCount;
1064         if (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
1065             componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
1066         {
1067             mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
1068                      << componentCount << ") exceed the maximum separate components ("
1069                      << caps.maxTransformFeedbackSeparateComponents << ").";
1070             return false;
1071         }
1072 
1073         totalComponents += componentCount;
1074         if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
1075             totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
1076         {
1077             mInfoLog << "Transform feedback varying total components (" << totalComponents
1078                      << ") exceed the maximum interleaved components ("
1079                      << caps.maxTransformFeedbackInterleavedComponents << ").";
1080             return false;
1081         }
1082     }
1083     return true;
1084 }
1085 
gatherTransformFeedbackVaryings(const ProgramMergedVaryings & varyings,ShaderType stage,const std::vector<std::string> & transformFeedbackVaryingNames)1086 void ProgramExecutable::gatherTransformFeedbackVaryings(
1087     const ProgramMergedVaryings &varyings,
1088     ShaderType stage,
1089     const std::vector<std::string> &transformFeedbackVaryingNames)
1090 {
1091     // Gather the linked varyings that are used for transform feedback, they should all exist.
1092     mLinkedTransformFeedbackVaryings.clear();
1093     for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
1094     {
1095         std::vector<unsigned int> subscripts;
1096         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
1097         size_t subscript     = GL_INVALID_INDEX;
1098         if (!subscripts.empty())
1099         {
1100             subscript = subscripts.back();
1101         }
1102         for (const ProgramVaryingRef &ref : varyings)
1103         {
1104             if (ref.frontShaderStage != stage)
1105             {
1106                 continue;
1107             }
1108 
1109             const sh::ShaderVariable *varying = ref.get(stage);
1110             if (baseName == varying->name)
1111             {
1112                 mLinkedTransformFeedbackVaryings.emplace_back(*varying,
1113                                                               static_cast<GLuint>(subscript));
1114                 break;
1115             }
1116             else if (varying->isStruct())
1117             {
1118                 GLuint fieldIndex = 0;
1119                 const auto *field = varying->findField(tfVaryingName, &fieldIndex);
1120                 if (field != nullptr)
1121                 {
1122                     mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
1123                     break;
1124                 }
1125             }
1126         }
1127     }
1128 }
1129 
updateTransformFeedbackStrides()1130 void ProgramExecutable::updateTransformFeedbackStrides()
1131 {
1132     if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
1133     {
1134         mTransformFeedbackStrides.resize(1);
1135         size_t totalSize = 0;
1136         for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
1137         {
1138             totalSize += varying.size() * VariableExternalSize(varying.type);
1139         }
1140         mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
1141     }
1142     else
1143     {
1144         mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
1145         for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
1146         {
1147             TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
1148             mTransformFeedbackStrides[i] =
1149                 static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
1150         }
1151     }
1152 }
1153 
validateSamplersImpl(InfoLog * infoLog,const Caps & caps) const1154 bool ProgramExecutable::validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const
1155 {
1156     // if any two active samplers in a program are of different types, but refer to the same
1157     // texture image unit, and this is the current program, then ValidateProgram will fail, and
1158     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
1159     for (size_t textureUnit : mActiveSamplersMask)
1160     {
1161         if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
1162         {
1163             if (infoLog)
1164             {
1165                 (*infoLog) << "Samplers of conflicting types refer to the same texture "
1166                               "image unit ("
1167                            << textureUnit << ").";
1168             }
1169 
1170             mCachedValidateSamplersResult = false;
1171             return false;
1172         }
1173 
1174         if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
1175         {
1176             if (infoLog)
1177             {
1178                 (*infoLog) << "Samplers of conflicting formats refer to the same texture "
1179                               "image unit ("
1180                            << textureUnit << ").";
1181             }
1182 
1183             mCachedValidateSamplersResult = false;
1184             return false;
1185         }
1186     }
1187 
1188     mCachedValidateSamplersResult = true;
1189     return true;
1190 }
1191 
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)1192 bool ProgramExecutable::linkValidateOutputVariables(
1193     const Caps &caps,
1194     const Extensions &extensions,
1195     const Version &version,
1196     GLuint combinedImageUniformsCount,
1197     GLuint combinedShaderStorageBlocksCount,
1198     const std::vector<sh::ShaderVariable> &outputVariables,
1199     int fragmentShaderVersion,
1200     const ProgramAliasedBindings &fragmentOutputLocations,
1201     const ProgramAliasedBindings &fragmentOutputIndices)
1202 {
1203     ASSERT(mOutputVariableTypes.empty());
1204     ASSERT(mActiveOutputVariablesMask.none());
1205     ASSERT(mDrawBufferTypeMask.none());
1206     ASSERT(!mYUVOutput);
1207 
1208     // Gather output variable types
1209     for (const sh::ShaderVariable &outputVariable : outputVariables)
1210     {
1211         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
1212             outputVariable.name != "gl_FragData")
1213         {
1214             continue;
1215         }
1216 
1217         unsigned int baseLocation =
1218             (outputVariable.location == -1 ? 0u
1219                                            : static_cast<unsigned int>(outputVariable.location));
1220 
1221         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1222         // structures, so we may use getBasicTypeElementCount().
1223         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
1224         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
1225         {
1226             const unsigned int location = baseLocation + elementIndex;
1227             if (location >= mOutputVariableTypes.size())
1228             {
1229                 mOutputVariableTypes.resize(location + 1, GL_NONE);
1230             }
1231             ASSERT(location < mActiveOutputVariablesMask.size());
1232             mActiveOutputVariablesMask.set(location);
1233             mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
1234             ComponentType componentType    = GLenumToComponentType(mOutputVariableTypes[location]);
1235             SetComponentTypeMask(componentType, location, &mDrawBufferTypeMask);
1236         }
1237 
1238         if (outputVariable.yuv)
1239         {
1240             ASSERT(outputVariables.size() == 1);
1241             mYUVOutput = true;
1242         }
1243     }
1244 
1245     if (version >= ES_3_1)
1246     {
1247         // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1248         // A link error will be generated if the sum of the number of active image uniforms used in
1249         // all shaders, the number of active shader storage blocks, and the number of active
1250         // fragment shader outputs exceeds the implementation-dependent value of
1251         // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1252         if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
1253                 mActiveOutputVariablesMask.count() >
1254             static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
1255         {
1256             mInfoLog
1257                 << "The sum of the number of active image uniforms, active shader storage blocks "
1258                    "and active fragment shader outputs exceeds "
1259                    "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1260                 << caps.maxCombinedShaderOutputResources << ")";
1261             return false;
1262         }
1263     }
1264 
1265     mOutputVariables = outputVariables;
1266 
1267     if (fragmentShaderVersion == 100)
1268     {
1269         return true;
1270     }
1271 
1272     // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
1273     // output array in explicit terms.
1274     //
1275     // Assuming fragData is an output array, you can defend the position that:
1276     // P1) you must support binding "fragData" because it's specified
1277     // P2) you must support querying "fragData[x]" because it's specified
1278     // P3) you must support binding "fragData[0]" because it's a frequently used pattern
1279     //
1280     // Then you can make the leap of faith:
1281     // P4) you must support binding "fragData[x]" because you support "fragData[0]"
1282     // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
1283     //
1284     // The spec brings in the "world of arrays" when it mentions binding the arrays and the
1285     // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
1286     // must infer the only possible interpretation (?). Note again: this need of interpretation
1287     // might be completely off of what GL spec logic is.
1288     //
1289     // The other complexity is that unless you implement this feature, it's hard to understand what
1290     // should happen when the client invokes the feature. You cannot add an additional error as it
1291     // is not specified. One can ignore it, but obviously it creates the discrepancies...
1292 
1293     std::vector<VariableLocation> reservedLocations;
1294 
1295     // Process any output API bindings for arrays that don't alias to the first element.
1296     for (const auto &bindingPair : fragmentOutputLocations)
1297     {
1298         const std::string &name       = bindingPair.first;
1299         const ProgramBinding &binding = bindingPair.second;
1300 
1301         size_t nameLengthWithoutArrayIndex;
1302         unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1303         if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
1304         {
1305             continue;
1306         }
1307         for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1308              outputVariableIndex++)
1309         {
1310             const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
1311             // Check that the binding corresponds to an output array and its array index fits.
1312             if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
1313                 !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) ||
1314                 arrayIndex >= outputVariable.getOutermostArraySize())
1315             {
1316                 continue;
1317             }
1318 
1319             // Get the API index that corresponds to this exact binding.
1320             // This index may differ from the index used for the array's base.
1321             std::vector<VariableLocation> &outputLocations =
1322                 fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations
1323                                                                   : mOutputLocations;
1324             unsigned int location = binding.location;
1325             VariableLocation locationInfo(arrayIndex, outputVariableIndex);
1326             if (location >= outputLocations.size())
1327             {
1328                 outputLocations.resize(location + 1);
1329             }
1330             if (outputLocations[location].used())
1331             {
1332                 mInfoLog << "Location of variable " << outputVariable.name
1333                          << " conflicts with another variable.";
1334                 return false;
1335             }
1336             outputLocations[location] = locationInfo;
1337 
1338             // Note the array binding location so that it can be skipped later.
1339             reservedLocations.push_back(locationInfo);
1340         }
1341     }
1342 
1343     // Reserve locations for output variables whose location is fixed in the shader or through the
1344     // API. Otherwise, the remaining unallocated outputs will be processed later.
1345     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1346          outputVariableIndex++)
1347     {
1348         const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
1349 
1350         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1351         if (outputVariable.isBuiltIn())
1352             continue;
1353 
1354         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1355         if (fixedLocation == -1)
1356         {
1357             // Here we're only reserving locations for variables whose location is fixed.
1358             continue;
1359         }
1360         unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
1361 
1362         std::vector<VariableLocation> &outputLocations =
1363             IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
1364                 ? mSecondaryOutputLocations
1365                 : mOutputLocations;
1366 
1367         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
1368         // structures, so we may use getBasicTypeElementCount().
1369         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
1370         if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
1371                                    outputVariableIndex))
1372         {
1373             mInfoLog << "Location of variable " << outputVariable.name
1374                      << " conflicts with another variable.";
1375             return false;
1376         }
1377         AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1378                               outputVariableIndex, mOutputVariables[outputVariableIndex]);
1379     }
1380 
1381     // Here we assign locations for the output variables that don't yet have them. Note that we're
1382     // not necessarily able to fit the variables optimally, since then we might have to try
1383     // different arrangements of output arrays. Now we just assign the locations in the order that
1384     // we got the output variables. The spec isn't clear on what kind of algorithm is required for
1385     // finding locations for the output variables, so this should be acceptable at least for now.
1386     GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
1387     if (!mSecondaryOutputLocations.empty())
1388     {
1389         // EXT_blend_func_extended: Program outputs will be validated against
1390         // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
1391         maxLocation = caps.maxDualSourceDrawBuffers;
1392     }
1393 
1394     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
1395          outputVariableIndex++)
1396     {
1397         const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
1398 
1399         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
1400         if (outputVariable.isBuiltIn())
1401             continue;
1402 
1403         int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
1404         std::vector<VariableLocation> &outputLocations =
1405             IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
1406                 ? mSecondaryOutputLocations
1407                 : mOutputLocations;
1408         unsigned int baseLocation = 0;
1409         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
1410         if (fixedLocation != -1)
1411         {
1412             // Secondary inputs might have caused the max location to drop below what has already
1413             // been explicitly assigned locations. Check for any fixed locations above the max
1414             // that should cause linking to fail.
1415             baseLocation = static_cast<unsigned int>(fixedLocation);
1416         }
1417         else
1418         {
1419             // No fixed location, so try to fit the output in unassigned locations.
1420             // Try baseLocations starting from 0 one at a time and see if the variable fits.
1421             while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
1422                                           reservedLocations, outputVariableIndex))
1423             {
1424                 baseLocation++;
1425             }
1426             AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
1427                                   outputVariableIndex, mOutputVariables[outputVariableIndex]);
1428         }
1429 
1430         // Check for any elements assigned above the max location that are actually used.
1431         if (baseLocation + elementCount > maxLocation &&
1432             (baseLocation >= maxLocation ||
1433              FindUsedOutputLocation(outputLocations, maxLocation,
1434                                     baseLocation + elementCount - maxLocation, reservedLocations,
1435                                     outputVariableIndex)))
1436         {
1437             // EXT_blend_func_extended: Linking can fail:
1438             // "if the explicit binding assignments do not leave enough space for the linker to
1439             // automatically assign a location for a varying out array, which requires multiple
1440             // contiguous locations."
1441             mInfoLog << "Could not fit output variable into available locations: "
1442                      << outputVariable.name;
1443             return false;
1444         }
1445     }
1446 
1447     return true;
1448 }
1449 
1450 }  // namespace gl
1451