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