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