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