1 //
2 // Copyright 2002 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
7 // Program.cpp: Implements the gl::Program class. Implements GL program objects
8 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
10 #include "libANGLE/Program.h"
11
12 #include <algorithm>
13 #include <utility>
14
15 #include "common/bitset_utils.h"
16 #include "common/debug.h"
17 #include "common/platform.h"
18 #include "common/string_utils.h"
19 #include "common/utilities.h"
20 #include "common/version.h"
21 #include "compiler/translator/blocklayout.h"
22 #include "libANGLE/Context.h"
23 #include "libANGLE/MemoryProgramCache.h"
24 #include "libANGLE/ProgramLinkedResources.h"
25 #include "libANGLE/ResourceManager.h"
26 #include "libANGLE/Uniform.h"
27 #include "libANGLE/VaryingPacking.h"
28 #include "libANGLE/Version.h"
29 #include "libANGLE/features.h"
30 #include "libANGLE/histogram_macros.h"
31 #include "libANGLE/queryconversions.h"
32 #include "libANGLE/renderer/GLImplFactory.h"
33 #include "libANGLE/renderer/ProgramImpl.h"
34 #include "platform/FrontendFeatures.h"
35 #include "platform/Platform.h"
36
37 namespace gl
38 {
39
40 namespace
41 {
42
43 // This simplified cast function doesn't need to worry about advanced concepts like
44 // depth range values, or casting to bool.
45 template <typename DestT, typename SrcT>
46 DestT UniformStateQueryCast(SrcT value);
47
48 // From-Float-To-Integer Casts
49 template <>
UniformStateQueryCast(GLfloat value)50 GLint UniformStateQueryCast(GLfloat value)
51 {
52 return clampCast<GLint>(roundf(value));
53 }
54
55 template <>
UniformStateQueryCast(GLfloat value)56 GLuint UniformStateQueryCast(GLfloat value)
57 {
58 return clampCast<GLuint>(roundf(value));
59 }
60
61 // From-Integer-to-Integer Casts
62 template <>
UniformStateQueryCast(GLuint value)63 GLint UniformStateQueryCast(GLuint value)
64 {
65 return clampCast<GLint>(value);
66 }
67
68 template <>
UniformStateQueryCast(GLint value)69 GLuint UniformStateQueryCast(GLint value)
70 {
71 return clampCast<GLuint>(value);
72 }
73
74 // From-Boolean-to-Anything Casts
75 template <>
UniformStateQueryCast(GLboolean value)76 GLfloat UniformStateQueryCast(GLboolean value)
77 {
78 return (ConvertToBool(value) ? 1.0f : 0.0f);
79 }
80
81 template <>
UniformStateQueryCast(GLboolean value)82 GLint UniformStateQueryCast(GLboolean value)
83 {
84 return (ConvertToBool(value) ? 1 : 0);
85 }
86
87 template <>
UniformStateQueryCast(GLboolean value)88 GLuint UniformStateQueryCast(GLboolean value)
89 {
90 return (ConvertToBool(value) ? 1u : 0u);
91 }
92
93 // Default to static_cast
94 template <typename DestT, typename SrcT>
UniformStateQueryCast(SrcT value)95 DestT UniformStateQueryCast(SrcT value)
96 {
97 return static_cast<DestT>(value);
98 }
99
100 template <typename SrcT, typename DestT>
UniformStateQueryCastLoop(DestT * dataOut,const uint8_t * srcPointer,int components)101 void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
102 {
103 for (int comp = 0; comp < components; ++comp)
104 {
105 // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
106 // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
107 size_t offset = comp * 4;
108 const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
109 dataOut[comp] = UniformStateQueryCast<DestT>(*typedSrcPointer);
110 }
111 }
112
113 template <typename VarT>
GetResourceIndexFromName(const std::vector<VarT> & list,const std::string & name)114 GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
115 {
116 std::string nameAsArrayName = name + "[0]";
117 for (size_t index = 0; index < list.size(); index++)
118 {
119 const VarT &resource = list[index];
120 if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
121 {
122 return static_cast<GLuint>(index);
123 }
124 }
125
126 return GL_INVALID_INDEX;
127 }
128
129 template <typename VarT>
GetVariableLocation(const std::vector<VarT> & list,const std::vector<VariableLocation> & locationList,const std::string & name)130 GLint GetVariableLocation(const std::vector<VarT> &list,
131 const std::vector<VariableLocation> &locationList,
132 const std::string &name)
133 {
134 size_t nameLengthWithoutArrayIndex;
135 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
136
137 for (size_t location = 0u; location < locationList.size(); ++location)
138 {
139 const VariableLocation &variableLocation = locationList[location];
140 if (!variableLocation.used())
141 {
142 continue;
143 }
144
145 const VarT &variable = list[variableLocation.index];
146
147 // Array output variables may be bound out of order, so we need to ensure we only pick the
148 // first element if given the base name. Uniforms don't allow this behavior and some code
149 // seemingly depends on the opposite behavior, so only enable it for output variables.
150 if (angle::BeginsWith(variable.name, name) &&
151 (!std::is_base_of<sh::OutputVariable, VarT>::value || variableLocation.arrayIndex == 0))
152 {
153 if (name.length() == variable.name.length())
154 {
155 ASSERT(name == variable.name);
156 // GLES 3.1 November 2016 page 87.
157 // The string exactly matches the name of the active variable.
158 return static_cast<GLint>(location);
159 }
160 if (name.length() + 3u == variable.name.length() && variable.isArray())
161 {
162 ASSERT(name + "[0]" == variable.name);
163 // The string identifies the base name of an active array, where the string would
164 // exactly match the name of the variable if the suffix "[0]" were appended to the
165 // string.
166 return static_cast<GLint>(location);
167 }
168 }
169 if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
170 nameLengthWithoutArrayIndex + 3u == variable.name.length() &&
171 angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
172 {
173 ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name);
174 // The string identifies an active element of the array, where the string ends with the
175 // concatenation of the "[" character, an integer (with no "+" sign, extra leading
176 // zeroes, or whitespace) identifying an array element, and the "]" character, the
177 // integer is less than the number of active elements of the array variable, and where
178 // the string would exactly match the enumerated name of the array if the decimal
179 // integer were replaced with zero.
180 return static_cast<GLint>(location);
181 }
182 }
183
184 return -1;
185 }
186
CopyStringToBuffer(GLchar * buffer,const std::string & string,GLsizei bufSize,GLsizei * lengthOut)187 void CopyStringToBuffer(GLchar *buffer,
188 const std::string &string,
189 GLsizei bufSize,
190 GLsizei *lengthOut)
191 {
192 ASSERT(bufSize > 0);
193 size_t length = std::min<size_t>(bufSize - 1, string.length());
194 memcpy(buffer, string.c_str(), length);
195 buffer[length] = '\0';
196
197 if (lengthOut)
198 {
199 *lengthOut = static_cast<GLsizei>(length);
200 }
201 }
202
IncludeSameArrayElement(const std::set<std::string> & nameSet,const std::string & name)203 bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
204 {
205 std::vector<unsigned int> subscripts;
206 std::string baseName = ParseResourceName(name, &subscripts);
207 for (const std::string &nameInSet : nameSet)
208 {
209 std::vector<unsigned int> arrayIndices;
210 std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
211 if (baseName == arrayName &&
212 (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
213 {
214 return true;
215 }
216 }
217 return false;
218 }
219
GetInterfaceBlockLimitName(ShaderType shaderType,sh::BlockType blockType)220 std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
221 {
222 std::ostringstream stream;
223 stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
224
225 switch (blockType)
226 {
227 case sh::BlockType::BLOCK_UNIFORM:
228 stream << "UNIFORM_BUFFERS";
229 break;
230 case sh::BlockType::BLOCK_BUFFER:
231 stream << "SHADER_STORAGE_BLOCKS";
232 break;
233 default:
234 UNREACHABLE();
235 return "";
236 }
237
238 if (shaderType == ShaderType::Geometry)
239 {
240 stream << "_EXT";
241 }
242
243 return stream.str();
244 }
245
GetInterfaceBlockTypeString(sh::BlockType blockType)246 const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
247 {
248 switch (blockType)
249 {
250 case sh::BlockType::BLOCK_UNIFORM:
251 return "uniform block";
252 case sh::BlockType::BLOCK_BUFFER:
253 return "shader storage block";
254 default:
255 UNREACHABLE();
256 return "";
257 }
258 }
259
LogInterfaceBlocksExceedLimit(InfoLog & infoLog,ShaderType shaderType,sh::BlockType blockType,GLuint limit)260 void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
261 ShaderType shaderType,
262 sh::BlockType blockType,
263 GLuint limit)
264 {
265 infoLog << GetShaderTypeString(shaderType) << " shader "
266 << GetInterfaceBlockTypeString(blockType) << " count exceeds "
267 << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
268 }
269
ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,sh::BlockType blockType,GLuint * combinedInterfaceBlocksCount,InfoLog & infoLog)270 bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
271 const std::vector<sh::InterfaceBlock> &interfaceBlocks,
272 ShaderType shaderType,
273 sh::BlockType blockType,
274 GLuint *combinedInterfaceBlocksCount,
275 InfoLog &infoLog)
276 {
277 GLuint blockCount = 0;
278 for (const sh::InterfaceBlock &block : interfaceBlocks)
279 {
280 if (IsActiveInterfaceBlock(block))
281 {
282 blockCount += std::max(block.arraySize, 1u);
283 if (blockCount > maxInterfaceBlocks)
284 {
285 LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
286 return false;
287 }
288 }
289 }
290
291 // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
292 // If a uniform block is used by multiple shader stages, each such use counts separately
293 // against this combined limit.
294 // [OpenGL ES 3.1] Chapter 7.8 Page 111:
295 // If a shader storage block in a program is referenced by multiple shaders, each such
296 // reference counts separately against this combined limit.
297 if (combinedInterfaceBlocksCount)
298 {
299 *combinedInterfaceBlocksCount += blockCount;
300 }
301
302 return true;
303 }
304
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)305 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
306 {
307 std::vector<unsigned int> subscripts;
308 std::string baseName = ParseResourceName(name, &subscripts);
309
310 unsigned int numBlocks = static_cast<unsigned int>(list.size());
311 for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
312 {
313 const auto &block = list[blockIndex];
314 if (block.name == baseName)
315 {
316 const bool arrayElementZero =
317 (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
318 const bool arrayElementMatches =
319 (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
320 if (arrayElementMatches || arrayElementZero)
321 {
322 return blockIndex;
323 }
324 }
325 }
326
327 return GL_INVALID_INDEX;
328 }
329
GetInterfaceBlockName(const GLuint index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)330 void GetInterfaceBlockName(const GLuint index,
331 const std::vector<InterfaceBlock> &list,
332 GLsizei bufSize,
333 GLsizei *length,
334 GLchar *name)
335 {
336 ASSERT(index < list.size());
337
338 const auto &block = list[index];
339
340 if (bufSize > 0)
341 {
342 std::string blockName = block.name;
343
344 if (block.isArray)
345 {
346 blockName += ArrayString(block.arrayElement);
347 }
348 CopyStringToBuffer(name, blockName, bufSize, length);
349 }
350 }
351
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)352 void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
353 {
354 for (ShaderType shaderType : AllShaderTypes())
355 {
356 Shader *shader = state.getAttachedShader(shaderType);
357 if (shader)
358 {
359 blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks());
360 }
361 }
362 }
363
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)364 void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
365 {
366 for (ShaderType shaderType : AllShaderTypes())
367 {
368 Shader *shader = state.getAttachedShader(shaderType);
369 if (shader != nullptr)
370 {
371 blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks());
372 }
373 }
374 }
375
376 // Find the matching varying or field by name.
FindVaryingOrField(const ProgramMergedVaryings & varyings,const std::string & name)377 const sh::ShaderVariable *FindVaryingOrField(const ProgramMergedVaryings &varyings,
378 const std::string &name)
379 {
380 const sh::ShaderVariable *var = nullptr;
381 for (const auto &ref : varyings)
382 {
383 const sh::Varying *varying = ref.second.get();
384 if (varying->name == name)
385 {
386 var = varying;
387 break;
388 }
389 GLuint fieldIndex = 0;
390 var = FindShaderVarField(*varying, name, &fieldIndex);
391 if (var != nullptr)
392 {
393 break;
394 }
395 }
396 return var;
397 }
398
AddParentPrefix(const std::string & parentName,std::string * mismatchedFieldName)399 void AddParentPrefix(const std::string &parentName, std::string *mismatchedFieldName)
400 {
401 ASSERT(mismatchedFieldName);
402 if (mismatchedFieldName->empty())
403 {
404 *mismatchedFieldName = parentName;
405 }
406 else
407 {
408 std::ostringstream stream;
409 stream << parentName << "." << *mismatchedFieldName;
410 *mismatchedFieldName = stream.str();
411 }
412 }
413
GetLinkMismatchErrorString(LinkMismatchError linkError)414 const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
415 {
416 switch (linkError)
417 {
418 case LinkMismatchError::TYPE_MISMATCH:
419 return "Type";
420 case LinkMismatchError::ARRAY_SIZE_MISMATCH:
421 return "Array size";
422 case LinkMismatchError::PRECISION_MISMATCH:
423 return "Precision";
424 case LinkMismatchError::STRUCT_NAME_MISMATCH:
425 return "Structure name";
426 case LinkMismatchError::FIELD_NUMBER_MISMATCH:
427 return "Field number";
428 case LinkMismatchError::FIELD_NAME_MISMATCH:
429 return "Field name";
430
431 case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
432 return "Interpolation type";
433 case LinkMismatchError::INVARIANCE_MISMATCH:
434 return "Invariance";
435
436 case LinkMismatchError::BINDING_MISMATCH:
437 return "Binding layout qualifier";
438 case LinkMismatchError::LOCATION_MISMATCH:
439 return "Location layout qualifier";
440 case LinkMismatchError::OFFSET_MISMATCH:
441 return "Offset layout qualifier";
442 case LinkMismatchError::INSTANCE_NAME_MISMATCH:
443 return "Instance name qualifier";
444
445 case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
446 return "Layout qualifier";
447 case LinkMismatchError::MATRIX_PACKING_MISMATCH:
448 return "Matrix Packing";
449 default:
450 UNREACHABLE();
451 return "";
452 }
453 }
454
LinkValidateInterfaceBlockFields(const sh::InterfaceBlockField & blockField1,const sh::InterfaceBlockField & blockField2,bool webglCompatibility,std::string * mismatchedBlockFieldName)455 LinkMismatchError LinkValidateInterfaceBlockFields(const sh::InterfaceBlockField &blockField1,
456 const sh::InterfaceBlockField &blockField2,
457 bool webglCompatibility,
458 std::string *mismatchedBlockFieldName)
459 {
460 if (blockField1.name != blockField2.name)
461 {
462 return LinkMismatchError::FIELD_NAME_MISMATCH;
463 }
464
465 // If webgl, validate precision of UBO fields, otherwise don't. See Khronos bug 10287.
466 LinkMismatchError linkError = Program::LinkValidateVariablesBase(
467 blockField1, blockField2, webglCompatibility, true, mismatchedBlockFieldName);
468 if (linkError != LinkMismatchError::NO_MISMATCH)
469 {
470 AddParentPrefix(blockField1.name, mismatchedBlockFieldName);
471 return linkError;
472 }
473
474 if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout)
475 {
476 AddParentPrefix(blockField1.name, mismatchedBlockFieldName);
477 return LinkMismatchError::MATRIX_PACKING_MISMATCH;
478 }
479
480 return LinkMismatchError::NO_MISMATCH;
481 }
482
AreMatchingInterfaceBlocks(const sh::InterfaceBlock & interfaceBlock1,const sh::InterfaceBlock & interfaceBlock2,bool webglCompatibility,std::string * mismatchedBlockFieldName)483 LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1,
484 const sh::InterfaceBlock &interfaceBlock2,
485 bool webglCompatibility,
486 std::string *mismatchedBlockFieldName)
487 {
488 // validate blocks for the same member types
489 if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size())
490 {
491 return LinkMismatchError::FIELD_NUMBER_MISMATCH;
492 }
493 if (interfaceBlock1.arraySize != interfaceBlock2.arraySize)
494 {
495 return LinkMismatchError::ARRAY_SIZE_MISMATCH;
496 }
497 if (interfaceBlock1.layout != interfaceBlock2.layout ||
498 interfaceBlock1.binding != interfaceBlock2.binding)
499 {
500 return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH;
501 }
502 if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty())
503 {
504 return LinkMismatchError::INSTANCE_NAME_MISMATCH;
505 }
506 const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size());
507 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
508 {
509 const sh::InterfaceBlockField &member1 = interfaceBlock1.fields[blockMemberIndex];
510 const sh::InterfaceBlockField &member2 = interfaceBlock2.fields[blockMemberIndex];
511
512 LinkMismatchError linkError = LinkValidateInterfaceBlockFields(
513 member1, member2, webglCompatibility, mismatchedBlockFieldName);
514 if (linkError != LinkMismatchError::NO_MISMATCH)
515 {
516 return linkError;
517 }
518 }
519 return LinkMismatchError::NO_MISMATCH;
520 }
521
522 using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>;
523 using InterfaceBlockMap = std::map<std::string, ShaderInterfaceBlock>;
524
InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * linkedInterfaceBlocks)525 void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
526 ShaderType shaderType,
527 InterfaceBlockMap *linkedInterfaceBlocks)
528 {
529 ASSERT(linkedInterfaceBlocks);
530
531 for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
532 {
533 (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
534 }
535 }
536
ValidateGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocksToLink,ShaderType shaderType,bool webglCompatibility,InterfaceBlockMap * linkedBlocks,InfoLog & infoLog)537 bool ValidateGraphicsInterfaceBlocksPerShader(
538 const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
539 ShaderType shaderType,
540 bool webglCompatibility,
541 InterfaceBlockMap *linkedBlocks,
542 InfoLog &infoLog)
543 {
544 ASSERT(linkedBlocks);
545
546 for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
547 {
548 const auto &entry = linkedBlocks->find(block.name);
549 if (entry != linkedBlocks->end())
550 {
551 const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
552 std::string mismatchedStructFieldName;
553 LinkMismatchError linkError = AreMatchingInterfaceBlocks(
554 block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
555 if (linkError != LinkMismatchError::NO_MISMATCH)
556 {
557 LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
558 linkError, mismatchedStructFieldName, entry->second.first,
559 shaderType);
560 return false;
561 }
562 }
563 else
564 {
565 (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
566 }
567 }
568
569 return true;
570 }
571
ValidateInterfaceBlocksMatch(GLuint numShadersHasInterfaceBlocks,const ShaderMap<const std::vector<sh::InterfaceBlock> * > & shaderInterfaceBlocks,InfoLog & infoLog,bool webglCompatibility)572 bool ValidateInterfaceBlocksMatch(
573 GLuint numShadersHasInterfaceBlocks,
574 const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
575 InfoLog &infoLog,
576 bool webglCompatibility)
577 {
578 if (numShadersHasInterfaceBlocks < 2u)
579 {
580 return true;
581 }
582
583 ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]);
584
585 // Check that interface blocks defined in the graphics shaders are identical
586
587 InterfaceBlockMap linkedInterfaceBlocks;
588
589 bool interfaceBlockMapInitialized = false;
590 for (ShaderType shaderType : kAllGraphicsShaderTypes)
591 {
592 if (!shaderInterfaceBlocks[shaderType])
593 {
594 continue;
595 }
596
597 if (!interfaceBlockMapInitialized)
598 {
599 InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
600 &linkedInterfaceBlocks);
601 interfaceBlockMapInitialized = true;
602 }
603 else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType],
604 shaderType, webglCompatibility,
605 &linkedInterfaceBlocks, infoLog))
606 {
607 return false;
608 }
609 }
610
611 return true;
612 }
613
WriteShaderVar(BinaryOutputStream * stream,const sh::ShaderVariable & var)614 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
615 {
616 stream->writeInt(var.type);
617 stream->writeInt(var.precision);
618 stream->writeString(var.name);
619 stream->writeString(var.mappedName);
620 stream->writeIntVector(var.arraySizes);
621 stream->writeInt(var.staticUse);
622 stream->writeInt(var.active);
623 stream->writeString(var.structName);
624 stream->writeInt(var.hasParentArrayIndex() ? var.parentArrayIndex() : -1);
625 ASSERT(var.fields.empty());
626 }
627
LoadShaderVar(BinaryInputStream * stream,sh::ShaderVariable * var)628 void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
629 {
630 var->type = stream->readInt<GLenum>();
631 var->precision = stream->readInt<GLenum>();
632 var->name = stream->readString();
633 var->mappedName = stream->readString();
634 stream->readIntVector<unsigned int>(&var->arraySizes);
635 var->staticUse = stream->readBool();
636 var->active = stream->readBool();
637 var->structName = stream->readString();
638 var->setParentArrayIndex(stream->readInt<int>());
639 }
640
WriteShaderVariableBuffer(BinaryOutputStream * stream,const ShaderVariableBuffer & var)641 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
642 {
643 stream->writeInt(var.binding);
644 stream->writeInt(var.dataSize);
645
646 for (ShaderType shaderType : AllShaderTypes())
647 {
648 stream->writeInt(var.isActive(shaderType));
649 }
650
651 stream->writeInt(var.memberIndexes.size());
652 for (unsigned int memberCounterIndex : var.memberIndexes)
653 {
654 stream->writeInt(memberCounterIndex);
655 }
656 }
657
LoadShaderVariableBuffer(BinaryInputStream * stream,ShaderVariableBuffer * var)658 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
659 {
660 var->binding = stream->readInt<int>();
661 var->dataSize = stream->readInt<unsigned int>();
662
663 for (ShaderType shaderType : AllShaderTypes())
664 {
665 var->setActive(shaderType, stream->readBool());
666 }
667
668 unsigned int numMembers = stream->readInt<unsigned int>();
669 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
670 {
671 var->memberIndexes.push_back(stream->readInt<unsigned int>());
672 }
673 }
674
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)675 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
676 {
677 WriteShaderVar(stream, var);
678
679 stream->writeInt(var.bufferIndex);
680 WriteBlockMemberInfo(stream, var.blockInfo);
681 stream->writeInt(var.topLevelArraySize);
682
683 for (ShaderType shaderType : AllShaderTypes())
684 {
685 stream->writeInt(var.isActive(shaderType));
686 }
687 }
688
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)689 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
690 {
691 LoadShaderVar(stream, var);
692
693 var->bufferIndex = stream->readInt<int>();
694 LoadBlockMemberInfo(stream, &var->blockInfo);
695 var->topLevelArraySize = stream->readInt<int>();
696
697 for (ShaderType shaderType : AllShaderTypes())
698 {
699 var->setActive(shaderType, stream->readBool());
700 }
701 }
702
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)703 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
704 {
705 stream->writeString(block.name);
706 stream->writeString(block.mappedName);
707 stream->writeInt(block.isArray);
708 stream->writeInt(block.arrayElement);
709
710 WriteShaderVariableBuffer(stream, block);
711 }
712
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)713 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
714 {
715 block->name = stream->readString();
716 block->mappedName = stream->readString();
717 block->isArray = stream->readBool();
718 block->arrayElement = stream->readInt<unsigned int>();
719
720 LoadShaderVariableBuffer(stream, block);
721 }
722
CountUniqueBlocks(const std::vector<InterfaceBlock> & blocks)723 size_t CountUniqueBlocks(const std::vector<InterfaceBlock> &blocks)
724 {
725 size_t count = 0;
726 for (const InterfaceBlock &block : blocks)
727 {
728 if (!block.isArray || block.arrayElement == 0)
729 {
730 ++count;
731 }
732 }
733 return count;
734 }
735 } // anonymous namespace
736
737 // Saves the linking context for later use in resolveLink().
738 struct Program::LinkingState
739 {
740 const Context *context;
741 std::unique_ptr<ProgramLinkedResources> resources;
742 egl::BlobCache::Key programHash;
743 std::unique_ptr<rx::LinkEvent> linkEvent;
744 bool linkingFromBinary;
745 };
746
747 const char *const g_fakepath = "C:\\fakepath";
748
749 // InfoLog implementation.
InfoLog()750 InfoLog::InfoLog() {}
751
~InfoLog()752 InfoLog::~InfoLog() {}
753
getLength() const754 size_t InfoLog::getLength() const
755 {
756 if (!mLazyStream)
757 {
758 return 0;
759 }
760
761 const std::string &logString = mLazyStream->str();
762 return logString.empty() ? 0 : logString.length() + 1;
763 }
764
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const765 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
766 {
767 size_t index = 0;
768
769 if (bufSize > 0)
770 {
771 const std::string logString(str());
772
773 if (!logString.empty())
774 {
775 index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
776 memcpy(infoLog, logString.c_str(), index);
777 }
778
779 infoLog[index] = '\0';
780 }
781
782 if (length)
783 {
784 *length = static_cast<GLsizei>(index);
785 }
786 }
787
788 // append a santized message to the program info log.
789 // The D3D compiler includes a fake file path in some of the warning or error
790 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)791 void InfoLog::appendSanitized(const char *message)
792 {
793 ensureInitialized();
794
795 std::string msg(message);
796
797 size_t found;
798 do
799 {
800 found = msg.find(g_fakepath);
801 if (found != std::string::npos)
802 {
803 msg.erase(found, strlen(g_fakepath));
804 }
805 } while (found != std::string::npos);
806
807 *mLazyStream << message << std::endl;
808 }
809
reset()810 void InfoLog::reset()
811 {
812 if (mLazyStream)
813 {
814 mLazyStream.reset(nullptr);
815 }
816 }
817
empty() const818 bool InfoLog::empty() const
819 {
820 if (!mLazyStream)
821 {
822 return true;
823 }
824
825 return mLazyStream->rdbuf()->in_avail() == 0;
826 }
827
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)828 void LogLinkMismatch(InfoLog &infoLog,
829 const std::string &variableName,
830 const char *variableType,
831 LinkMismatchError linkError,
832 const std::string &mismatchedStructOrBlockFieldName,
833 ShaderType shaderType1,
834 ShaderType shaderType2)
835 {
836 std::ostringstream stream;
837 stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
838 << variableName;
839
840 if (!mismatchedStructOrBlockFieldName.empty())
841 {
842 stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
843 }
844
845 stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
846 << GetShaderTypeString(shaderType2) << " shaders.";
847
848 infoLog << stream.str();
849 }
850
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)851 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
852 {
853 // Only 'packed' blocks are allowed to be considered inactive.
854 return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
855 }
856
WriteBlockMemberInfo(BinaryOutputStream * stream,const sh::BlockMemberInfo & var)857 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var)
858 {
859 stream->writeInt(var.arrayStride);
860 stream->writeInt(var.isRowMajorMatrix);
861 stream->writeInt(var.matrixStride);
862 stream->writeInt(var.offset);
863 stream->writeInt(var.topLevelArrayStride);
864 }
865
LoadBlockMemberInfo(BinaryInputStream * stream,sh::BlockMemberInfo * var)866 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
867 {
868 var->arrayStride = stream->readInt<int>();
869 var->isRowMajorMatrix = stream->readBool();
870 var->matrixStride = stream->readInt<int>();
871 var->offset = stream->readInt<int>();
872 var->topLevelArrayStride = stream->readInt<int>();
873 }
874
875 // VariableLocation implementation.
VariableLocation()876 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
877
VariableLocation(unsigned int arrayIndex,unsigned int index)878 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
879 : arrayIndex(arrayIndex), index(index), ignored(false)
880 {
881 ASSERT(arrayIndex != GL_INVALID_INDEX);
882 }
883
884 // SamplerBindings implementation.
SamplerBinding(TextureType textureTypeIn,SamplerFormat formatIn,size_t elementCount,bool unreferenced)885 SamplerBinding::SamplerBinding(TextureType textureTypeIn,
886 SamplerFormat formatIn,
887 size_t elementCount,
888 bool unreferenced)
889 : textureType(textureTypeIn),
890 format(formatIn),
891 boundTextureUnits(elementCount, 0),
892 unreferenced(unreferenced)
893 {}
894
895 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
896
897 SamplerBinding::~SamplerBinding() = default;
898
899 // ProgramBindings implementation.
ProgramBindings()900 ProgramBindings::ProgramBindings() {}
901
~ProgramBindings()902 ProgramBindings::~ProgramBindings() {}
903
bindLocation(GLuint index,const std::string & name)904 void ProgramBindings::bindLocation(GLuint index, const std::string &name)
905 {
906 mBindings[name] = ProgramBinding(index);
907
908 // EXT_blend_func_extended spec: "If it specifies the base name of an array,
909 // it identifies the resources associated with the first element of the array."
910 //
911 // Normalize array bindings so that "name" and "name[0]" map to the same entry.
912 // If this binding is of the form "name[0]", then mark the "name" binding as
913 // aliased but do not update it yet in case "name" is not actually an array.
914 size_t nameLengthWithoutArrayIndex;
915 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
916 if (arrayIndex == 0)
917 {
918 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
919 auto iter = mBindings.find(baseName);
920 if (iter != mBindings.end())
921 {
922 iter->second.aliased = true;
923 }
924 }
925 }
926
getBindingByName(const std::string & name) const927 int ProgramBindings::getBindingByName(const std::string &name) const
928 {
929 auto iter = mBindings.find(name);
930 return (iter != mBindings.end()) ? iter->second.location : -1;
931 }
932
getBinding(const sh::VariableWithLocation & variable) const933 int ProgramBindings::getBinding(const sh::VariableWithLocation &variable) const
934 {
935 const std::string &name = variable.name;
936
937 // Check with the normalized array name if applicable.
938 if (variable.isArray())
939 {
940 size_t nameLengthWithoutArrayIndex;
941 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
942 if (arrayIndex == 0)
943 {
944 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
945 auto iter = mBindings.find(baseName);
946 // If "name" exists and is not aliased, that means it was modified more
947 // recently than its "name[0]" form and should be used instead of that.
948 if (iter != mBindings.end() && !iter->second.aliased)
949 {
950 return iter->second.location;
951 }
952 }
953 }
954
955 return getBindingByName(name);
956 }
957
begin() const958 ProgramBindings::const_iterator ProgramBindings::begin() const
959 {
960 return mBindings.begin();
961 }
962
end() const963 ProgramBindings::const_iterator ProgramBindings::end() const
964 {
965 return mBindings.end();
966 }
967
968 // ImageBinding implementation.
ImageBinding(size_t count)969 ImageBinding::ImageBinding(size_t count) : boundImageUnits(count, 0), unreferenced(false) {}
ImageBinding(GLuint imageUnit,size_t count,bool unreferenced)970 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, bool unreferenced)
971 : unreferenced(unreferenced)
972 {
973 for (size_t index = 0; index < count; ++index)
974 {
975 boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
976 }
977 }
978
979 ImageBinding::ImageBinding(const ImageBinding &other) = default;
980
981 ImageBinding::~ImageBinding() = default;
982
983 // ProgramState implementation.
ProgramState()984 ProgramState::ProgramState()
985 : mLabel(),
986 mAttachedShaders{},
987 mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
988 mMaxActiveAttribLocation(0),
989 mSamplerUniformRange(0, 0),
990 mImageUniformRange(0, 0),
991 mAtomicCounterUniformRange(0, 0),
992 mBinaryRetrieveableHint(false),
993 mNumViews(-1),
994 // [GL_EXT_geometry_shader] Table 20.22
995 mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
996 mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
997 mGeometryShaderInvocations(1),
998 mGeometryShaderMaxVertices(0),
999 mDrawIDLocation(-1),
1000 mBaseVertexLocation(-1),
1001 mBaseInstanceLocation(-1),
1002 mActiveSamplerRefCounts{}
1003 {
1004 mComputeShaderLocalSize.fill(1);
1005 mActiveSamplerTypes.fill(TextureType::InvalidEnum);
1006 }
1007
~ProgramState()1008 ProgramState::~ProgramState()
1009 {
1010 ASSERT(!hasAttachedShader());
1011 }
1012
getLabel()1013 const std::string &ProgramState::getLabel()
1014 {
1015 return mLabel;
1016 }
1017
getAttachedShader(ShaderType shaderType) const1018 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
1019 {
1020 ASSERT(shaderType != ShaderType::InvalidEnum);
1021 return mAttachedShaders[shaderType];
1022 }
1023
getUniqueUniformBlockCount() const1024 size_t ProgramState::getUniqueUniformBlockCount() const
1025 {
1026 return CountUniqueBlocks(mUniformBlocks);
1027 }
1028
getUniqueStorageBlockCount() const1029 size_t ProgramState::getUniqueStorageBlockCount() const
1030 {
1031 return CountUniqueBlocks(mShaderStorageBlocks);
1032 }
1033
getUniformIndexFromName(const std::string & name) const1034 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
1035 {
1036 return GetResourceIndexFromName(mUniforms, name);
1037 }
1038
getBufferVariableIndexFromName(const std::string & name) const1039 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
1040 {
1041 return GetResourceIndexFromName(mBufferVariables, name);
1042 }
1043
getUniformIndexFromLocation(GLint location) const1044 GLuint ProgramState::getUniformIndexFromLocation(GLint location) const
1045 {
1046 ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformLocations.size());
1047 return mUniformLocations[location].index;
1048 }
1049
getSamplerIndex(GLint location) const1050 Optional<GLuint> ProgramState::getSamplerIndex(GLint location) const
1051 {
1052 GLuint index = getUniformIndexFromLocation(location);
1053 if (!isSamplerUniformIndex(index))
1054 {
1055 return Optional<GLuint>::Invalid();
1056 }
1057
1058 return getSamplerIndexFromUniformIndex(index);
1059 }
1060
isSamplerUniformIndex(GLuint index) const1061 bool ProgramState::isSamplerUniformIndex(GLuint index) const
1062 {
1063 return mSamplerUniformRange.contains(index);
1064 }
1065
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const1066 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
1067 {
1068 ASSERT(isSamplerUniformIndex(uniformIndex));
1069 return uniformIndex - mSamplerUniformRange.low();
1070 }
1071
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const1072 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
1073 {
1074 ASSERT(samplerIndex < mSamplerUniformRange.length());
1075 return samplerIndex + mSamplerUniformRange.low();
1076 }
1077
isImageUniformIndex(GLuint index) const1078 bool ProgramState::isImageUniformIndex(GLuint index) const
1079 {
1080 return mImageUniformRange.contains(index);
1081 }
1082
getImageIndexFromUniformIndex(GLuint uniformIndex) const1083 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
1084 {
1085 ASSERT(isImageUniformIndex(uniformIndex));
1086 return uniformIndex - mImageUniformRange.low();
1087 }
1088
getUniformIndexFromImageIndex(GLuint imageIndex) const1089 GLuint ProgramState::getUniformIndexFromImageIndex(GLuint imageIndex) const
1090 {
1091 ASSERT(imageIndex < mImageUniformRange.length());
1092 return imageIndex + mImageUniformRange.low();
1093 }
1094
getAttributeLocation(const std::string & name) const1095 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1096 {
1097 for (const sh::Attribute &attribute : mAttributes)
1098 {
1099 if (attribute.name == name)
1100 {
1101 return attribute.location;
1102 }
1103 }
1104
1105 return static_cast<GLuint>(-1);
1106 }
1107
hasAttachedShader() const1108 bool ProgramState::hasAttachedShader() const
1109 {
1110 for (const Shader *shader : mAttachedShaders)
1111 {
1112 if (shader)
1113 {
1114 return true;
1115 }
1116 }
1117 return false;
1118 }
1119
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,GLuint handle)1120 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle)
1121 : mProgram(factory->createProgram(mState)),
1122 mValidated(false),
1123 mLinked(false),
1124 mLinkResolved(true),
1125 mDeleteStatus(false),
1126 mRefCount(0),
1127 mResourceManager(manager),
1128 mHandle(handle)
1129 {
1130 ASSERT(mProgram);
1131
1132 unlink();
1133 }
1134
~Program()1135 Program::~Program()
1136 {
1137 ASSERT(!mProgram);
1138 }
1139
onDestroy(const Context * context)1140 void Program::onDestroy(const Context *context)
1141 {
1142 resolveLink(context);
1143 for (ShaderType shaderType : AllShaderTypes())
1144 {
1145 if (mState.mAttachedShaders[shaderType])
1146 {
1147 mState.mAttachedShaders[shaderType]->release(context);
1148 mState.mAttachedShaders[shaderType] = nullptr;
1149 }
1150 }
1151
1152 mProgram->destroy(context);
1153
1154 ASSERT(!mState.hasAttachedShader());
1155 SafeDelete(mProgram);
1156
1157 delete this;
1158 }
id() const1159 GLuint Program::id() const
1160 {
1161 ASSERT(mLinkResolved);
1162 return mHandle;
1163 }
1164
setLabel(const Context * context,const std::string & label)1165 void Program::setLabel(const Context *context, const std::string &label)
1166 {
1167 ASSERT(mLinkResolved);
1168 mState.mLabel = label;
1169 }
1170
getLabel() const1171 const std::string &Program::getLabel() const
1172 {
1173 ASSERT(mLinkResolved);
1174 return mState.mLabel;
1175 }
1176
attachShader(Shader * shader)1177 void Program::attachShader(Shader *shader)
1178 {
1179 ASSERT(mLinkResolved);
1180 ShaderType shaderType = shader->getType();
1181 ASSERT(shaderType != ShaderType::InvalidEnum);
1182
1183 mState.mAttachedShaders[shaderType] = shader;
1184 mState.mAttachedShaders[shaderType]->addRef();
1185 }
1186
detachShader(const Context * context,Shader * shader)1187 void Program::detachShader(const Context *context, Shader *shader)
1188 {
1189 ASSERT(mLinkResolved);
1190 ShaderType shaderType = shader->getType();
1191 ASSERT(shaderType != ShaderType::InvalidEnum);
1192
1193 ASSERT(mState.mAttachedShaders[shaderType] == shader);
1194 shader->release(context);
1195 mState.mAttachedShaders[shaderType] = nullptr;
1196 }
1197
getAttachedShadersCount() const1198 int Program::getAttachedShadersCount() const
1199 {
1200 ASSERT(mLinkResolved);
1201 int numAttachedShaders = 0;
1202 for (const Shader *shader : mState.mAttachedShaders)
1203 {
1204 if (shader)
1205 {
1206 ++numAttachedShaders;
1207 }
1208 }
1209
1210 return numAttachedShaders;
1211 }
1212
getAttachedShader(ShaderType shaderType) const1213 const Shader *Program::getAttachedShader(ShaderType shaderType) const
1214 {
1215 ASSERT(mLinkResolved);
1216 return mState.getAttachedShader(shaderType);
1217 }
1218
bindAttributeLocation(GLuint index,const char * name)1219 void Program::bindAttributeLocation(GLuint index, const char *name)
1220 {
1221 ASSERT(mLinkResolved);
1222 mAttributeBindings.bindLocation(index, name);
1223 }
1224
bindUniformLocation(GLuint index,const char * name)1225 void Program::bindUniformLocation(GLuint index, const char *name)
1226 {
1227 ASSERT(mLinkResolved);
1228 mUniformLocationBindings.bindLocation(index, name);
1229 }
1230
bindFragmentInputLocation(GLint index,const char * name)1231 void Program::bindFragmentInputLocation(GLint index, const char *name)
1232 {
1233 ASSERT(mLinkResolved);
1234 mFragmentInputBindings.bindLocation(index, name);
1235 }
1236
bindFragmentOutputLocation(GLuint index,const char * name)1237 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1238 {
1239 mFragmentOutputLocations.bindLocation(index, name);
1240 }
1241
bindFragmentOutputIndex(GLuint index,const char * name)1242 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1243 {
1244 mFragmentOutputIndexes.bindLocation(index, name);
1245 }
1246
getFragmentInputBindingInfo(GLint index) const1247 BindingInfo Program::getFragmentInputBindingInfo(GLint index) const
1248 {
1249 ASSERT(mLinkResolved);
1250 BindingInfo ret;
1251 ret.type = GL_NONE;
1252 ret.valid = false;
1253
1254 Shader *fragmentShader = mState.getAttachedShader(ShaderType::Fragment);
1255 ASSERT(fragmentShader);
1256
1257 // Find the actual fragment shader varying we're interested in
1258 const std::vector<sh::Varying> &inputs = fragmentShader->getInputVaryings();
1259
1260 for (const auto &binding : mFragmentInputBindings)
1261 {
1262 if (binding.second.location != static_cast<GLuint>(index))
1263 continue;
1264
1265 ret.valid = true;
1266
1267 size_t nameLengthWithoutArrayIndex;
1268 unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
1269
1270 for (const auto &in : inputs)
1271 {
1272 if (in.name.length() == nameLengthWithoutArrayIndex &&
1273 angle::BeginsWith(in.name, binding.first, nameLengthWithoutArrayIndex))
1274 {
1275 if (in.isArray())
1276 {
1277 // The client wants to bind either "name" or "name[0]".
1278 // GL ES 3.1 spec refers to active array names with language such as:
1279 // "if the string identifies the base name of an active array, where the
1280 // string would exactly match the name of the variable if the suffix "[0]"
1281 // were appended to the string".
1282 if (arrayIndex == GL_INVALID_INDEX)
1283 arrayIndex = 0;
1284
1285 ret.name = in.mappedName + "[" + ToString(arrayIndex) + "]";
1286 }
1287 else
1288 {
1289 ret.name = in.mappedName;
1290 }
1291 ret.type = in.type;
1292 return ret;
1293 }
1294 }
1295 }
1296
1297 return ret;
1298 }
1299
pathFragmentInputGen(GLint index,GLenum genMode,GLint components,const GLfloat * coeffs)1300 void Program::pathFragmentInputGen(GLint index,
1301 GLenum genMode,
1302 GLint components,
1303 const GLfloat *coeffs)
1304 {
1305 ASSERT(mLinkResolved);
1306 // If the location is -1 then the command is silently ignored
1307 if (index == -1)
1308 return;
1309
1310 const auto &binding = getFragmentInputBindingInfo(index);
1311
1312 // If the input doesn't exist then then the command is silently ignored
1313 // This could happen through optimization for example, the shader translator
1314 // decides that a variable is not actually being used and optimizes it away.
1315 if (binding.name.empty())
1316 return;
1317
1318 mProgram->setPathFragmentInputGen(binding.name, genMode, components, coeffs);
1319 }
1320
1321 // The attached shaders are checked for linking errors by matching up their variables.
1322 // Uniform, input and output variables get collected.
1323 // The code gets compiled into binaries.
link(const Context * context)1324 angle::Result Program::link(const Context *context)
1325 {
1326 ASSERT(mLinkResolved);
1327 const auto &data = context->getState();
1328
1329 auto *platform = ANGLEPlatformCurrent();
1330 double startTime = platform->currentTime(platform);
1331
1332 unlink();
1333 mInfoLog.reset();
1334
1335 // Validate we have properly attached shaders before checking the cache.
1336 if (!linkValidateShaders(mInfoLog))
1337 {
1338 return angle::Result::Continue;
1339 }
1340
1341 egl::BlobCache::Key programHash = {0};
1342 MemoryProgramCache *cache = context->getMemoryProgramCache();
1343
1344 if (cache)
1345 {
1346 angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1347 ANGLE_TRY(cacheResult);
1348
1349 // Check explicitly for Continue, Incomplete means a cache miss
1350 if (cacheResult == angle::Result::Continue)
1351 {
1352 // Succeeded in loading the binaries in the front-end, back end may still be loading
1353 // asynchronously
1354 double delta = platform->currentTime(platform) - startTime;
1355 int us = static_cast<int>(delta * 1000000.0);
1356 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1357 return angle::Result::Continue;
1358 }
1359 }
1360
1361 // Cache load failed, fall through to normal linking.
1362 unlink();
1363
1364 // Re-link shaders after the unlink call.
1365 ASSERT(linkValidateShaders(mInfoLog));
1366
1367 std::unique_ptr<ProgramLinkedResources> resources;
1368 if (mState.mAttachedShaders[ShaderType::Compute])
1369 {
1370 resources.reset(new ProgramLinkedResources(
1371 0, PackMode::ANGLE_RELAXED, &mState.mUniformBlocks, &mState.mUniforms,
1372 &mState.mShaderStorageBlocks, &mState.mBufferVariables, &mState.mAtomicCounterBuffers));
1373
1374 GLuint combinedImageUniforms = 0u;
1375 if (!linkUniforms(context->getCaps(), mInfoLog, mUniformLocationBindings,
1376 &combinedImageUniforms, &resources->unusedUniforms))
1377 {
1378 return angle::Result::Continue;
1379 }
1380
1381 GLuint combinedShaderStorageBlocks = 0u;
1382 if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1383 context->getExtensions().webglCompatibility, mInfoLog,
1384 &combinedShaderStorageBlocks))
1385 {
1386 return angle::Result::Continue;
1387 }
1388
1389 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1390 // A link error will be generated if the sum of the number of active image uniforms used in
1391 // all shaders, the number of active shader storage blocks, and the number of active
1392 // fragment shader outputs exceeds the implementation-dependent value of
1393 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1394 if (combinedImageUniforms + combinedShaderStorageBlocks >
1395 context->getCaps().maxCombinedShaderOutputResources)
1396 {
1397 mInfoLog
1398 << "The sum of the number of active image uniforms, active shader storage blocks "
1399 "and active fragment shader outputs exceeds "
1400 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1401 << context->getCaps().maxCombinedShaderOutputResources << ")";
1402 return angle::Result::Continue;
1403 }
1404
1405 InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
1406 InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
1407 }
1408 else
1409 {
1410 // Map the varyings to the register file
1411 // In WebGL, we use a slightly different handling for packing variables.
1412 gl::PackMode packMode = PackMode::ANGLE_RELAXED;
1413 if (data.getLimitations().noFlexibleVaryingPacking)
1414 {
1415 // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
1416 packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
1417 }
1418 else if (data.getExtensions().webglCompatibility)
1419 {
1420 packMode = PackMode::WEBGL_STRICT;
1421 }
1422
1423 resources.reset(new ProgramLinkedResources(
1424 data.getCaps().maxVaryingVectors, packMode, &mState.mUniformBlocks, &mState.mUniforms,
1425 &mState.mShaderStorageBlocks, &mState.mBufferVariables, &mState.mAtomicCounterBuffers));
1426
1427 if (!linkAttributes(context, mInfoLog))
1428 {
1429 return angle::Result::Continue;
1430 }
1431
1432 if (!linkVaryings(mInfoLog))
1433 {
1434 return angle::Result::Continue;
1435 }
1436
1437 GLuint combinedImageUniforms = 0u;
1438 if (!linkUniforms(context->getCaps(), mInfoLog, mUniformLocationBindings,
1439 &combinedImageUniforms, &resources->unusedUniforms))
1440 {
1441 return angle::Result::Continue;
1442 }
1443
1444 GLuint combinedShaderStorageBlocks = 0u;
1445 if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1446 context->getExtensions().webglCompatibility, mInfoLog,
1447 &combinedShaderStorageBlocks))
1448 {
1449 return angle::Result::Continue;
1450 }
1451
1452 if (!linkValidateGlobalNames(mInfoLog))
1453 {
1454 return angle::Result::Continue;
1455 }
1456
1457 if (!linkOutputVariables(context->getCaps(), context->getExtensions(),
1458 context->getClientVersion(), combinedImageUniforms,
1459 combinedShaderStorageBlocks))
1460 {
1461 return angle::Result::Continue;
1462 }
1463
1464 const auto &mergedVaryings = getMergedVaryings();
1465
1466 ASSERT(mState.mAttachedShaders[ShaderType::Vertex]);
1467 mState.mNumViews = mState.mAttachedShaders[ShaderType::Vertex]->getNumViews();
1468
1469 InitUniformBlockLinker(mState, &resources->uniformBlockLinker);
1470 InitShaderStorageBlockLinker(mState, &resources->shaderStorageBlockLinker);
1471
1472 if (!linkValidateTransformFeedback(context->getClientVersion(), mInfoLog, mergedVaryings,
1473 context->getCaps()))
1474 {
1475 return angle::Result::Continue;
1476 }
1477
1478 if (!resources->varyingPacking.collectAndPackUserVaryings(
1479 mInfoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames()))
1480 {
1481 return angle::Result::Continue;
1482 }
1483
1484 gatherTransformFeedbackVaryings(mergedVaryings);
1485 mState.updateTransformFeedbackStrides();
1486 }
1487
1488 updateLinkedShaderStages();
1489
1490 mLinkingState.reset(new LinkingState());
1491 mLinkingState->context = context;
1492 mLinkingState->linkingFromBinary = false;
1493 mLinkingState->programHash = programHash;
1494 mLinkingState->linkEvent = mProgram->link(context, *resources, mInfoLog);
1495 mLinkingState->resources = std::move(resources);
1496 mLinkResolved = false;
1497
1498 return angle::Result::Continue;
1499 }
1500
isLinking() const1501 bool Program::isLinking() const
1502 {
1503 return (mLinkingState.get() && mLinkingState->linkEvent->isLinking());
1504 }
1505
resolveLinkImpl(const Context * context)1506 void Program::resolveLinkImpl(const Context *context)
1507 {
1508 ASSERT(mLinkingState.get());
1509
1510 angle::Result result = mLinkingState->linkEvent->wait(context);
1511
1512 mLinked = result == angle::Result::Continue;
1513 mLinkResolved = true;
1514 std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1515 if (!mLinked)
1516 {
1517 return;
1518 }
1519
1520 if (linkingState->linkingFromBinary)
1521 {
1522 // All internal Program state is already loaded from the binary.
1523 return;
1524 }
1525
1526 initInterfaceBlockBindings();
1527
1528 // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1529 // Only successfully linked program can replace the executables.
1530 ASSERT(mLinked);
1531
1532 // Mark implementation-specific unreferenced uniforms as ignored.
1533 mProgram->markUnusedUniformLocations(&mState.mUniformLocations, &mState.mSamplerBindings,
1534 &mState.mImageBindings);
1535
1536 // Must be called after markUnusedUniformLocations.
1537 postResolveLink(context);
1538
1539 // TODO(syoussefi): this might need to be moved to postResolveLink() so it will be called from
1540 // deserialize() as well. http://anglebug.com/3089
1541 setUniformValuesFromBindingQualifiers();
1542
1543 // Save to the program cache.
1544 auto *cache = linkingState->context->getMemoryProgramCache();
1545 if (cache && (mState.mLinkedTransformFeedbackVaryings.empty() ||
1546 !linkingState->context->getFrontendFeatures()
1547 .disableProgramCachingForTransformFeedback.enabled))
1548 {
1549 cache->putProgram(linkingState->programHash, linkingState->context, this);
1550 }
1551 }
1552
updateLinkedShaderStages()1553 void Program::updateLinkedShaderStages()
1554 {
1555 mState.mLinkedShaderStages.reset();
1556
1557 for (const Shader *shader : mState.mAttachedShaders)
1558 {
1559 if (shader)
1560 {
1561 mState.mLinkedShaderStages.set(shader->getType());
1562 }
1563 }
1564 }
1565
updateTransformFeedbackStrides()1566 void ProgramState::updateTransformFeedbackStrides()
1567 {
1568 if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
1569 {
1570 mTransformFeedbackStrides.resize(1);
1571 size_t totalSize = 0;
1572 for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
1573 {
1574 totalSize += varying.size() * VariableExternalSize(varying.type);
1575 }
1576 mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
1577 }
1578 else
1579 {
1580 mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
1581 for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
1582 {
1583 TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
1584 mTransformFeedbackStrides[i] =
1585 static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
1586 }
1587 }
1588 }
1589
updateActiveSamplers()1590 void ProgramState::updateActiveSamplers()
1591 {
1592 mActiveSamplerRefCounts.fill(0);
1593
1594 for (SamplerBinding &samplerBinding : mSamplerBindings)
1595 {
1596 if (samplerBinding.unreferenced)
1597 continue;
1598
1599 for (GLint textureUnit : samplerBinding.boundTextureUnits)
1600 {
1601 if (++mActiveSamplerRefCounts[textureUnit] == 1)
1602 {
1603 mActiveSamplerTypes[textureUnit] = samplerBinding.textureType;
1604 mActiveSamplerFormats[textureUnit] = samplerBinding.format;
1605 }
1606 else
1607 {
1608 if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType)
1609 {
1610 mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
1611 }
1612 if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
1613 {
1614 mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
1615 }
1616 }
1617 mActiveSamplersMask.set(textureUnit);
1618 }
1619 }
1620 }
1621
updateActiveImages()1622 void ProgramState::updateActiveImages()
1623 {
1624 for (ImageBinding &imageBinding : mImageBindings)
1625 {
1626 if (imageBinding.unreferenced)
1627 continue;
1628
1629 for (GLint imageUnit : imageBinding.boundImageUnits)
1630 {
1631 mActiveImagesMask.set(imageUnit);
1632 }
1633 }
1634 }
1635
1636 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1637 void Program::unlink()
1638 {
1639 mState.mAttributes.clear();
1640 mState.mAttributesTypeMask.reset();
1641 mState.mAttributesMask.reset();
1642 mState.mActiveAttribLocationsMask.reset();
1643 mState.mMaxActiveAttribLocation = 0;
1644 mState.mLinkedTransformFeedbackVaryings.clear();
1645 mState.mUniforms.clear();
1646 mState.mUniformLocations.clear();
1647 mState.mUniformBlocks.clear();
1648 mState.mActiveUniformBlockBindings.reset();
1649 mState.mAtomicCounterBuffers.clear();
1650 mState.mOutputVariables.clear();
1651 mState.mOutputLocations.clear();
1652 mState.mSecondaryOutputLocations.clear();
1653 mState.mOutputVariableTypes.clear();
1654 mState.mDrawBufferTypeMask.reset();
1655 mState.mActiveOutputVariables.reset();
1656 mState.mComputeShaderLocalSize.fill(1);
1657 mState.mSamplerBindings.clear();
1658 mState.mImageBindings.clear();
1659 mState.mActiveImagesMask.reset();
1660 mState.mNumViews = -1;
1661 mState.mGeometryShaderInputPrimitiveType = PrimitiveMode::Triangles;
1662 mState.mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
1663 mState.mGeometryShaderInvocations = 1;
1664 mState.mGeometryShaderMaxVertices = 0;
1665 mState.mDrawIDLocation = -1;
1666 mState.mBaseVertexLocation = -1;
1667 mState.mBaseInstanceLocation = -1;
1668
1669 mValidated = false;
1670
1671 mLinked = false;
1672 mInfoLog.reset();
1673 }
1674
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1675 angle::Result Program::loadBinary(const Context *context,
1676 GLenum binaryFormat,
1677 const void *binary,
1678 GLsizei length)
1679 {
1680 ASSERT(mLinkResolved);
1681 unlink();
1682
1683 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1684 return angle::Result::Continue;
1685 #else
1686 ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1687 if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1688 {
1689 mInfoLog << "Invalid program binary format.";
1690 return angle::Result::Continue;
1691 }
1692
1693 BinaryInputStream stream(binary, length);
1694 ANGLE_TRY(deserialize(context, stream, mInfoLog));
1695
1696 // Currently we require the full shader text to compute the program hash.
1697 // We could also store the binary in the internal program cache.
1698
1699 for (size_t uniformBlockIndex = 0; uniformBlockIndex < mState.mUniformBlocks.size();
1700 ++uniformBlockIndex)
1701 {
1702 mDirtyBits.set(uniformBlockIndex);
1703 }
1704
1705 mLinkingState.reset(new LinkingState());
1706 mLinkingState->context = context;
1707 mLinkingState->linkingFromBinary = true;
1708 mLinkingState->linkEvent = mProgram->load(context, &stream, mInfoLog);
1709 mLinkResolved = false;
1710
1711 return angle::Result::Continue;
1712 #endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1713 }
1714
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1715 angle::Result Program::saveBinary(Context *context,
1716 GLenum *binaryFormat,
1717 void *binary,
1718 GLsizei bufSize,
1719 GLsizei *length) const
1720 {
1721 ASSERT(mLinkResolved);
1722 if (binaryFormat)
1723 {
1724 *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1725 }
1726
1727 angle::MemoryBuffer memoryBuf;
1728 serialize(context, &memoryBuf);
1729
1730 GLsizei streamLength = static_cast<GLsizei>(memoryBuf.size());
1731 const uint8_t *streamState = memoryBuf.data();
1732
1733 if (streamLength > bufSize)
1734 {
1735 if (length)
1736 {
1737 *length = 0;
1738 }
1739
1740 // TODO: This should be moved to the validation layer but computing the size of the binary
1741 // before saving it causes the save to happen twice. It may be possible to write the binary
1742 // to a separate buffer, validate sizes and then copy it.
1743 ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1744 }
1745
1746 if (binary)
1747 {
1748 char *ptr = reinterpret_cast<char *>(binary);
1749
1750 memcpy(ptr, streamState, streamLength);
1751 ptr += streamLength;
1752
1753 ASSERT(ptr - streamLength == binary);
1754 }
1755
1756 if (length)
1757 {
1758 *length = streamLength;
1759 }
1760
1761 return angle::Result::Continue;
1762 }
1763
getBinaryLength(Context * context) const1764 GLint Program::getBinaryLength(Context *context) const
1765 {
1766 ASSERT(mLinkResolved);
1767 if (!mLinked)
1768 {
1769 return 0;
1770 }
1771
1772 GLint length;
1773 angle::Result result =
1774 saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1775 if (result != angle::Result::Continue)
1776 {
1777 return 0;
1778 }
1779
1780 return length;
1781 }
1782
setBinaryRetrievableHint(bool retrievable)1783 void Program::setBinaryRetrievableHint(bool retrievable)
1784 {
1785 ASSERT(mLinkResolved);
1786 // TODO(jmadill) : replace with dirty bits
1787 mProgram->setBinaryRetrievableHint(retrievable);
1788 mState.mBinaryRetrieveableHint = retrievable;
1789 }
1790
getBinaryRetrievableHint() const1791 bool Program::getBinaryRetrievableHint() const
1792 {
1793 ASSERT(mLinkResolved);
1794 return mState.mBinaryRetrieveableHint;
1795 }
1796
setSeparable(bool separable)1797 void Program::setSeparable(bool separable)
1798 {
1799 ASSERT(mLinkResolved);
1800 // TODO(yunchao) : replace with dirty bits
1801 if (mState.mSeparable != separable)
1802 {
1803 mProgram->setSeparable(separable);
1804 mState.mSeparable = separable;
1805 }
1806 }
1807
isSeparable() const1808 bool Program::isSeparable() const
1809 {
1810 ASSERT(mLinkResolved);
1811 return mState.mSeparable;
1812 }
1813
deleteSelf(const Context * context)1814 void Program::deleteSelf(const Context *context)
1815 {
1816 ASSERT(mRefCount == 0 && mDeleteStatus);
1817 mResourceManager->deleteProgram(context, mHandle);
1818 }
1819
getRefCount() const1820 unsigned int Program::getRefCount() const
1821 {
1822 return mRefCount;
1823 }
1824
getInfoLogLength() const1825 int Program::getInfoLogLength() const
1826 {
1827 ASSERT(mLinkResolved);
1828 return static_cast<int>(mInfoLog.getLength());
1829 }
1830
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const1831 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
1832 {
1833 ASSERT(mLinkResolved);
1834 return mInfoLog.getLog(bufSize, length, infoLog);
1835 }
1836
getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders) const1837 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const
1838 {
1839 ASSERT(mLinkResolved);
1840 int total = 0;
1841
1842 for (const Shader *shader : mState.mAttachedShaders)
1843 {
1844 if (shader && (total < maxCount))
1845 {
1846 shaders[total] = shader->getHandle();
1847 ++total;
1848 }
1849 }
1850
1851 if (count)
1852 {
1853 *count = total;
1854 }
1855 }
1856
getAttributeLocation(const std::string & name) const1857 GLuint Program::getAttributeLocation(const std::string &name) const
1858 {
1859 ASSERT(mLinkResolved);
1860 return mState.getAttributeLocation(name);
1861 }
1862
isAttribLocationActive(size_t attribLocation) const1863 bool Program::isAttribLocationActive(size_t attribLocation) const
1864 {
1865 ASSERT(mLinkResolved);
1866 ASSERT(attribLocation < mState.mActiveAttribLocationsMask.size());
1867 return mState.mActiveAttribLocationsMask[attribLocation];
1868 }
1869
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const1870 void Program::getActiveAttribute(GLuint index,
1871 GLsizei bufsize,
1872 GLsizei *length,
1873 GLint *size,
1874 GLenum *type,
1875 GLchar *name) const
1876 {
1877 ASSERT(mLinkResolved);
1878 if (!mLinked)
1879 {
1880 if (bufsize > 0)
1881 {
1882 name[0] = '\0';
1883 }
1884
1885 if (length)
1886 {
1887 *length = 0;
1888 }
1889
1890 *type = GL_NONE;
1891 *size = 1;
1892 return;
1893 }
1894
1895 ASSERT(index < mState.mAttributes.size());
1896 const sh::Attribute &attrib = mState.mAttributes[index];
1897
1898 if (bufsize > 0)
1899 {
1900 CopyStringToBuffer(name, attrib.name, bufsize, length);
1901 }
1902
1903 // Always a single 'type' instance
1904 *size = 1;
1905 *type = attrib.type;
1906 }
1907
getActiveAttributeCount() const1908 GLint Program::getActiveAttributeCount() const
1909 {
1910 ASSERT(mLinkResolved);
1911 if (!mLinked)
1912 {
1913 return 0;
1914 }
1915
1916 return static_cast<GLint>(mState.mAttributes.size());
1917 }
1918
getActiveAttributeMaxLength() const1919 GLint Program::getActiveAttributeMaxLength() const
1920 {
1921 ASSERT(mLinkResolved);
1922 if (!mLinked)
1923 {
1924 return 0;
1925 }
1926
1927 size_t maxLength = 0;
1928
1929 for (const sh::Attribute &attrib : mState.mAttributes)
1930 {
1931 maxLength = std::max(attrib.name.length() + 1, maxLength);
1932 }
1933
1934 return static_cast<GLint>(maxLength);
1935 }
1936
getAttributes() const1937 const std::vector<sh::Attribute> &Program::getAttributes() const
1938 {
1939 ASSERT(mLinkResolved);
1940 return mState.mAttributes;
1941 }
1942
getSamplerBindings() const1943 const std::vector<SamplerBinding> &Program::getSamplerBindings() const
1944 {
1945 ASSERT(mLinkResolved);
1946 return mState.mSamplerBindings;
1947 }
1948
getComputeShaderLocalSize() const1949 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
1950 {
1951 ASSERT(mLinkResolved);
1952 return mState.mComputeShaderLocalSize;
1953 }
1954
getGeometryShaderInputPrimitiveType() const1955 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
1956 {
1957 ASSERT(mLinkResolved);
1958 return mState.mGeometryShaderInputPrimitiveType;
1959 }
getGeometryShaderOutputPrimitiveType() const1960 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
1961 {
1962 ASSERT(mLinkResolved);
1963 return mState.mGeometryShaderOutputPrimitiveType;
1964 }
getGeometryShaderInvocations() const1965 GLint Program::getGeometryShaderInvocations() const
1966 {
1967 ASSERT(mLinkResolved);
1968 return mState.mGeometryShaderInvocations;
1969 }
getGeometryShaderMaxVertices() const1970 GLint Program::getGeometryShaderMaxVertices() const
1971 {
1972 ASSERT(mLinkResolved);
1973 return mState.mGeometryShaderMaxVertices;
1974 }
1975
getInputResourceIndex(const GLchar * name) const1976 GLuint Program::getInputResourceIndex(const GLchar *name) const
1977 {
1978 ASSERT(mLinkResolved);
1979 return GetResourceIndexFromName(mState.mAttributes, std::string(name));
1980 }
1981
getOutputResourceIndex(const GLchar * name) const1982 GLuint Program::getOutputResourceIndex(const GLchar *name) const
1983 {
1984 ASSERT(mLinkResolved);
1985 return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
1986 }
1987
getOutputResourceCount() const1988 size_t Program::getOutputResourceCount() const
1989 {
1990 ASSERT(mLinkResolved);
1991 return (mLinked ? mState.mOutputVariables.size() : 0);
1992 }
1993
getOutputVariableTypes() const1994 const std::vector<GLenum> &Program::getOutputVariableTypes() const
1995 {
1996 ASSERT(mLinkResolved);
1997 return mState.mOutputVariableTypes;
1998 }
1999
2000 template <typename T>
getResourceName(GLuint index,const std::vector<T> & resources,GLsizei bufSize,GLsizei * length,GLchar * name) const2001 void Program::getResourceName(GLuint index,
2002 const std::vector<T> &resources,
2003 GLsizei bufSize,
2004 GLsizei *length,
2005 GLchar *name) const
2006 {
2007 if (length)
2008 {
2009 *length = 0;
2010 }
2011
2012 if (!mLinked)
2013 {
2014 if (bufSize > 0)
2015 {
2016 name[0] = '\0';
2017 }
2018 return;
2019 }
2020 ASSERT(index < resources.size());
2021 const auto &resource = resources[index];
2022
2023 if (bufSize > 0)
2024 {
2025 CopyStringToBuffer(name, resource.name, bufSize, length);
2026 }
2027 }
2028
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2029 void Program::getInputResourceName(GLuint index,
2030 GLsizei bufSize,
2031 GLsizei *length,
2032 GLchar *name) const
2033 {
2034 ASSERT(mLinkResolved);
2035 getResourceName(index, mState.mAttributes, bufSize, length, name);
2036 }
2037
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2038 void Program::getOutputResourceName(GLuint index,
2039 GLsizei bufSize,
2040 GLsizei *length,
2041 GLchar *name) const
2042 {
2043 ASSERT(mLinkResolved);
2044 getResourceName(index, mState.mOutputVariables, bufSize, length, name);
2045 }
2046
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2047 void Program::getUniformResourceName(GLuint index,
2048 GLsizei bufSize,
2049 GLsizei *length,
2050 GLchar *name) const
2051 {
2052 ASSERT(mLinkResolved);
2053 getResourceName(index, mState.mUniforms, bufSize, length, name);
2054 }
2055
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2056 void Program::getBufferVariableResourceName(GLuint index,
2057 GLsizei bufSize,
2058 GLsizei *length,
2059 GLchar *name) const
2060 {
2061 ASSERT(mLinkResolved);
2062 getResourceName(index, mState.mBufferVariables, bufSize, length, name);
2063 }
2064
getInputResource(GLuint index) const2065 const sh::Attribute &Program::getInputResource(GLuint index) const
2066 {
2067 ASSERT(mLinkResolved);
2068 ASSERT(index < mState.mAttributes.size());
2069 return mState.mAttributes[index];
2070 }
2071
getOutputResource(GLuint index) const2072 const sh::OutputVariable &Program::getOutputResource(GLuint index) const
2073 {
2074 ASSERT(mLinkResolved);
2075 ASSERT(index < mState.mOutputVariables.size());
2076 return mState.mOutputVariables[index];
2077 }
2078
getAttributeBindings() const2079 const ProgramBindings &Program::getAttributeBindings() const
2080 {
2081 ASSERT(mLinkResolved);
2082 return mAttributeBindings;
2083 }
getUniformLocationBindings() const2084 const ProgramBindings &Program::getUniformLocationBindings() const
2085 {
2086 ASSERT(mLinkResolved);
2087 return mUniformLocationBindings;
2088 }
getFragmentInputBindings() const2089 const ProgramBindings &Program::getFragmentInputBindings() const
2090 {
2091 ASSERT(mLinkResolved);
2092 return mFragmentInputBindings;
2093 }
2094
getDrawBufferTypeMask() const2095 ComponentTypeMask Program::getDrawBufferTypeMask() const
2096 {
2097 ASSERT(mLinkResolved);
2098 return mState.mDrawBufferTypeMask;
2099 }
getAttributesTypeMask() const2100 ComponentTypeMask Program::getAttributesTypeMask() const
2101 {
2102 ASSERT(mLinkResolved);
2103 return mState.mAttributesTypeMask;
2104 }
getAttributesMask() const2105 AttributesMask Program::getAttributesMask() const
2106 {
2107 ASSERT(mLinkResolved);
2108 return mState.mAttributesMask;
2109 }
2110
getTransformFeedbackStrides() const2111 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2112 {
2113 ASSERT(mLinkResolved);
2114 return mState.mTransformFeedbackStrides;
2115 }
2116
getFragDataLocation(const std::string & name) const2117 GLint Program::getFragDataLocation(const std::string &name) const
2118 {
2119 ASSERT(mLinkResolved);
2120 GLint primaryLocation =
2121 GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name);
2122 if (primaryLocation != -1)
2123 {
2124 return primaryLocation;
2125 }
2126 return GetVariableLocation(mState.mOutputVariables, mState.mSecondaryOutputLocations, name);
2127 }
2128
getFragDataIndex(const std::string & name) const2129 GLint Program::getFragDataIndex(const std::string &name) const
2130 {
2131 ASSERT(mLinkResolved);
2132 if (GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name) != -1)
2133 {
2134 return 0;
2135 }
2136 if (GetVariableLocation(mState.mOutputVariables, mState.mSecondaryOutputLocations, name) != -1)
2137 {
2138 return 1;
2139 }
2140 return -1;
2141 }
2142
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2143 void Program::getActiveUniform(GLuint index,
2144 GLsizei bufsize,
2145 GLsizei *length,
2146 GLint *size,
2147 GLenum *type,
2148 GLchar *name) const
2149 {
2150 ASSERT(mLinkResolved);
2151 if (mLinked)
2152 {
2153 // index must be smaller than getActiveUniformCount()
2154 ASSERT(index < mState.mUniforms.size());
2155 const LinkedUniform &uniform = mState.mUniforms[index];
2156
2157 if (bufsize > 0)
2158 {
2159 std::string string = uniform.name;
2160 CopyStringToBuffer(name, string, bufsize, length);
2161 }
2162
2163 *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2164 *type = uniform.type;
2165 }
2166 else
2167 {
2168 if (bufsize > 0)
2169 {
2170 name[0] = '\0';
2171 }
2172
2173 if (length)
2174 {
2175 *length = 0;
2176 }
2177
2178 *size = 0;
2179 *type = GL_NONE;
2180 }
2181 }
2182
getActiveUniformCount() const2183 GLint Program::getActiveUniformCount() const
2184 {
2185 ASSERT(mLinkResolved);
2186 if (mLinked)
2187 {
2188 return static_cast<GLint>(mState.mUniforms.size());
2189 }
2190 else
2191 {
2192 return 0;
2193 }
2194 }
2195
getActiveBufferVariableCount() const2196 size_t Program::getActiveBufferVariableCount() const
2197 {
2198 ASSERT(mLinkResolved);
2199 return mLinked ? mState.mBufferVariables.size() : 0;
2200 }
2201
getActiveUniformMaxLength() const2202 GLint Program::getActiveUniformMaxLength() const
2203 {
2204 ASSERT(mLinkResolved);
2205 size_t maxLength = 0;
2206
2207 if (mLinked)
2208 {
2209 for (const LinkedUniform &uniform : mState.mUniforms)
2210 {
2211 if (!uniform.name.empty())
2212 {
2213 size_t length = uniform.name.length() + 1u;
2214 if (uniform.isArray())
2215 {
2216 length += 3; // Counting in "[0]".
2217 }
2218 maxLength = std::max(length, maxLength);
2219 }
2220 }
2221 }
2222
2223 return static_cast<GLint>(maxLength);
2224 }
2225
isValidUniformLocation(GLint location) const2226 bool Program::isValidUniformLocation(GLint location) const
2227 {
2228 ASSERT(mLinkResolved);
2229 ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2230 return (location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size() &&
2231 mState.mUniformLocations[static_cast<size_t>(location)].used());
2232 }
2233
getUniformByLocation(GLint location) const2234 const LinkedUniform &Program::getUniformByLocation(GLint location) const
2235 {
2236 ASSERT(mLinkResolved);
2237 ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
2238 return mState.mUniforms[mState.getUniformIndexFromLocation(location)];
2239 }
2240
getUniformLocation(GLint location) const2241 const VariableLocation &Program::getUniformLocation(GLint location) const
2242 {
2243 ASSERT(mLinkResolved);
2244 ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
2245 return mState.mUniformLocations[location];
2246 }
2247
getBufferVariableByIndex(GLuint index) const2248 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2249 {
2250 ASSERT(mLinkResolved);
2251 ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2252 return mState.mBufferVariables[index];
2253 }
2254
getUniformLocation(const std::string & name) const2255 GLint Program::getUniformLocation(const std::string &name) const
2256 {
2257 ASSERT(mLinkResolved);
2258 return GetVariableLocation(mState.mUniforms, mState.mUniformLocations, name);
2259 }
2260
getUniformIndex(const std::string & name) const2261 GLuint Program::getUniformIndex(const std::string &name) const
2262 {
2263 ASSERT(mLinkResolved);
2264 return mState.getUniformIndexFromName(name);
2265 }
2266
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)2267 void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2268 {
2269 ASSERT(mLinkResolved);
2270 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2271 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2272 mProgram->setUniform1fv(location, clampedCount, v);
2273 }
2274
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)2275 void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2276 {
2277 ASSERT(mLinkResolved);
2278 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2279 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2280 mProgram->setUniform2fv(location, clampedCount, v);
2281 }
2282
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)2283 void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2284 {
2285 ASSERT(mLinkResolved);
2286 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2287 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2288 mProgram->setUniform3fv(location, clampedCount, v);
2289 }
2290
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)2291 void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2292 {
2293 ASSERT(mLinkResolved);
2294 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2295 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2296 mProgram->setUniform4fv(location, clampedCount, v);
2297 }
2298
setUniform1iv(Context * context,GLint location,GLsizei count,const GLint * v)2299 void Program::setUniform1iv(Context *context, GLint location, GLsizei count, const GLint *v)
2300 {
2301 ASSERT(mLinkResolved);
2302 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2303 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2304
2305 mProgram->setUniform1iv(location, clampedCount, v);
2306
2307 if (mState.isSamplerUniformIndex(locationInfo.index))
2308 {
2309 updateSamplerUniform(context, locationInfo, clampedCount, v);
2310 }
2311 }
2312
setUniform2iv(GLint location,GLsizei count,const GLint * v)2313 void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2314 {
2315 ASSERT(mLinkResolved);
2316 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2317 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2318 mProgram->setUniform2iv(location, clampedCount, v);
2319 }
2320
setUniform3iv(GLint location,GLsizei count,const GLint * v)2321 void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2322 {
2323 ASSERT(mLinkResolved);
2324 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2325 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2326 mProgram->setUniform3iv(location, clampedCount, v);
2327 }
2328
setUniform4iv(GLint location,GLsizei count,const GLint * v)2329 void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2330 {
2331 ASSERT(mLinkResolved);
2332 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2333 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2334 mProgram->setUniform4iv(location, clampedCount, v);
2335 }
2336
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)2337 void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2338 {
2339 ASSERT(mLinkResolved);
2340 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2341 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2342 mProgram->setUniform1uiv(location, clampedCount, v);
2343 }
2344
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)2345 void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2346 {
2347 ASSERT(mLinkResolved);
2348 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2349 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2350 mProgram->setUniform2uiv(location, clampedCount, v);
2351 }
2352
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)2353 void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2354 {
2355 ASSERT(mLinkResolved);
2356 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2357 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2358 mProgram->setUniform3uiv(location, clampedCount, v);
2359 }
2360
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)2361 void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2362 {
2363 ASSERT(mLinkResolved);
2364 const VariableLocation &locationInfo = mState.mUniformLocations[location];
2365 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2366 mProgram->setUniform4uiv(location, clampedCount, v);
2367 }
2368
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2369 void Program::setUniformMatrix2fv(GLint location,
2370 GLsizei count,
2371 GLboolean transpose,
2372 const GLfloat *v)
2373 {
2374 ASSERT(mLinkResolved);
2375 GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
2376 mProgram->setUniformMatrix2fv(location, clampedCount, transpose, v);
2377 }
2378
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2379 void Program::setUniformMatrix3fv(GLint location,
2380 GLsizei count,
2381 GLboolean transpose,
2382 const GLfloat *v)
2383 {
2384 ASSERT(mLinkResolved);
2385 GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
2386 mProgram->setUniformMatrix3fv(location, clampedCount, transpose, v);
2387 }
2388
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2389 void Program::setUniformMatrix4fv(GLint location,
2390 GLsizei count,
2391 GLboolean transpose,
2392 const GLfloat *v)
2393 {
2394 ASSERT(mLinkResolved);
2395 GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
2396 mProgram->setUniformMatrix4fv(location, clampedCount, transpose, v);
2397 }
2398
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2399 void Program::setUniformMatrix2x3fv(GLint location,
2400 GLsizei count,
2401 GLboolean transpose,
2402 const GLfloat *v)
2403 {
2404 ASSERT(mLinkResolved);
2405 GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
2406 mProgram->setUniformMatrix2x3fv(location, clampedCount, transpose, v);
2407 }
2408
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2409 void Program::setUniformMatrix2x4fv(GLint location,
2410 GLsizei count,
2411 GLboolean transpose,
2412 const GLfloat *v)
2413 {
2414 ASSERT(mLinkResolved);
2415 GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
2416 mProgram->setUniformMatrix2x4fv(location, clampedCount, transpose, v);
2417 }
2418
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2419 void Program::setUniformMatrix3x2fv(GLint location,
2420 GLsizei count,
2421 GLboolean transpose,
2422 const GLfloat *v)
2423 {
2424 ASSERT(mLinkResolved);
2425 GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
2426 mProgram->setUniformMatrix3x2fv(location, clampedCount, transpose, v);
2427 }
2428
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2429 void Program::setUniformMatrix3x4fv(GLint location,
2430 GLsizei count,
2431 GLboolean transpose,
2432 const GLfloat *v)
2433 {
2434 ASSERT(mLinkResolved);
2435 GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
2436 mProgram->setUniformMatrix3x4fv(location, clampedCount, transpose, v);
2437 }
2438
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2439 void Program::setUniformMatrix4x2fv(GLint location,
2440 GLsizei count,
2441 GLboolean transpose,
2442 const GLfloat *v)
2443 {
2444 ASSERT(mLinkResolved);
2445 GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
2446 mProgram->setUniformMatrix4x2fv(location, clampedCount, transpose, v);
2447 }
2448
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)2449 void Program::setUniformMatrix4x3fv(GLint location,
2450 GLsizei count,
2451 GLboolean transpose,
2452 const GLfloat *v)
2453 {
2454 ASSERT(mLinkResolved);
2455 GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
2456 mProgram->setUniformMatrix4x3fv(location, clampedCount, transpose, v);
2457 }
2458
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2459 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2460 {
2461 ASSERT(mLinkResolved);
2462 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2463 const std::vector<GLuint> &boundTextureUnits =
2464 mState.mSamplerBindings[samplerIndex].boundTextureUnits;
2465 return boundTextureUnits[uniformLocation.arrayIndex];
2466 }
2467
getUniformfv(const Context * context,GLint location,GLfloat * v) const2468 void Program::getUniformfv(const Context *context, GLint location, GLfloat *v) const
2469 {
2470 ASSERT(mLinkResolved);
2471 const VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2472 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2473
2474 if (uniform.isSampler())
2475 {
2476 *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2477 return;
2478 }
2479
2480 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2481 if (nativeType == GL_FLOAT)
2482 {
2483 mProgram->getUniformfv(context, location, v);
2484 }
2485 else
2486 {
2487 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2488 }
2489 }
2490
getUniformiv(const Context * context,GLint location,GLint * v) const2491 void Program::getUniformiv(const Context *context, GLint location, GLint *v) const
2492 {
2493 ASSERT(mLinkResolved);
2494 const VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2495 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2496
2497 if (uniform.isSampler())
2498 {
2499 *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2500 return;
2501 }
2502
2503 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2504 if (nativeType == GL_INT || nativeType == GL_BOOL)
2505 {
2506 mProgram->getUniformiv(context, location, v);
2507 }
2508 else
2509 {
2510 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2511 }
2512 }
2513
getUniformuiv(const Context * context,GLint location,GLuint * v) const2514 void Program::getUniformuiv(const Context *context, GLint location, GLuint *v) const
2515 {
2516 ASSERT(mLinkResolved);
2517 const VariableLocation &uniformLocation = mState.getUniformLocations()[location];
2518 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2519
2520 if (uniform.isSampler())
2521 {
2522 *v = getSamplerUniformBinding(uniformLocation);
2523 return;
2524 }
2525
2526 const GLenum nativeType = VariableComponentType(uniform.type);
2527 if (nativeType == GL_UNSIGNED_INT)
2528 {
2529 mProgram->getUniformuiv(context, location, v);
2530 }
2531 else
2532 {
2533 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2534 }
2535 }
2536
flagForDeletion()2537 void Program::flagForDeletion()
2538 {
2539 ASSERT(mLinkResolved);
2540 mDeleteStatus = true;
2541 }
2542
isFlaggedForDeletion() const2543 bool Program::isFlaggedForDeletion() const
2544 {
2545 ASSERT(mLinkResolved);
2546 return mDeleteStatus;
2547 }
2548
validate(const Caps & caps)2549 void Program::validate(const Caps &caps)
2550 {
2551 ASSERT(mLinkResolved);
2552 mInfoLog.reset();
2553
2554 if (mLinked)
2555 {
2556 mValidated = ConvertToBool(mProgram->validate(caps, &mInfoLog));
2557 }
2558 else
2559 {
2560 mInfoLog << "Program has not been successfully linked.";
2561 }
2562 }
2563
validateSamplersImpl(InfoLog * infoLog,const Caps & caps)2564 bool Program::validateSamplersImpl(InfoLog *infoLog, const Caps &caps)
2565 {
2566 ASSERT(mLinkResolved);
2567
2568 // if any two active samplers in a program are of different types, but refer to the same
2569 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2570 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
2571 for (size_t textureUnit : mState.mActiveSamplersMask)
2572 {
2573 if (mState.mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
2574 {
2575 if (infoLog)
2576 {
2577 (*infoLog) << "Samplers of conflicting types refer to the same texture "
2578 "image unit ("
2579 << textureUnit << ").";
2580 }
2581
2582 mCachedValidateSamplersResult = false;
2583 return false;
2584 }
2585 }
2586
2587 mCachedValidateSamplersResult = true;
2588 return true;
2589 }
2590
isValidated() const2591 bool Program::isValidated() const
2592 {
2593 ASSERT(mLinkResolved);
2594 return mValidated;
2595 }
2596
getActiveUniformBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2597 void Program::getActiveUniformBlockName(const GLuint blockIndex,
2598 GLsizei bufSize,
2599 GLsizei *length,
2600 GLchar *blockName) const
2601 {
2602 ASSERT(mLinkResolved);
2603 GetInterfaceBlockName(blockIndex, mState.mUniformBlocks, bufSize, length, blockName);
2604 }
2605
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2606 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
2607 GLsizei bufSize,
2608 GLsizei *length,
2609 GLchar *blockName) const
2610 {
2611 ASSERT(mLinkResolved);
2612 GetInterfaceBlockName(blockIndex, mState.mShaderStorageBlocks, bufSize, length, blockName);
2613 }
2614
2615 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const2616 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
2617 {
2618 int maxLength = 0;
2619
2620 if (mLinked)
2621 {
2622 for (const T &resource : resources)
2623 {
2624 if (!resource.name.empty())
2625 {
2626 int length = static_cast<int>(resource.nameWithArrayIndex().length());
2627 maxLength = std::max(length + 1, maxLength);
2628 }
2629 }
2630 }
2631
2632 return maxLength;
2633 }
2634
getActiveUniformBlockMaxNameLength() const2635 GLint Program::getActiveUniformBlockMaxNameLength() const
2636 {
2637 ASSERT(mLinkResolved);
2638 return getActiveInterfaceBlockMaxNameLength(mState.mUniformBlocks);
2639 }
2640
getActiveShaderStorageBlockMaxNameLength() const2641 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
2642 {
2643 ASSERT(mLinkResolved);
2644 return getActiveInterfaceBlockMaxNameLength(mState.mShaderStorageBlocks);
2645 }
2646
getUniformBlockIndex(const std::string & name) const2647 GLuint Program::getUniformBlockIndex(const std::string &name) const
2648 {
2649 ASSERT(mLinkResolved);
2650 return GetInterfaceBlockIndex(mState.mUniformBlocks, name);
2651 }
2652
getShaderStorageBlockIndex(const std::string & name) const2653 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
2654 {
2655 ASSERT(mLinkResolved);
2656 return GetInterfaceBlockIndex(mState.mShaderStorageBlocks, name);
2657 }
2658
getUniformBlockByIndex(GLuint index) const2659 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
2660 {
2661 ASSERT(mLinkResolved);
2662 ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size()));
2663 return mState.mUniformBlocks[index];
2664 }
2665
getShaderStorageBlockByIndex(GLuint index) const2666 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
2667 {
2668 ASSERT(mLinkResolved);
2669 ASSERT(index < static_cast<GLuint>(mState.mShaderStorageBlocks.size()));
2670 return mState.mShaderStorageBlocks[index];
2671 }
2672
bindUniformBlock(GLuint uniformBlockIndex,GLuint uniformBlockBinding)2673 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
2674 {
2675 ASSERT(mLinkResolved);
2676 mState.mUniformBlocks[uniformBlockIndex].binding = uniformBlockBinding;
2677 mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlockBinding != 0);
2678 mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex);
2679 }
2680
getUniformBlockBinding(GLuint uniformBlockIndex) const2681 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
2682 {
2683 ASSERT(mLinkResolved);
2684 return mState.getUniformBlockBinding(uniformBlockIndex);
2685 }
2686
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const2687 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
2688 {
2689 ASSERT(mLinkResolved);
2690 return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
2691 }
2692
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2693 void Program::setTransformFeedbackVaryings(GLsizei count,
2694 const GLchar *const *varyings,
2695 GLenum bufferMode)
2696 {
2697 ASSERT(mLinkResolved);
2698 mState.mTransformFeedbackVaryingNames.resize(count);
2699 for (GLsizei i = 0; i < count; i++)
2700 {
2701 mState.mTransformFeedbackVaryingNames[i] = varyings[i];
2702 }
2703
2704 mState.mTransformFeedbackBufferMode = bufferMode;
2705 }
2706
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2707 void Program::getTransformFeedbackVarying(GLuint index,
2708 GLsizei bufSize,
2709 GLsizei *length,
2710 GLsizei *size,
2711 GLenum *type,
2712 GLchar *name) const
2713 {
2714 ASSERT(mLinkResolved);
2715 if (mLinked)
2716 {
2717 ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size());
2718 const auto &var = mState.mLinkedTransformFeedbackVaryings[index];
2719 std::string varName = var.nameWithArrayIndex();
2720 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
2721 if (length)
2722 {
2723 *length = lastNameIdx;
2724 }
2725 if (size)
2726 {
2727 *size = var.size();
2728 }
2729 if (type)
2730 {
2731 *type = var.type;
2732 }
2733 if (name)
2734 {
2735 memcpy(name, varName.c_str(), lastNameIdx);
2736 name[lastNameIdx] = '\0';
2737 }
2738 }
2739 }
2740
getTransformFeedbackVaryingCount() const2741 GLsizei Program::getTransformFeedbackVaryingCount() const
2742 {
2743 ASSERT(mLinkResolved);
2744 if (mLinked)
2745 {
2746 return static_cast<GLsizei>(mState.mLinkedTransformFeedbackVaryings.size());
2747 }
2748 else
2749 {
2750 return 0;
2751 }
2752 }
2753
getTransformFeedbackVaryingMaxLength() const2754 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
2755 {
2756 ASSERT(mLinkResolved);
2757 if (mLinked)
2758 {
2759 GLsizei maxSize = 0;
2760 for (const auto &var : mState.mLinkedTransformFeedbackVaryings)
2761 {
2762 maxSize =
2763 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
2764 }
2765
2766 return maxSize;
2767 }
2768 else
2769 {
2770 return 0;
2771 }
2772 }
2773
getTransformFeedbackBufferMode() const2774 GLenum Program::getTransformFeedbackBufferMode() const
2775 {
2776 ASSERT(mLinkResolved);
2777 return mState.mTransformFeedbackBufferMode;
2778 }
2779
linkValidateShaders(InfoLog & infoLog)2780 bool Program::linkValidateShaders(InfoLog &infoLog)
2781 {
2782 Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
2783 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
2784 Shader *computeShader = mState.mAttachedShaders[ShaderType::Compute];
2785 Shader *geometryShader = mState.mAttachedShaders[ShaderType::Geometry];
2786
2787 bool isComputeShaderAttached = (computeShader != nullptr);
2788 bool isGraphicsShaderAttached =
2789 (vertexShader != nullptr || fragmentShader != nullptr || geometryShader != nullptr);
2790 // Check whether we both have a compute and non-compute shaders attached.
2791 // If there are of both types attached, then linking should fail.
2792 // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
2793 if (isComputeShaderAttached == true && isGraphicsShaderAttached == true)
2794 {
2795 infoLog << "Both compute and graphics shaders are attached to the same program.";
2796 return false;
2797 }
2798
2799 if (computeShader)
2800 {
2801 if (!computeShader->isCompiled())
2802 {
2803 infoLog << "Attached compute shader is not compiled.";
2804 return false;
2805 }
2806 ASSERT(computeShader->getType() == ShaderType::Compute);
2807
2808 mState.mComputeShaderLocalSize = computeShader->getWorkGroupSize();
2809
2810 // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
2811 // If the work group size is not specified, a link time error should occur.
2812 if (!mState.mComputeShaderLocalSize.isDeclared())
2813 {
2814 infoLog << "Work group size is not specified.";
2815 return false;
2816 }
2817 }
2818 else
2819 {
2820 if (!fragmentShader || !fragmentShader->isCompiled())
2821 {
2822 infoLog << "No compiled fragment shader when at least one graphics shader is attached.";
2823 return false;
2824 }
2825 ASSERT(fragmentShader->getType() == ShaderType::Fragment);
2826
2827 if (!vertexShader || !vertexShader->isCompiled())
2828 {
2829 infoLog << "No compiled vertex shader when at least one graphics shader is attached.";
2830 return false;
2831 }
2832 ASSERT(vertexShader->getType() == ShaderType::Vertex);
2833
2834 int vertexShaderVersion = vertexShader->getShaderVersion();
2835 if (fragmentShader->getShaderVersion() != vertexShaderVersion)
2836 {
2837 infoLog << "Fragment shader version does not match vertex shader version.";
2838 return false;
2839 }
2840
2841 if (geometryShader)
2842 {
2843 // [GL_EXT_geometry_shader] Chapter 7
2844 // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
2845 // Language Specification, as well as any of the following reasons:
2846 // * One or more of the shader objects attached to <program> are not compiled
2847 // successfully.
2848 // * The shaders do not use the same shader language version.
2849 // * <program> contains objects to form a geometry shader, and
2850 // - <program> is not separable and contains no objects to form a vertex shader; or
2851 // - the input primitive type, output primitive type, or maximum output vertex count
2852 // is not specified in the compiled geometry shader object.
2853 if (!geometryShader->isCompiled())
2854 {
2855 infoLog << "The attached geometry shader isn't compiled.";
2856 return false;
2857 }
2858
2859 if (geometryShader->getShaderVersion() != vertexShaderVersion)
2860 {
2861 mInfoLog << "Geometry shader version does not match vertex shader version.";
2862 return false;
2863 }
2864 ASSERT(geometryShader->getType() == ShaderType::Geometry);
2865
2866 Optional<PrimitiveMode> inputPrimitive =
2867 geometryShader->getGeometryShaderInputPrimitiveType();
2868 if (!inputPrimitive.valid())
2869 {
2870 mInfoLog << "Input primitive type is not specified in the geometry shader.";
2871 return false;
2872 }
2873
2874 Optional<PrimitiveMode> outputPrimitive =
2875 geometryShader->getGeometryShaderOutputPrimitiveType();
2876 if (!outputPrimitive.valid())
2877 {
2878 mInfoLog << "Output primitive type is not specified in the geometry shader.";
2879 return false;
2880 }
2881
2882 Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
2883 if (!maxVertices.valid())
2884 {
2885 mInfoLog << "'max_vertices' is not specified in the geometry shader.";
2886 return false;
2887 }
2888
2889 mState.mGeometryShaderInputPrimitiveType = inputPrimitive.value();
2890 mState.mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
2891 mState.mGeometryShaderMaxVertices = maxVertices.value();
2892 mState.mGeometryShaderInvocations = geometryShader->getGeometryShaderInvocations();
2893 }
2894 }
2895
2896 return true;
2897 }
2898
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const2899 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
2900 {
2901 ASSERT(mLinkResolved);
2902 for (GLuint tfIndex = 0; tfIndex < mState.mLinkedTransformFeedbackVaryings.size(); ++tfIndex)
2903 {
2904 const auto &tf = mState.mLinkedTransformFeedbackVaryings[tfIndex];
2905 if (tf.nameWithArrayIndex() == name)
2906 {
2907 return tfIndex;
2908 }
2909 }
2910 return GL_INVALID_INDEX;
2911 }
2912
getTransformFeedbackVaryingResource(GLuint index) const2913 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
2914 {
2915 ASSERT(mLinkResolved);
2916 ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size());
2917 return mState.mLinkedTransformFeedbackVaryings[index];
2918 }
2919
hasDrawIDUniform() const2920 bool Program::hasDrawIDUniform() const
2921 {
2922 ASSERT(mLinkResolved);
2923 return mState.mDrawIDLocation >= 0;
2924 }
2925
setDrawIDUniform(GLint drawid)2926 void Program::setDrawIDUniform(GLint drawid)
2927 {
2928 ASSERT(mLinkResolved);
2929 ASSERT(mState.mDrawIDLocation >= 0);
2930 mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
2931 }
2932
hasBaseVertexUniform() const2933 bool Program::hasBaseVertexUniform() const
2934 {
2935 ASSERT(mLinkResolved);
2936 return mState.mBaseVertexLocation >= 0;
2937 }
2938
setBaseVertexUniform(GLint baseVertex)2939 void Program::setBaseVertexUniform(GLint baseVertex)
2940 {
2941 ASSERT(mLinkResolved);
2942 ASSERT(mState.mBaseVertexLocation >= 0);
2943 mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
2944 }
2945
hasBaseInstanceUniform() const2946 bool Program::hasBaseInstanceUniform() const
2947 {
2948 ASSERT(mLinkResolved);
2949 return mState.mBaseInstanceLocation >= 0;
2950 }
2951
setBaseInstanceUniform(GLuint baseInstance)2952 void Program::setBaseInstanceUniform(GLuint baseInstance)
2953 {
2954 ASSERT(mLinkResolved);
2955 ASSERT(mState.mBaseInstanceLocation >= 0);
2956 GLint baseInstanceInt = baseInstance;
2957 mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
2958 }
2959
linkVaryings(InfoLog & infoLog) const2960 bool Program::linkVaryings(InfoLog &infoLog) const
2961 {
2962 Shader *previousShader = nullptr;
2963 for (ShaderType shaderType : kAllGraphicsShaderTypes)
2964 {
2965 Shader *currentShader = mState.mAttachedShaders[shaderType];
2966 if (!currentShader)
2967 {
2968 continue;
2969 }
2970
2971 if (previousShader)
2972 {
2973 if (!linkValidateShaderInterfaceMatching(previousShader, currentShader, infoLog))
2974 {
2975 return false;
2976 }
2977 }
2978 previousShader = currentShader;
2979 }
2980
2981 if (!linkValidateBuiltInVaryings(infoLog))
2982 {
2983 return false;
2984 }
2985
2986 if (!linkValidateFragmentInputBindings(infoLog))
2987 {
2988 return false;
2989 }
2990
2991 return true;
2992 }
2993
2994 // [OpenGL ES 3.1] Chapter 7.4.1 "Shader Interface Matching" Page 91
2995 // TODO(jiawei.shao@intel.com): add validation on input/output blocks matching
linkValidateShaderInterfaceMatching(gl::Shader * generatingShader,gl::Shader * consumingShader,gl::InfoLog & infoLog) const2996 bool Program::linkValidateShaderInterfaceMatching(gl::Shader *generatingShader,
2997 gl::Shader *consumingShader,
2998 gl::InfoLog &infoLog) const
2999 {
3000 ASSERT(generatingShader->getShaderVersion() == consumingShader->getShaderVersion());
3001
3002 const std::vector<sh::Varying> &outputVaryings = generatingShader->getOutputVaryings();
3003 const std::vector<sh::Varying> &inputVaryings = consumingShader->getInputVaryings();
3004
3005 bool validateGeometryShaderInputs = consumingShader->getType() == ShaderType::Geometry;
3006
3007 for (const sh::Varying &input : inputVaryings)
3008 {
3009 bool matched = false;
3010
3011 // Built-in varyings obey special rules
3012 if (input.isBuiltIn())
3013 {
3014 continue;
3015 }
3016
3017 // An output variable is considered to match an input variable in the subsequent
3018 // shader if:
3019 // - the two variables match in name, type, and qualification; or
3020 // - the two variables are declared with the same location qualifier and
3021 // match in type and qualification.
3022 for (const sh::Varying &output : outputVaryings)
3023 {
3024 bool namesMatch = input.name == output.name;
3025 bool locationsMatch = (input.location != -1) && (input.location == output.location);
3026
3027 if (namesMatch || locationsMatch)
3028 {
3029 ASSERT(!output.isBuiltIn());
3030
3031 std::string mismatchedStructFieldName;
3032 LinkMismatchError linkError =
3033 LinkValidateVaryings(output, input, generatingShader->getShaderVersion(),
3034 validateGeometryShaderInputs, &mismatchedStructFieldName);
3035 if (linkError != LinkMismatchError::NO_MISMATCH)
3036 {
3037 LogLinkMismatch(infoLog, input.name, "varying", linkError,
3038 mismatchedStructFieldName, generatingShader->getType(),
3039 consumingShader->getType());
3040 return false;
3041 }
3042
3043 matched = true;
3044 break;
3045 }
3046 }
3047
3048 // We permit unmatched, unreferenced varyings. Note that this specifically depends on
3049 // whether the input is statically used - a statically used input should fail this test even
3050 // if it is not active. GLSL ES 3.00.6 section 4.3.10.
3051 if (!matched && input.staticUse)
3052 {
3053 infoLog << GetShaderTypeString(consumingShader->getType()) << " varying " << input.name
3054 << " does not match any " << GetShaderTypeString(generatingShader->getType())
3055 << " varying";
3056 return false;
3057 }
3058 }
3059
3060 // TODO(jmadill): verify no unmatched output varyings?
3061
3062 return true;
3063 }
3064
linkValidateFragmentInputBindings(gl::InfoLog & infoLog) const3065 bool Program::linkValidateFragmentInputBindings(gl::InfoLog &infoLog) const
3066 {
3067 ASSERT(mState.mAttachedShaders[ShaderType::Fragment]);
3068
3069 std::map<GLuint, std::string> staticFragmentInputLocations;
3070
3071 const std::vector<sh::Varying> &fragmentInputVaryings =
3072 mState.mAttachedShaders[ShaderType::Fragment]->getInputVaryings();
3073 for (const sh::Varying &input : fragmentInputVaryings)
3074 {
3075 if (input.isBuiltIn() || !input.staticUse)
3076 {
3077 continue;
3078 }
3079
3080 const auto inputBinding = mFragmentInputBindings.getBinding(input);
3081 if (inputBinding == -1)
3082 continue;
3083
3084 const auto it = staticFragmentInputLocations.find(inputBinding);
3085 if (it == std::end(staticFragmentInputLocations))
3086 {
3087 staticFragmentInputLocations.insert(std::make_pair(inputBinding, input.name));
3088 }
3089 else
3090 {
3091 infoLog << "Binding for fragment input " << input.name << " conflicts with "
3092 << it->second;
3093 return false;
3094 }
3095 }
3096
3097 return true;
3098 }
3099
linkUniforms(const Caps & caps,InfoLog & infoLog,const ProgramBindings & uniformLocationBindings,GLuint * combinedImageUniformsCount,std::vector<UnusedUniform> * unusedUniforms)3100 bool Program::linkUniforms(const Caps &caps,
3101 InfoLog &infoLog,
3102 const ProgramBindings &uniformLocationBindings,
3103 GLuint *combinedImageUniformsCount,
3104 std::vector<UnusedUniform> *unusedUniforms)
3105 {
3106 UniformLinker linker(mState);
3107 if (!linker.link(caps, infoLog, uniformLocationBindings))
3108 {
3109 return false;
3110 }
3111
3112 linker.getResults(&mState.mUniforms, unusedUniforms, &mState.mUniformLocations);
3113
3114 linkSamplerAndImageBindings(combinedImageUniformsCount);
3115
3116 if (!linkAtomicCounterBuffers())
3117 {
3118 return false;
3119 }
3120
3121 return true;
3122 }
3123
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)3124 void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
3125 {
3126 ASSERT(combinedImageUniforms);
3127
3128 unsigned int high = static_cast<unsigned int>(mState.mUniforms.size());
3129 unsigned int low = high;
3130
3131 for (auto counterIter = mState.mUniforms.rbegin();
3132 counterIter != mState.mUniforms.rend() && counterIter->isAtomicCounter(); ++counterIter)
3133 {
3134 --low;
3135 }
3136
3137 mState.mAtomicCounterUniformRange = RangeUI(low, high);
3138
3139 high = low;
3140
3141 for (auto imageIter = mState.mUniforms.rbegin();
3142 imageIter != mState.mUniforms.rend() && imageIter->isImage(); ++imageIter)
3143 {
3144 --low;
3145 }
3146
3147 mState.mImageUniformRange = RangeUI(low, high);
3148 *combinedImageUniforms = 0u;
3149 // If uniform is a image type, insert it into the mImageBindings array.
3150 for (unsigned int imageIndex : mState.mImageUniformRange)
3151 {
3152 // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
3153 // cannot load values into a uniform defined as an image. if declare without a
3154 // binding qualifier, any uniform image variable (include all elements of
3155 // unbound image array) shoud be bound to unit zero.
3156 auto &imageUniform = mState.mUniforms[imageIndex];
3157 if (imageUniform.binding == -1)
3158 {
3159 mState.mImageBindings.emplace_back(
3160 ImageBinding(imageUniform.getBasicTypeElementCount()));
3161 }
3162 else
3163 {
3164 mState.mImageBindings.emplace_back(
3165 ImageBinding(imageUniform.binding, imageUniform.getBasicTypeElementCount(), false));
3166 }
3167
3168 GLuint arraySize = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
3169 *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
3170 }
3171
3172 high = low;
3173
3174 for (auto samplerIter = mState.mUniforms.rbegin() + mState.mImageUniformRange.length();
3175 samplerIter != mState.mUniforms.rend() && samplerIter->isSampler(); ++samplerIter)
3176 {
3177 --low;
3178 }
3179
3180 mState.mSamplerUniformRange = RangeUI(low, high);
3181
3182 // If uniform is a sampler type, insert it into the mSamplerBindings array.
3183 for (unsigned int samplerIndex : mState.mSamplerUniformRange)
3184 {
3185 const auto &samplerUniform = mState.mUniforms[samplerIndex];
3186 TextureType textureType = SamplerTypeToTextureType(samplerUniform.type);
3187 unsigned int elementCount = samplerUniform.getBasicTypeElementCount();
3188 SamplerFormat format = samplerUniform.typeInfo->samplerFormat;
3189 mState.mSamplerBindings.emplace_back(textureType, format, elementCount, false);
3190 }
3191 }
3192
linkAtomicCounterBuffers()3193 bool Program::linkAtomicCounterBuffers()
3194 {
3195 for (unsigned int index : mState.mAtomicCounterUniformRange)
3196 {
3197 auto &uniform = mState.mUniforms[index];
3198 uniform.blockInfo.offset = uniform.offset;
3199 uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0);
3200 uniform.blockInfo.matrixStride = 0;
3201 uniform.blockInfo.isRowMajorMatrix = false;
3202
3203 bool found = false;
3204 for (unsigned int bufferIndex = 0; bufferIndex < mState.mAtomicCounterBuffers.size();
3205 ++bufferIndex)
3206 {
3207 auto &buffer = mState.mAtomicCounterBuffers[bufferIndex];
3208 if (buffer.binding == uniform.binding)
3209 {
3210 buffer.memberIndexes.push_back(index);
3211 uniform.bufferIndex = bufferIndex;
3212 found = true;
3213 buffer.unionReferencesWith(uniform);
3214 break;
3215 }
3216 }
3217 if (!found)
3218 {
3219 AtomicCounterBuffer atomicCounterBuffer;
3220 atomicCounterBuffer.binding = uniform.binding;
3221 atomicCounterBuffer.memberIndexes.push_back(index);
3222 atomicCounterBuffer.unionReferencesWith(uniform);
3223 mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer);
3224 uniform.bufferIndex = static_cast<int>(mState.mAtomicCounterBuffers.size() - 1);
3225 }
3226 }
3227 // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
3228 // gl_Max[Vertex|Fragment|Compute|Geometry|Combined]AtomicCounterBuffers.
3229
3230 return true;
3231 }
3232
3233 // Assigns locations to all attributes from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3234 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3235 {
3236 const Caps &caps = context->getCaps();
3237 const Limitations &limitations = context->getLimitations();
3238 bool webglCompatibility = context->getExtensions().webglCompatibility;
3239
3240 Shader *vertexShader = mState.getAttachedShader(ShaderType::Vertex);
3241
3242 int shaderVersion = vertexShader->getShaderVersion();
3243
3244 unsigned int usedLocations = 0;
3245 if (shaderVersion >= 300)
3246 {
3247 // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes - see GLSL
3248 // ES 3.00.6 section 12.46. Inactive attributes will be pruned after aliasing checks.
3249 mState.mAttributes = vertexShader->getAllAttributes();
3250 }
3251 else
3252 {
3253 // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3254 mState.mAttributes = vertexShader->getActiveAttributes();
3255 }
3256 GLuint maxAttribs = caps.maxVertexAttributes;
3257
3258 std::vector<sh::Attribute *> usedAttribMap(maxAttribs, nullptr);
3259
3260 // Assign locations to attributes that have a binding location and check for attribute aliasing.
3261 for (sh::Attribute &attribute : mState.mAttributes)
3262 {
3263 // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3264 // structures, so we don't need to worry about adjusting their names or generating entries
3265 // for each member/element (unlike uniforms for example).
3266 ASSERT(!attribute.isArray() && !attribute.isStruct());
3267
3268 int bindingLocation = mAttributeBindings.getBinding(attribute);
3269 if (attribute.location == -1 && bindingLocation != -1)
3270 {
3271 attribute.location = bindingLocation;
3272 }
3273
3274 if (attribute.location != -1)
3275 {
3276 // Location is set by glBindAttribLocation or by location layout qualifier
3277 const int regs = VariableRegisterCount(attribute.type);
3278
3279 if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3280 {
3281 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3282 << " is too big to fit";
3283
3284 return false;
3285 }
3286
3287 for (int reg = 0; reg < regs; reg++)
3288 {
3289 const int regLocation = attribute.location + reg;
3290 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3291
3292 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3293 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3294 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3295 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3296 if (linkedAttribute)
3297 {
3298 if (shaderVersion >= 300 || webglCompatibility ||
3299 limitations.noVertexAttributeAliasing)
3300 {
3301 infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3302 << linkedAttribute->name << "' at location " << regLocation;
3303 return false;
3304 }
3305 }
3306 else
3307 {
3308 usedAttribMap[regLocation] = &attribute;
3309 }
3310
3311 usedLocations |= 1 << regLocation;
3312 }
3313 }
3314 }
3315
3316 // Assign locations to attributes that don't have a binding location.
3317 for (sh::Attribute &attribute : mState.mAttributes)
3318 {
3319 // Not set by glBindAttribLocation or by location layout qualifier
3320 if (attribute.location == -1)
3321 {
3322 int regs = VariableRegisterCount(attribute.type);
3323 int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3324
3325 if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3326 {
3327 infoLog << "Too many attributes (" << attribute.name << ")";
3328 return false;
3329 }
3330
3331 attribute.location = availableIndex;
3332 }
3333 }
3334
3335 ASSERT(mState.mAttributesTypeMask.none());
3336 ASSERT(mState.mAttributesMask.none());
3337
3338 // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3339 // shader versions we're only processing active attributes to begin with.
3340 if (shaderVersion >= 300)
3341 {
3342 for (auto attributeIter = mState.mAttributes.begin();
3343 attributeIter != mState.mAttributes.end();)
3344 {
3345 if (attributeIter->active)
3346 {
3347 ++attributeIter;
3348 }
3349 else
3350 {
3351 attributeIter = mState.mAttributes.erase(attributeIter);
3352 }
3353 }
3354 }
3355
3356 for (const sh::Attribute &attribute : mState.mAttributes)
3357 {
3358 ASSERT(attribute.active);
3359 ASSERT(attribute.location != -1);
3360 unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3361
3362 for (unsigned int r = 0; r < regs; r++)
3363 {
3364 unsigned int location = static_cast<unsigned int>(attribute.location) + r;
3365 mState.mActiveAttribLocationsMask.set(location);
3366 mState.mMaxActiveAttribLocation =
3367 std::max(mState.mMaxActiveAttribLocation, location + 1);
3368
3369 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
3370 if (!attribute.isBuiltIn())
3371 {
3372 ComponentType componentType =
3373 GLenumToComponentType(VariableComponentType(attribute.type));
3374
3375 SetComponentTypeMask(componentType, location, &mState.mAttributesTypeMask);
3376 mState.mAttributesMask.set(location);
3377 }
3378 }
3379 }
3380
3381 return true;
3382 }
3383
linkInterfaceBlocks(const Caps & caps,const Version & version,bool webglCompatibility,InfoLog & infoLog,GLuint * combinedShaderStorageBlocksCount)3384 bool Program::linkInterfaceBlocks(const Caps &caps,
3385 const Version &version,
3386 bool webglCompatibility,
3387 InfoLog &infoLog,
3388 GLuint *combinedShaderStorageBlocksCount)
3389 {
3390 ASSERT(combinedShaderStorageBlocksCount);
3391
3392 GLuint combinedUniformBlocksCount = 0u;
3393 GLuint numShadersHasUniformBlocks = 0u;
3394 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
3395 for (ShaderType shaderType : AllShaderTypes())
3396 {
3397 Shader *shader = mState.mAttachedShaders[shaderType];
3398 if (!shader)
3399 {
3400 continue;
3401 }
3402
3403 const auto &uniformBlocks = shader->getUniformBlocks();
3404 if (!uniformBlocks.empty())
3405 {
3406 if (!ValidateInterfaceBlocksCount(
3407 caps.maxShaderUniformBlocks[shaderType], uniformBlocks, shaderType,
3408 sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
3409 {
3410 return false;
3411 }
3412
3413 allShaderUniformBlocks[shaderType] = &uniformBlocks;
3414 ++numShadersHasUniformBlocks;
3415 }
3416 }
3417
3418 if (combinedUniformBlocksCount > caps.maxCombinedUniformBlocks)
3419 {
3420 infoLog << "The sum of the number of active uniform blocks exceeds "
3421 "MAX_COMBINED_UNIFORM_BLOCKS ("
3422 << caps.maxCombinedUniformBlocks << ").";
3423 return false;
3424 }
3425
3426 if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
3427 webglCompatibility))
3428 {
3429 return false;
3430 }
3431
3432 if (version >= Version(3, 1))
3433 {
3434 *combinedShaderStorageBlocksCount = 0u;
3435 GLuint numShadersHasShaderStorageBlocks = 0u;
3436 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
3437 for (ShaderType shaderType : AllShaderTypes())
3438 {
3439 Shader *shader = mState.mAttachedShaders[shaderType];
3440 if (!shader)
3441 {
3442 continue;
3443 }
3444
3445 const auto &shaderStorageBlocks = shader->getShaderStorageBlocks();
3446 if (!shaderStorageBlocks.empty())
3447 {
3448 if (!ValidateInterfaceBlocksCount(
3449 caps.maxShaderStorageBlocks[shaderType], shaderStorageBlocks, shaderType,
3450 sh::BlockType::BLOCK_BUFFER, combinedShaderStorageBlocksCount, infoLog))
3451 {
3452 return false;
3453 }
3454
3455 allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
3456 ++numShadersHasShaderStorageBlocks;
3457 }
3458 }
3459
3460 if (*combinedShaderStorageBlocksCount > caps.maxCombinedShaderStorageBlocks)
3461 {
3462 infoLog << "The sum of the number of active shader storage blocks exceeds "
3463 "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
3464 << caps.maxCombinedShaderStorageBlocks << ").";
3465 return false;
3466 }
3467
3468 if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
3469 infoLog, webglCompatibility))
3470 {
3471 return false;
3472 }
3473 }
3474
3475 return true;
3476 }
3477
LinkValidateVariablesBase(const sh::ShaderVariable & variable1,const sh::ShaderVariable & variable2,bool validatePrecision,bool validateArraySize,std::string * mismatchedStructOrBlockMemberName)3478 LinkMismatchError Program::LinkValidateVariablesBase(const sh::ShaderVariable &variable1,
3479 const sh::ShaderVariable &variable2,
3480 bool validatePrecision,
3481 bool validateArraySize,
3482 std::string *mismatchedStructOrBlockMemberName)
3483 {
3484 if (variable1.type != variable2.type)
3485 {
3486 return LinkMismatchError::TYPE_MISMATCH;
3487 }
3488 if (validateArraySize && variable1.arraySizes != variable2.arraySizes)
3489 {
3490 return LinkMismatchError::ARRAY_SIZE_MISMATCH;
3491 }
3492 if (validatePrecision && variable1.precision != variable2.precision)
3493 {
3494 return LinkMismatchError::PRECISION_MISMATCH;
3495 }
3496 if (variable1.structName != variable2.structName)
3497 {
3498 return LinkMismatchError::STRUCT_NAME_MISMATCH;
3499 }
3500
3501 if (variable1.fields.size() != variable2.fields.size())
3502 {
3503 return LinkMismatchError::FIELD_NUMBER_MISMATCH;
3504 }
3505 const unsigned int numMembers = static_cast<unsigned int>(variable1.fields.size());
3506 for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
3507 {
3508 const sh::ShaderVariable &member1 = variable1.fields[memberIndex];
3509 const sh::ShaderVariable &member2 = variable2.fields[memberIndex];
3510
3511 if (member1.name != member2.name)
3512 {
3513 return LinkMismatchError::FIELD_NAME_MISMATCH;
3514 }
3515
3516 LinkMismatchError linkErrorOnField = LinkValidateVariablesBase(
3517 member1, member2, validatePrecision, true, mismatchedStructOrBlockMemberName);
3518 if (linkErrorOnField != LinkMismatchError::NO_MISMATCH)
3519 {
3520 AddParentPrefix(member1.name, mismatchedStructOrBlockMemberName);
3521 return linkErrorOnField;
3522 }
3523 }
3524
3525 return LinkMismatchError::NO_MISMATCH;
3526 }
3527
LinkValidateVaryings(const sh::Varying & outputVarying,const sh::Varying & inputVarying,int shaderVersion,bool validateGeometryShaderInputVarying,std::string * mismatchedStructFieldName)3528 LinkMismatchError Program::LinkValidateVaryings(const sh::Varying &outputVarying,
3529 const sh::Varying &inputVarying,
3530 int shaderVersion,
3531 bool validateGeometryShaderInputVarying,
3532 std::string *mismatchedStructFieldName)
3533 {
3534 if (validateGeometryShaderInputVarying)
3535 {
3536 // [GL_EXT_geometry_shader] Section 11.1gs.4.3:
3537 // The OpenGL ES Shading Language doesn't support multi-dimensional arrays as shader inputs
3538 // or outputs.
3539 ASSERT(inputVarying.arraySizes.size() == 1u);
3540
3541 // Geometry shader input varyings are not treated as arrays, so a vertex array output
3542 // varying cannot match a geometry shader input varying.
3543 // [GL_EXT_geometry_shader] Section 7.4.1:
3544 // Geometry shader per-vertex input variables and blocks are required to be declared as
3545 // arrays, with each element representing input or output values for a single vertex of a
3546 // multi-vertex primitive. For the purposes of interface matching, such variables and blocks
3547 // are treated as though they were not declared as arrays.
3548 if (outputVarying.isArray())
3549 {
3550 return LinkMismatchError::ARRAY_SIZE_MISMATCH;
3551 }
3552 }
3553
3554 // Skip the validation on the array sizes between a vertex output varying and a geometry input
3555 // varying as it has been done before.
3556 LinkMismatchError linkError =
3557 LinkValidateVariablesBase(outputVarying, inputVarying, false,
3558 !validateGeometryShaderInputVarying, mismatchedStructFieldName);
3559 if (linkError != LinkMismatchError::NO_MISMATCH)
3560 {
3561 return linkError;
3562 }
3563
3564 if (!sh::InterpolationTypesMatch(outputVarying.interpolation, inputVarying.interpolation))
3565 {
3566 return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
3567 }
3568
3569 if (shaderVersion == 100 && outputVarying.isInvariant != inputVarying.isInvariant)
3570 {
3571 return LinkMismatchError::INVARIANCE_MISMATCH;
3572 }
3573
3574 return LinkMismatchError::NO_MISMATCH;
3575 }
3576
linkValidateBuiltInVaryings(InfoLog & infoLog) const3577 bool Program::linkValidateBuiltInVaryings(InfoLog &infoLog) const
3578 {
3579 Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
3580 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
3581 const auto &vertexVaryings = vertexShader->getOutputVaryings();
3582 const auto &fragmentVaryings = fragmentShader->getInputVaryings();
3583 int shaderVersion = vertexShader->getShaderVersion();
3584
3585 if (shaderVersion != 100)
3586 {
3587 // Only ESSL 1.0 has restrictions on matching input and output invariance
3588 return true;
3589 }
3590
3591 bool glPositionIsInvariant = false;
3592 bool glPointSizeIsInvariant = false;
3593 bool glFragCoordIsInvariant = false;
3594 bool glPointCoordIsInvariant = false;
3595
3596 for (const sh::Varying &varying : vertexVaryings)
3597 {
3598 if (!varying.isBuiltIn())
3599 {
3600 continue;
3601 }
3602 if (varying.name.compare("gl_Position") == 0)
3603 {
3604 glPositionIsInvariant = varying.isInvariant;
3605 }
3606 else if (varying.name.compare("gl_PointSize") == 0)
3607 {
3608 glPointSizeIsInvariant = varying.isInvariant;
3609 }
3610 }
3611
3612 for (const sh::Varying &varying : fragmentVaryings)
3613 {
3614 if (!varying.isBuiltIn())
3615 {
3616 continue;
3617 }
3618 if (varying.name.compare("gl_FragCoord") == 0)
3619 {
3620 glFragCoordIsInvariant = varying.isInvariant;
3621 }
3622 else if (varying.name.compare("gl_PointCoord") == 0)
3623 {
3624 glPointCoordIsInvariant = varying.isInvariant;
3625 }
3626 }
3627
3628 // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
3629 // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
3630 // Not requiring invariance to match is supported by:
3631 // dEQP, WebGL CTS, Nexus 5X GLES
3632 if (glFragCoordIsInvariant && !glPositionIsInvariant)
3633 {
3634 infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
3635 "declared invariant.";
3636 return false;
3637 }
3638 if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
3639 {
3640 infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
3641 "declared invariant.";
3642 return false;
3643 }
3644
3645 return true;
3646 }
3647
linkValidateTransformFeedback(const Version & version,InfoLog & infoLog,const ProgramMergedVaryings & varyings,const Caps & caps) const3648 bool Program::linkValidateTransformFeedback(const Version &version,
3649 InfoLog &infoLog,
3650 const ProgramMergedVaryings &varyings,
3651 const Caps &caps) const
3652 {
3653
3654 // Validate the tf names regardless of the actual program varyings.
3655 std::set<std::string> uniqueNames;
3656 for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
3657 {
3658 if (version < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
3659 {
3660 infoLog << "Capture of array elements is undefined and not supported.";
3661 return false;
3662 }
3663 if (version >= Version(3, 1))
3664 {
3665 if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
3666 {
3667 infoLog << "Two transform feedback varyings include the same array element ("
3668 << tfVaryingName << ").";
3669 return false;
3670 }
3671 }
3672 else
3673 {
3674 if (uniqueNames.count(tfVaryingName) > 0)
3675 {
3676 infoLog << "Two transform feedback varyings specify the same output variable ("
3677 << tfVaryingName << ").";
3678 return false;
3679 }
3680 }
3681 uniqueNames.insert(tfVaryingName);
3682 }
3683
3684 // Validate against program varyings.
3685 size_t totalComponents = 0;
3686 for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
3687 {
3688 std::vector<unsigned int> subscripts;
3689 std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
3690
3691 const sh::ShaderVariable *var = FindVaryingOrField(varyings, baseName);
3692 if (var == nullptr)
3693 {
3694 infoLog << "Transform feedback varying " << tfVaryingName
3695 << " does not exist in the vertex shader.";
3696 return false;
3697 }
3698
3699 // Validate the matching variable.
3700 if (var->isStruct())
3701 {
3702 infoLog << "Struct cannot be captured directly (" << baseName << ").";
3703 return false;
3704 }
3705
3706 size_t elementCount = 0;
3707 size_t componentCount = 0;
3708
3709 if (var->isArray())
3710 {
3711 if (version < Version(3, 1))
3712 {
3713 infoLog << "Capture of arrays is undefined and not supported.";
3714 return false;
3715 }
3716
3717 // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
3718 ASSERT(!var->isArrayOfArrays());
3719
3720 if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
3721 {
3722 infoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
3723 return false;
3724 }
3725 elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
3726 }
3727 else
3728 {
3729 if (!subscripts.empty())
3730 {
3731 infoLog << "Varying '" << baseName
3732 << "' is not an array to be captured by element.";
3733 return false;
3734 }
3735 elementCount = 1;
3736 }
3737
3738 // TODO(jmadill): Investigate implementation limits on D3D11
3739 componentCount = VariableComponentCount(var->type) * elementCount;
3740 if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
3741 componentCount > caps.maxTransformFeedbackSeparateComponents)
3742 {
3743 infoLog << "Transform feedback varying " << tfVaryingName << " components ("
3744 << componentCount << ") exceed the maximum separate components ("
3745 << caps.maxTransformFeedbackSeparateComponents << ").";
3746 return false;
3747 }
3748
3749 totalComponents += componentCount;
3750 if (mState.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
3751 totalComponents > caps.maxTransformFeedbackInterleavedComponents)
3752 {
3753 infoLog << "Transform feedback varying total components (" << totalComponents
3754 << ") exceed the maximum interleaved components ("
3755 << caps.maxTransformFeedbackInterleavedComponents << ").";
3756 return false;
3757 }
3758 }
3759 return true;
3760 }
3761
linkValidateGlobalNames(InfoLog & infoLog) const3762 bool Program::linkValidateGlobalNames(InfoLog &infoLog) const
3763 {
3764 const std::vector<sh::Attribute> &attributes =
3765 mState.mAttachedShaders[ShaderType::Vertex]->getActiveAttributes();
3766 std::unordered_map<std::string, const sh::Uniform *> uniformMap;
3767 using BlockAndFieldPair =
3768 std::pair<const sh::InterfaceBlock *, const sh::InterfaceBlockField *>;
3769 std::unordered_map<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap;
3770
3771 for (ShaderType shaderType : kAllGraphicsShaderTypes)
3772 {
3773 Shader *shader = mState.mAttachedShaders[shaderType];
3774 if (!shader)
3775 {
3776 continue;
3777 }
3778
3779 // Build a map of Uniforms
3780 const std::vector<sh::Uniform> uniforms = shader->getUniforms();
3781 for (const auto &uniform : uniforms)
3782 {
3783 uniformMap[uniform.name] = &uniform;
3784 }
3785
3786 // Build a map of Uniform Blocks
3787 // This will also detect any field name conflicts between Uniform Blocks without instance
3788 // names
3789 const std::vector<sh::InterfaceBlock> &uniformBlocks = shader->getUniformBlocks();
3790 for (const auto &uniformBlock : uniformBlocks)
3791 {
3792 // Only uniform blocks without an instance name can create a conflict with their field
3793 // names
3794 if (!uniformBlock.instanceName.empty())
3795 {
3796 continue;
3797 }
3798
3799 for (const auto &field : uniformBlock.fields)
3800 {
3801 if (!uniformBlockFieldMap.count(field.name))
3802 {
3803 // First time we've seen this uniform block field name, so add the
3804 // (Uniform Block, Field) pair immediately since there can't be a conflict yet
3805 BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
3806 std::vector<BlockAndFieldPair> newUniformBlockList;
3807 newUniformBlockList.push_back(blockAndFieldPair);
3808 uniformBlockFieldMap[field.name] = newUniformBlockList;
3809 continue;
3810 }
3811
3812 // We've seen this name before.
3813 // We need to check each of the uniform blocks that contain a field with this name
3814 // to see if there's a conflict or not.
3815 std::vector<BlockAndFieldPair> prevBlockFieldPairs =
3816 uniformBlockFieldMap[field.name];
3817 for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
3818 {
3819 const sh::InterfaceBlock *prevUniformBlock = prevBlockFieldPair.first;
3820 const sh::InterfaceBlockField *prevUniformBlockField =
3821 prevBlockFieldPair.second;
3822
3823 if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
3824 {
3825 // The same uniform block should, by definition, contain the same field name
3826 continue;
3827 }
3828
3829 // The uniform blocks don't match, so check if the necessary field properties
3830 // also match
3831 if ((field.name == prevUniformBlockField->name) &&
3832 (field.type == prevUniformBlockField->type) &&
3833 (field.precision == prevUniformBlockField->precision))
3834 {
3835 infoLog << "Name conflicts between uniform block field names: "
3836 << field.name;
3837 return false;
3838 }
3839 }
3840
3841 // No conflict, so record this pair
3842 BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
3843 uniformBlockFieldMap[field.name].push_back(blockAndFieldPair);
3844 }
3845 }
3846 }
3847
3848 // Validate no uniform names conflict with attribute names
3849 for (const auto &attrib : attributes)
3850 {
3851 if (uniformMap.count(attrib.name))
3852 {
3853 infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
3854 return false;
3855 }
3856 }
3857
3858 // Validate no Uniform Block fields conflict with other Uniforms
3859 for (const auto &uniformBlockField : uniformBlockFieldMap)
3860 {
3861 const std::string &fieldName = uniformBlockField.first;
3862 if (uniformMap.count(fieldName))
3863 {
3864 infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName;
3865 return false;
3866 }
3867 }
3868
3869 return true;
3870 }
3871
gatherTransformFeedbackVaryings(const ProgramMergedVaryings & varyings)3872 void Program::gatherTransformFeedbackVaryings(const ProgramMergedVaryings &varyings)
3873 {
3874 // Gather the linked varyings that are used for transform feedback, they should all exist.
3875 mState.mLinkedTransformFeedbackVaryings.clear();
3876 for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
3877 {
3878 std::vector<unsigned int> subscripts;
3879 std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
3880 size_t subscript = GL_INVALID_INDEX;
3881 if (!subscripts.empty())
3882 {
3883 subscript = subscripts.back();
3884 }
3885 for (const auto &ref : varyings)
3886 {
3887 const sh::Varying *varying = ref.second.get();
3888 if (baseName == varying->name)
3889 {
3890 mState.mLinkedTransformFeedbackVaryings.emplace_back(
3891 *varying, static_cast<GLuint>(subscript));
3892 break;
3893 }
3894 else if (varying->isStruct())
3895 {
3896 GLuint fieldIndex = 0;
3897 const auto *field = FindShaderVarField(*varying, tfVaryingName, &fieldIndex);
3898 if (field != nullptr)
3899 {
3900 mState.mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
3901 break;
3902 }
3903 }
3904 }
3905 }
3906 }
3907
getMergedVaryings() const3908 ProgramMergedVaryings Program::getMergedVaryings() const
3909 {
3910 ProgramMergedVaryings merged;
3911
3912 for (const sh::Varying &varying :
3913 mState.mAttachedShaders[ShaderType::Vertex]->getOutputVaryings())
3914 {
3915 merged[varying.name].vertex = &varying;
3916 }
3917
3918 for (const sh::Varying &varying :
3919 mState.mAttachedShaders[ShaderType::Fragment]->getInputVaryings())
3920 {
3921 merged[varying.name].fragment = &varying;
3922 }
3923
3924 return merged;
3925 }
3926
CompareOutputVariable(const sh::OutputVariable & a,const sh::OutputVariable & b)3927 bool CompareOutputVariable(const sh::OutputVariable &a, const sh::OutputVariable &b)
3928 {
3929 return a.getArraySizeProduct() > b.getArraySizeProduct();
3930 }
3931
getOutputLocationForLink(const sh::OutputVariable & outputVariable) const3932 int Program::getOutputLocationForLink(const sh::OutputVariable &outputVariable) const
3933 {
3934 if (outputVariable.location != -1)
3935 {
3936 return outputVariable.location;
3937 }
3938 int apiLocation = mFragmentOutputLocations.getBinding(outputVariable);
3939 if (apiLocation != -1)
3940 {
3941 return apiLocation;
3942 }
3943 return -1;
3944 }
3945
isOutputSecondaryForLink(const sh::OutputVariable & outputVariable) const3946 bool Program::isOutputSecondaryForLink(const sh::OutputVariable &outputVariable) const
3947 {
3948 if (outputVariable.index != -1)
3949 {
3950 ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
3951 return (outputVariable.index == 1);
3952 }
3953 int apiIndex = mFragmentOutputIndexes.getBinding(outputVariable);
3954 if (apiIndex != -1)
3955 {
3956 // Index layout qualifier from the shader takes precedence, so the index from the API is
3957 // checked only if the index was not set in the shader. This is not specified in the EXT
3958 // spec, but is specified in desktop OpenGL specs.
3959 return (apiIndex == 1);
3960 }
3961 // EXT_blend_func_extended: Outputs get index 0 by default.
3962 return false;
3963 }
3964
3965 namespace
3966 {
3967
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)3968 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
3969 unsigned int baseLocation,
3970 unsigned int elementCount,
3971 const std::vector<VariableLocation> &reservedLocations,
3972 unsigned int variableIndex)
3973 {
3974 if (baseLocation + elementCount > outputLocations.size())
3975 {
3976 elementCount = baseLocation < outputLocations.size()
3977 ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
3978 : 0;
3979 }
3980 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
3981 {
3982 const unsigned int location = baseLocation + elementIndex;
3983 if (outputLocations[location].used())
3984 {
3985 VariableLocation locationInfo(elementIndex, variableIndex);
3986 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
3987 reservedLocations.end())
3988 {
3989 return true;
3990 }
3991 }
3992 }
3993 return false;
3994 }
3995
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)3996 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
3997 unsigned int baseLocation,
3998 unsigned int elementCount,
3999 const std::vector<VariableLocation> &reservedLocations,
4000 unsigned int variableIndex)
4001 {
4002 if (baseLocation + elementCount > outputLocations.size())
4003 {
4004 outputLocations.resize(baseLocation + elementCount);
4005 }
4006 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4007 {
4008 VariableLocation locationInfo(elementIndex, variableIndex);
4009 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4010 reservedLocations.end())
4011 {
4012 const unsigned int location = baseLocation + elementIndex;
4013 outputLocations[location] = locationInfo;
4014 }
4015 }
4016 }
4017
4018 } // anonymous namespace
4019
linkOutputVariables(const Caps & caps,const Extensions & extensions,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount)4020 bool Program::linkOutputVariables(const Caps &caps,
4021 const Extensions &extensions,
4022 const Version &version,
4023 GLuint combinedImageUniformsCount,
4024 GLuint combinedShaderStorageBlocksCount)
4025 {
4026 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
4027 ASSERT(fragmentShader != nullptr);
4028
4029 ASSERT(mState.mOutputVariableTypes.empty());
4030 ASSERT(mState.mActiveOutputVariables.none());
4031 ASSERT(mState.mDrawBufferTypeMask.none());
4032
4033 const auto &outputVariables = fragmentShader->getActiveOutputVariables();
4034 // Gather output variable types
4035 for (const auto &outputVariable : outputVariables)
4036 {
4037 if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
4038 outputVariable.name != "gl_FragData")
4039 {
4040 continue;
4041 }
4042
4043 unsigned int baseLocation =
4044 (outputVariable.location == -1 ? 0u
4045 : static_cast<unsigned int>(outputVariable.location));
4046
4047 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4048 // structures, so we may use getBasicTypeElementCount().
4049 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4050 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4051 {
4052 const unsigned int location = baseLocation + elementIndex;
4053 if (location >= mState.mOutputVariableTypes.size())
4054 {
4055 mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
4056 }
4057 ASSERT(location < mState.mActiveOutputVariables.size());
4058 mState.mActiveOutputVariables.set(location);
4059 mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
4060 ComponentType componentType =
4061 GLenumToComponentType(mState.mOutputVariableTypes[location]);
4062 SetComponentTypeMask(componentType, location, &mState.mDrawBufferTypeMask);
4063 }
4064 }
4065
4066 if (version >= ES_3_1)
4067 {
4068 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
4069 // A link error will be generated if the sum of the number of active image uniforms used in
4070 // all shaders, the number of active shader storage blocks, and the number of active
4071 // fragment shader outputs exceeds the implementation-dependent value of
4072 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
4073 if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
4074 mState.mActiveOutputVariables.count() >
4075 caps.maxCombinedShaderOutputResources)
4076 {
4077 mInfoLog
4078 << "The sum of the number of active image uniforms, active shader storage blocks "
4079 "and active fragment shader outputs exceeds "
4080 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
4081 << caps.maxCombinedShaderOutputResources << ")";
4082 return false;
4083 }
4084 }
4085
4086 // Skip this step for GLES2 shaders.
4087 if (fragmentShader->getShaderVersion() == 100)
4088 return true;
4089
4090 mState.mOutputVariables = outputVariables;
4091 // TODO(jmadill): any caps validation here?
4092
4093 for (sh::OutputVariable &outputVariable : mState.mOutputVariables)
4094 {
4095 if (outputVariable.isArray())
4096 {
4097 // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active
4098 // Resources and including [0] at the end of array variable names.
4099 outputVariable.name += "[0]";
4100 outputVariable.mappedName += "[0]";
4101 }
4102 }
4103
4104 // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
4105 // output array in explicit terms.
4106 //
4107 // Assuming fragData is an output array, you can defend the position that:
4108 // P1) you must support binding "fragData" because it's specified
4109 // P2) you must support querying "fragData[x]" because it's specified
4110 // P3) you must support binding "fragData[0]" because it's a frequently used pattern
4111 //
4112 // Then you can make the leap of faith:
4113 // P4) you must support binding "fragData[x]" because you support "fragData[0]"
4114 // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
4115 //
4116 // The spec brings in the "world of arrays" when it mentions binding the arrays and the
4117 // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
4118 // must infer the only possible interpretation (?). Note again: this need of interpretation
4119 // might be completely off of what GL spec logic is.
4120 //
4121 // The other complexity is that unless you implement this feature, it's hard to understand what
4122 // should happen when the client invokes the feature. You cannot add an additional error as it
4123 // is not specified. One can ignore it, but obviously it creates the discrepancies...
4124
4125 std::vector<VariableLocation> reservedLocations;
4126
4127 // Process any output API bindings for arrays that don't alias to the first element.
4128 for (const auto &binding : mFragmentOutputLocations)
4129 {
4130 size_t nameLengthWithoutArrayIndex;
4131 unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
4132 if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
4133 {
4134 continue;
4135 }
4136 for (unsigned int outputVariableIndex = 0;
4137 outputVariableIndex < mState.mOutputVariables.size(); outputVariableIndex++)
4138 {
4139 const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
4140 // Check that the binding corresponds to an output array and its array index fits.
4141 if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
4142 !angle::BeginsWith(outputVariable.name, binding.first,
4143 nameLengthWithoutArrayIndex) ||
4144 arrayIndex >= outputVariable.getOutermostArraySize())
4145 {
4146 continue;
4147 }
4148
4149 // Get the API index that corresponds to this exact binding.
4150 // This index may differ from the index used for the array's base.
4151 auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1
4152 ? mState.mSecondaryOutputLocations
4153 : mState.mOutputLocations;
4154 unsigned int location = binding.second.location;
4155 VariableLocation locationInfo(arrayIndex, outputVariableIndex);
4156 if (location >= outputLocations.size())
4157 {
4158 outputLocations.resize(location + 1);
4159 }
4160 if (outputLocations[location].used())
4161 {
4162 mInfoLog << "Location of variable " << outputVariable.name
4163 << " conflicts with another variable.";
4164 return false;
4165 }
4166 outputLocations[location] = locationInfo;
4167
4168 // Note the array binding location so that it can be skipped later.
4169 reservedLocations.push_back(locationInfo);
4170 }
4171 }
4172
4173 // Reserve locations for output variables whose location is fixed in the shader or through the
4174 // API. Otherwise, the remaining unallocated outputs will be processed later.
4175 for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
4176 outputVariableIndex++)
4177 {
4178 const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
4179
4180 // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4181 if (outputVariable.isBuiltIn())
4182 continue;
4183
4184 int fixedLocation = getOutputLocationForLink(outputVariable);
4185 if (fixedLocation == -1)
4186 {
4187 // Here we're only reserving locations for variables whose location is fixed.
4188 continue;
4189 }
4190 unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
4191
4192 auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4193 ? mState.mSecondaryOutputLocations
4194 : mState.mOutputLocations;
4195
4196 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4197 // structures, so we may use getBasicTypeElementCount().
4198 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4199 if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
4200 outputVariableIndex))
4201 {
4202 mInfoLog << "Location of variable " << outputVariable.name
4203 << " conflicts with another variable.";
4204 return false;
4205 }
4206 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4207 outputVariableIndex);
4208 }
4209
4210 // Here we assign locations for the output variables that don't yet have them. Note that we're
4211 // not necessarily able to fit the variables optimally, since then we might have to try
4212 // different arrangements of output arrays. Now we just assign the locations in the order that
4213 // we got the output variables. The spec isn't clear on what kind of algorithm is required for
4214 // finding locations for the output variables, so this should be acceptable at least for now.
4215 GLuint maxLocation = caps.maxDrawBuffers;
4216 if (!mState.mSecondaryOutputLocations.empty())
4217 {
4218 // EXT_blend_func_extended: Program outputs will be validated against
4219 // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
4220 maxLocation = extensions.maxDualSourceDrawBuffers;
4221 }
4222
4223 for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
4224 outputVariableIndex++)
4225 {
4226 const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
4227
4228 // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4229 if (outputVariable.isBuiltIn())
4230 continue;
4231
4232 int fixedLocation = getOutputLocationForLink(outputVariable);
4233 auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4234 ? mState.mSecondaryOutputLocations
4235 : mState.mOutputLocations;
4236 unsigned int baseLocation = 0;
4237 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4238 if (fixedLocation != -1)
4239 {
4240 // Secondary inputs might have caused the max location to drop below what has already
4241 // been explicitly assigned locations. Check for any fixed locations above the max
4242 // that should cause linking to fail.
4243 baseLocation = static_cast<unsigned int>(fixedLocation);
4244 }
4245 else
4246 {
4247 // No fixed location, so try to fit the output in unassigned locations.
4248 // Try baseLocations starting from 0 one at a time and see if the variable fits.
4249 while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
4250 reservedLocations, outputVariableIndex))
4251 {
4252 baseLocation++;
4253 }
4254 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4255 outputVariableIndex);
4256 }
4257
4258 // Check for any elements assigned above the max location that are actually used.
4259 if (baseLocation + elementCount > maxLocation &&
4260 (baseLocation >= maxLocation ||
4261 FindUsedOutputLocation(outputLocations, maxLocation,
4262 baseLocation + elementCount - maxLocation, reservedLocations,
4263 outputVariableIndex)))
4264 {
4265 // EXT_blend_func_extended: Linking can fail:
4266 // "if the explicit binding assignments do not leave enough space for the linker to
4267 // automatically assign a location for a varying out array, which requires multiple
4268 // contiguous locations."
4269 mInfoLog << "Could not fit output variable into available locations: "
4270 << outputVariable.name;
4271 return false;
4272 }
4273 }
4274
4275 return true;
4276 }
4277
setUniformValuesFromBindingQualifiers()4278 void Program::setUniformValuesFromBindingQualifiers()
4279 {
4280 for (unsigned int samplerIndex : mState.mSamplerUniformRange)
4281 {
4282 const auto &samplerUniform = mState.mUniforms[samplerIndex];
4283 if (samplerUniform.binding != -1)
4284 {
4285 GLint location = getUniformLocation(samplerUniform.name);
4286 ASSERT(location != -1);
4287 std::vector<GLint> boundTextureUnits;
4288 for (unsigned int elementIndex = 0;
4289 elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
4290 {
4291 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
4292 }
4293
4294 // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
4295 // We know it's safe not to notify the Context because this is only called after link.
4296 setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
4297 boundTextureUnits.data());
4298 }
4299 }
4300 }
4301
initInterfaceBlockBindings()4302 void Program::initInterfaceBlockBindings()
4303 {
4304 // Set initial bindings from shader.
4305 for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++)
4306 {
4307 InterfaceBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
4308 bindUniformBlock(blockIndex, uniformBlock.binding);
4309 }
4310 }
4311
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)4312 void Program::updateSamplerUniform(Context *context,
4313 const VariableLocation &locationInfo,
4314 GLsizei clampedCount,
4315 const GLint *v)
4316 {
4317 ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
4318 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
4319 SamplerBinding &samplerBinding = mState.mSamplerBindings[samplerIndex];
4320 std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
4321
4322 if (samplerBinding.unreferenced)
4323 return;
4324
4325 // Update the sampler uniforms.
4326 for (GLsizei arrayIndex = 0; arrayIndex < clampedCount; ++arrayIndex)
4327 {
4328 GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
4329 GLint newTextureUnit = v[arrayIndex];
4330
4331 if (oldTextureUnit == newTextureUnit)
4332 continue;
4333
4334 boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
4335
4336 // Update the reference counts.
4337 uint32_t &oldRefCount = mState.mActiveSamplerRefCounts[oldTextureUnit];
4338 uint32_t &newRefCount = mState.mActiveSamplerRefCounts[newTextureUnit];
4339 ASSERT(oldRefCount > 0);
4340 ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
4341 oldRefCount--;
4342 newRefCount++;
4343
4344 // Check for binding type change.
4345 TextureType &newSamplerType = mState.mActiveSamplerTypes[newTextureUnit];
4346 TextureType &oldSamplerType = mState.mActiveSamplerTypes[oldTextureUnit];
4347 SamplerFormat &newSamplerFormat = mState.mActiveSamplerFormats[newTextureUnit];
4348 SamplerFormat &oldSamplerFormat = mState.mActiveSamplerFormats[oldTextureUnit];
4349
4350 if (newRefCount == 1)
4351 {
4352 newSamplerType = samplerBinding.textureType;
4353 newSamplerFormat = samplerBinding.format;
4354 mState.mActiveSamplersMask.set(newTextureUnit);
4355 }
4356 else
4357 {
4358 if (newSamplerType != samplerBinding.textureType)
4359 {
4360 // Conflict detected. Ensure we reset it properly.
4361 newSamplerType = TextureType::InvalidEnum;
4362 }
4363 if (newSamplerFormat != samplerBinding.format)
4364 {
4365 newSamplerFormat = SamplerFormat::InvalidEnum;
4366 }
4367 }
4368
4369 // Unset previously active sampler.
4370 if (oldRefCount == 0)
4371 {
4372 oldSamplerType = TextureType::InvalidEnum;
4373 oldSamplerFormat = SamplerFormat::InvalidEnum;
4374 mState.mActiveSamplersMask.reset(oldTextureUnit);
4375 }
4376 else
4377 {
4378 if (oldSamplerType == TextureType::InvalidEnum ||
4379 oldSamplerFormat == SamplerFormat::InvalidEnum)
4380 {
4381 // Previous conflict. Check if this new change fixed the conflict.
4382 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
4383 }
4384 }
4385
4386 // Notify context.
4387 if (context)
4388 {
4389 context->onSamplerUniformChange(newTextureUnit);
4390 context->onSamplerUniformChange(oldTextureUnit);
4391 }
4392 }
4393
4394 // Invalidate the validation cache.
4395 mCachedValidateSamplersResult.reset();
4396 }
4397
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)4398 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
4399 {
4400 bool foundBinding = false;
4401 TextureType foundType = TextureType::InvalidEnum;
4402 SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
4403
4404 for (const SamplerBinding &binding : mSamplerBindings)
4405 {
4406 if (binding.unreferenced)
4407 continue;
4408
4409 // A conflict exists if samplers of different types are sourced by the same texture unit.
4410 // We need to check all bound textures to detect this error case.
4411 for (GLuint textureUnit : binding.boundTextureUnits)
4412 {
4413 if (textureUnit == textureUnitIndex)
4414 {
4415 if (!foundBinding)
4416 {
4417 foundBinding = true;
4418 foundType = binding.textureType;
4419 foundFormat = binding.format;
4420 }
4421 else
4422 {
4423 if (foundType != binding.textureType)
4424 {
4425 foundType = TextureType::InvalidEnum;
4426 }
4427 if (foundFormat != binding.format)
4428 {
4429 foundFormat = SamplerFormat::InvalidEnum;
4430 }
4431 }
4432 }
4433 }
4434 }
4435
4436 mActiveSamplerTypes[textureUnitIndex] = foundType;
4437 mActiveSamplerFormats[textureUnitIndex] = foundFormat;
4438 }
4439
4440 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)4441 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
4442 GLsizei count,
4443 int vectorSize,
4444 const T *v)
4445 {
4446 if (count == 1)
4447 return 1;
4448
4449 const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
4450
4451 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4452 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4453 unsigned int remainingElements =
4454 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4455 GLsizei maxElementCount =
4456 static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
4457
4458 if (count * vectorSize > maxElementCount)
4459 {
4460 return maxElementCount / vectorSize;
4461 }
4462
4463 return count;
4464 }
4465
4466 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(GLint location,GLsizei count,GLboolean transpose,const T * v)4467 GLsizei Program::clampMatrixUniformCount(GLint location,
4468 GLsizei count,
4469 GLboolean transpose,
4470 const T *v)
4471 {
4472 const VariableLocation &locationInfo = mState.mUniformLocations[location];
4473
4474 if (!transpose)
4475 {
4476 return clampUniformCount(locationInfo, count, cols * rows, v);
4477 }
4478
4479 const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
4480
4481 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4482 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4483 unsigned int remainingElements =
4484 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4485 return std::min(count, static_cast<GLsizei>(remainingElements));
4486 }
4487
4488 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
4489 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
4490 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,GLint location,GLenum nativeType,int components) const4491 void Program::getUniformInternal(const Context *context,
4492 DestT *dataOut,
4493 GLint location,
4494 GLenum nativeType,
4495 int components) const
4496 {
4497 switch (nativeType)
4498 {
4499 case GL_BOOL:
4500 {
4501 GLint tempValue[16] = {0};
4502 mProgram->getUniformiv(context, location, tempValue);
4503 UniformStateQueryCastLoop<GLboolean>(
4504 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4505 break;
4506 }
4507 case GL_INT:
4508 {
4509 GLint tempValue[16] = {0};
4510 mProgram->getUniformiv(context, location, tempValue);
4511 UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4512 components);
4513 break;
4514 }
4515 case GL_UNSIGNED_INT:
4516 {
4517 GLuint tempValue[16] = {0};
4518 mProgram->getUniformuiv(context, location, tempValue);
4519 UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4520 components);
4521 break;
4522 }
4523 case GL_FLOAT:
4524 {
4525 GLfloat tempValue[16] = {0};
4526 mProgram->getUniformfv(context, location, tempValue);
4527 UniformStateQueryCastLoop<GLfloat>(
4528 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4529 break;
4530 }
4531 default:
4532 UNREACHABLE();
4533 break;
4534 }
4535 }
4536
syncState(const Context * context)4537 angle::Result Program::syncState(const Context *context)
4538 {
4539 if (mDirtyBits.any())
4540 {
4541 ASSERT(mLinkResolved);
4542 ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
4543 mDirtyBits.reset();
4544 }
4545
4546 return angle::Result::Continue;
4547 }
4548
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const4549 void Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
4550 {
4551 BinaryOutputStream stream;
4552
4553 stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
4554 ANGLE_COMMIT_HASH_SIZE);
4555
4556 // nullptr context is supported when computing binary length.
4557 if (context)
4558 {
4559 stream.writeInt(context->getClientVersion().major);
4560 stream.writeInt(context->getClientVersion().minor);
4561 }
4562 else
4563 {
4564 stream.writeInt(2);
4565 stream.writeInt(0);
4566 }
4567
4568 const auto &computeLocalSize = mState.getComputeShaderLocalSize();
4569
4570 stream.writeInt(computeLocalSize[0]);
4571 stream.writeInt(computeLocalSize[1]);
4572 stream.writeInt(computeLocalSize[2]);
4573
4574 ASSERT(mState.mGeometryShaderInvocations >= 1 && mState.mGeometryShaderMaxVertices >= 0);
4575 stream.writeEnum(mState.mGeometryShaderInputPrimitiveType);
4576 stream.writeEnum(mState.mGeometryShaderOutputPrimitiveType);
4577 stream.writeInt(mState.mGeometryShaderInvocations);
4578 stream.writeInt(mState.mGeometryShaderMaxVertices);
4579
4580 stream.writeInt(mState.mNumViews);
4581
4582 stream.writeInt(mState.mMaxActiveAttribLocation);
4583
4584 static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
4585 "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
4586 stream.writeInt(static_cast<int>(mState.mAttributesTypeMask.to_ulong()));
4587 stream.writeInt(static_cast<int>(mState.mAttributesMask.to_ulong()));
4588
4589 stream.writeInt(mState.getActiveAttribLocationsMask().to_ulong());
4590
4591 stream.writeInt(mState.getAttributes().size());
4592 for (const sh::Attribute &attrib : mState.getAttributes())
4593 {
4594 WriteShaderVar(&stream, attrib);
4595 stream.writeInt(attrib.location);
4596 }
4597
4598 stream.writeInt(mState.getUniforms().size());
4599 for (const LinkedUniform &uniform : mState.getUniforms())
4600 {
4601 WriteShaderVar(&stream, uniform);
4602
4603 // FIXME: referenced
4604
4605 stream.writeInt(uniform.bufferIndex);
4606 WriteBlockMemberInfo(&stream, uniform.blockInfo);
4607
4608 // Active shader info
4609 for (ShaderType shaderType : gl::AllShaderTypes())
4610 {
4611 stream.writeInt(uniform.isActive(shaderType));
4612 }
4613 }
4614
4615 stream.writeInt(mState.getUniformLocations().size());
4616 for (const auto &variable : mState.getUniformLocations())
4617 {
4618 stream.writeInt(variable.arrayIndex);
4619 stream.writeIntOrNegOne(variable.index);
4620 stream.writeInt(variable.ignored);
4621 }
4622
4623 stream.writeInt(mState.getUniformBlocks().size());
4624 for (const InterfaceBlock &uniformBlock : mState.getUniformBlocks())
4625 {
4626 WriteInterfaceBlock(&stream, uniformBlock);
4627 }
4628
4629 stream.writeInt(mState.getBufferVariables().size());
4630 for (const BufferVariable &bufferVariable : mState.getBufferVariables())
4631 {
4632 WriteBufferVariable(&stream, bufferVariable);
4633 }
4634
4635 stream.writeInt(mState.getShaderStorageBlocks().size());
4636 for (const InterfaceBlock &shaderStorageBlock : mState.getShaderStorageBlocks())
4637 {
4638 WriteInterfaceBlock(&stream, shaderStorageBlock);
4639 }
4640
4641 stream.writeInt(mState.mAtomicCounterBuffers.size());
4642 for (const auto &atomicCounterBuffer : mState.mAtomicCounterBuffers)
4643 {
4644 WriteShaderVariableBuffer(&stream, atomicCounterBuffer);
4645 }
4646
4647 // Warn the app layer if saving a binary with unsupported transform feedback.
4648 if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
4649 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4650 {
4651 WARN() << "Saving program binary with transform feedback, which is not supported on this "
4652 "driver.";
4653 }
4654
4655 stream.writeInt(mState.getLinkedTransformFeedbackVaryings().size());
4656 for (const auto &var : mState.getLinkedTransformFeedbackVaryings())
4657 {
4658 stream.writeIntVector(var.arraySizes);
4659 stream.writeInt(var.type);
4660 stream.writeString(var.name);
4661
4662 stream.writeIntOrNegOne(var.arrayIndex);
4663 }
4664
4665 stream.writeInt(mState.getTransformFeedbackBufferMode());
4666
4667 stream.writeInt(mState.getOutputVariables().size());
4668 for (const sh::OutputVariable &output : mState.getOutputVariables())
4669 {
4670 WriteShaderVar(&stream, output);
4671 stream.writeInt(output.location);
4672 stream.writeInt(output.index);
4673 }
4674
4675 stream.writeInt(mState.getOutputLocations().size());
4676 for (const auto &outputVar : mState.getOutputLocations())
4677 {
4678 stream.writeInt(outputVar.arrayIndex);
4679 stream.writeIntOrNegOne(outputVar.index);
4680 stream.writeInt(outputVar.ignored);
4681 }
4682
4683 stream.writeInt(mState.getSecondaryOutputLocations().size());
4684 for (const auto &outputVar : mState.getSecondaryOutputLocations())
4685 {
4686 stream.writeInt(outputVar.arrayIndex);
4687 stream.writeIntOrNegOne(outputVar.index);
4688 stream.writeInt(outputVar.ignored);
4689 }
4690
4691 stream.writeInt(mState.mOutputVariableTypes.size());
4692 for (const auto &outputVariableType : mState.mOutputVariableTypes)
4693 {
4694 stream.writeInt(outputVariableType);
4695 }
4696
4697 static_assert(
4698 IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4699 "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
4700 stream.writeInt(static_cast<int>(mState.mDrawBufferTypeMask.to_ulong()));
4701 stream.writeInt(static_cast<int>(mState.mActiveOutputVariables.to_ulong()));
4702
4703 stream.writeInt(mState.getSamplerUniformRange().low());
4704 stream.writeInt(mState.getSamplerUniformRange().high());
4705
4706 stream.writeInt(mState.getSamplerBindings().size());
4707 for (const auto &samplerBinding : mState.getSamplerBindings())
4708 {
4709 stream.writeEnum(samplerBinding.textureType);
4710 stream.writeEnum(samplerBinding.format);
4711 stream.writeInt(samplerBinding.boundTextureUnits.size());
4712 stream.writeInt(samplerBinding.unreferenced);
4713 }
4714
4715 stream.writeInt(mState.getImageUniformRange().low());
4716 stream.writeInt(mState.getImageUniformRange().high());
4717
4718 stream.writeInt(mState.getImageBindings().size());
4719 for (const auto &imageBinding : mState.getImageBindings())
4720 {
4721 stream.writeInt(imageBinding.boundImageUnits.size());
4722 for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
4723 {
4724 stream.writeInt(imageBinding.boundImageUnits[i]);
4725 }
4726 }
4727
4728 stream.writeInt(mState.getAtomicCounterUniformRange().low());
4729 stream.writeInt(mState.getAtomicCounterUniformRange().high());
4730
4731 stream.writeInt(mState.getLinkedShaderStages().to_ulong());
4732
4733 mProgram->save(context, &stream);
4734
4735 ASSERT(binaryOut);
4736 binaryOut->resize(stream.length());
4737 memcpy(binaryOut->data(), stream.data(), stream.length());
4738 }
4739
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)4740 angle::Result Program::deserialize(const Context *context,
4741 BinaryInputStream &stream,
4742 InfoLog &infoLog)
4743 {
4744 unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
4745 stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
4746 if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
4747 0)
4748 {
4749 infoLog << "Invalid program binary version.";
4750 return angle::Result::Incomplete;
4751 }
4752
4753 int majorVersion = stream.readInt<int>();
4754 int minorVersion = stream.readInt<int>();
4755 if (majorVersion != context->getClientMajorVersion() ||
4756 minorVersion != context->getClientMinorVersion())
4757 {
4758 infoLog << "Cannot load program binaries across different ES context versions.";
4759 return angle::Result::Incomplete;
4760 }
4761
4762 mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
4763 mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
4764 mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
4765
4766 mState.mGeometryShaderInputPrimitiveType = stream.readEnum<PrimitiveMode>();
4767 mState.mGeometryShaderOutputPrimitiveType = stream.readEnum<PrimitiveMode>();
4768 mState.mGeometryShaderInvocations = stream.readInt<int>();
4769 mState.mGeometryShaderMaxVertices = stream.readInt<int>();
4770
4771 mState.mNumViews = stream.readInt<int>();
4772
4773 mState.mMaxActiveAttribLocation = stream.readInt<unsigned int>();
4774
4775 static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
4776 "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
4777 mState.mAttributesTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4778 mState.mAttributesMask = stream.readInt<gl::AttributesMask>();
4779
4780 static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8,
4781 "Too many vertex attribs for mask");
4782 mState.mActiveAttribLocationsMask = stream.readInt<gl::AttributesMask>();
4783
4784 unsigned int attribCount = stream.readInt<unsigned int>();
4785 ASSERT(mState.mAttributes.empty());
4786 for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
4787 {
4788 sh::Attribute attrib;
4789 LoadShaderVar(&stream, &attrib);
4790 attrib.location = stream.readInt<int>();
4791 mState.mAttributes.push_back(attrib);
4792 }
4793
4794 unsigned int uniformCount = stream.readInt<unsigned int>();
4795 ASSERT(mState.mUniforms.empty());
4796 for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
4797 {
4798 LinkedUniform uniform;
4799 LoadShaderVar(&stream, &uniform);
4800
4801 uniform.bufferIndex = stream.readInt<int>();
4802 LoadBlockMemberInfo(&stream, &uniform.blockInfo);
4803
4804 uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
4805
4806 // Active shader info
4807 for (ShaderType shaderType : gl::AllShaderTypes())
4808 {
4809 uniform.setActive(shaderType, stream.readBool());
4810 }
4811
4812 mState.mUniforms.push_back(uniform);
4813 }
4814
4815 const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
4816 ASSERT(mState.mUniformLocations.empty());
4817 for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount;
4818 uniformIndexIndex++)
4819 {
4820 VariableLocation variable;
4821 stream.readInt(&variable.arrayIndex);
4822 stream.readInt(&variable.index);
4823 stream.readBool(&variable.ignored);
4824
4825 mState.mUniformLocations.push_back(variable);
4826 }
4827
4828 unsigned int uniformBlockCount = stream.readInt<unsigned int>();
4829 ASSERT(mState.mUniformBlocks.empty());
4830 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount;
4831 ++uniformBlockIndex)
4832 {
4833 InterfaceBlock uniformBlock;
4834 LoadInterfaceBlock(&stream, &uniformBlock);
4835 mState.mUniformBlocks.push_back(uniformBlock);
4836
4837 mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
4838 }
4839
4840 unsigned int bufferVariableCount = stream.readInt<unsigned int>();
4841 ASSERT(mState.mBufferVariables.empty());
4842 for (unsigned int index = 0; index < bufferVariableCount; ++index)
4843 {
4844 BufferVariable bufferVariable;
4845 LoadBufferVariable(&stream, &bufferVariable);
4846 mState.mBufferVariables.push_back(bufferVariable);
4847 }
4848
4849 unsigned int shaderStorageBlockCount = stream.readInt<unsigned int>();
4850 ASSERT(mState.mShaderStorageBlocks.empty());
4851 for (unsigned int shaderStorageBlockIndex = 0;
4852 shaderStorageBlockIndex < shaderStorageBlockCount; ++shaderStorageBlockIndex)
4853 {
4854 InterfaceBlock shaderStorageBlock;
4855 LoadInterfaceBlock(&stream, &shaderStorageBlock);
4856 mState.mShaderStorageBlocks.push_back(shaderStorageBlock);
4857 }
4858
4859 unsigned int atomicCounterBufferCount = stream.readInt<unsigned int>();
4860 ASSERT(mState.mAtomicCounterBuffers.empty());
4861 for (unsigned int bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
4862 {
4863 AtomicCounterBuffer atomicCounterBuffer;
4864 LoadShaderVariableBuffer(&stream, &atomicCounterBuffer);
4865
4866 mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer);
4867 }
4868
4869 unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
4870
4871 // Reject programs that use transform feedback varyings if the hardware cannot support them.
4872 if (transformFeedbackVaryingCount > 0 &&
4873 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4874 {
4875 infoLog << "Current driver does not support transform feedback in binary programs.";
4876 return angle::Result::Incomplete;
4877 }
4878
4879 ASSERT(mState.mLinkedTransformFeedbackVaryings.empty());
4880 for (unsigned int transformFeedbackVaryingIndex = 0;
4881 transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
4882 ++transformFeedbackVaryingIndex)
4883 {
4884 sh::Varying varying;
4885 stream.readIntVector<unsigned int>(&varying.arraySizes);
4886 stream.readInt(&varying.type);
4887 stream.readString(&varying.name);
4888
4889 GLuint arrayIndex = stream.readInt<GLuint>();
4890
4891 mState.mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
4892 }
4893
4894 stream.readInt(&mState.mTransformFeedbackBufferMode);
4895
4896 unsigned int outputCount = stream.readInt<unsigned int>();
4897 ASSERT(mState.mOutputVariables.empty());
4898 for (unsigned int outputIndex = 0; outputIndex < outputCount; ++outputIndex)
4899 {
4900 sh::OutputVariable output;
4901 LoadShaderVar(&stream, &output);
4902 output.location = stream.readInt<int>();
4903 output.index = stream.readInt<int>();
4904 mState.mOutputVariables.push_back(output);
4905 }
4906
4907 unsigned int outputVarCount = stream.readInt<unsigned int>();
4908 ASSERT(mState.mOutputLocations.empty());
4909 for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
4910 {
4911 VariableLocation locationData;
4912 stream.readInt(&locationData.arrayIndex);
4913 stream.readInt(&locationData.index);
4914 stream.readBool(&locationData.ignored);
4915 mState.mOutputLocations.push_back(locationData);
4916 }
4917
4918 unsigned int secondaryOutputVarCount = stream.readInt<unsigned int>();
4919 ASSERT(mState.mSecondaryOutputLocations.empty());
4920 for (unsigned int outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex)
4921 {
4922 VariableLocation locationData;
4923 stream.readInt(&locationData.arrayIndex);
4924 stream.readInt(&locationData.index);
4925 stream.readBool(&locationData.ignored);
4926 mState.mSecondaryOutputLocations.push_back(locationData);
4927 }
4928
4929 unsigned int outputTypeCount = stream.readInt<unsigned int>();
4930 for (unsigned int outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
4931 {
4932 mState.mOutputVariableTypes.push_back(stream.readInt<GLenum>());
4933 }
4934
4935 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4936 "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
4937 "into 32 bits each");
4938 mState.mDrawBufferTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4939 mState.mActiveOutputVariables = stream.readInt<gl::DrawBufferMask>();
4940
4941 unsigned int samplerRangeLow = stream.readInt<unsigned int>();
4942 unsigned int samplerRangeHigh = stream.readInt<unsigned int>();
4943 mState.mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh);
4944 unsigned int samplerCount = stream.readInt<unsigned int>();
4945 for (unsigned int samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
4946 {
4947 TextureType textureType = stream.readEnum<TextureType>();
4948 SamplerFormat format = stream.readEnum<SamplerFormat>();
4949 size_t bindingCount = stream.readInt<size_t>();
4950 bool unreferenced = stream.readBool();
4951 mState.mSamplerBindings.emplace_back(textureType, format, bindingCount, unreferenced);
4952 }
4953
4954 unsigned int imageRangeLow = stream.readInt<unsigned int>();
4955 unsigned int imageRangeHigh = stream.readInt<unsigned int>();
4956 mState.mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh);
4957 unsigned int imageBindingCount = stream.readInt<unsigned int>();
4958 for (unsigned int imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
4959 {
4960 unsigned int elementCount = stream.readInt<unsigned int>();
4961 ImageBinding imageBinding(elementCount);
4962 for (unsigned int i = 0; i < elementCount; ++i)
4963 {
4964 imageBinding.boundImageUnits[i] = stream.readInt<unsigned int>();
4965 }
4966 mState.mImageBindings.emplace_back(imageBinding);
4967 }
4968
4969 unsigned int atomicCounterRangeLow = stream.readInt<unsigned int>();
4970 unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
4971 mState.mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
4972
4973 static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
4974 "Too many shader types");
4975 mState.mLinkedShaderStages = ShaderBitSet(stream.readInt<uint8_t>());
4976
4977 if (!mState.mAttachedShaders[ShaderType::Compute])
4978 {
4979 mState.updateTransformFeedbackStrides();
4980 }
4981
4982 postResolveLink(context);
4983
4984 return angle::Result::Continue;
4985 }
4986
postResolveLink(const gl::Context * context)4987 void Program::postResolveLink(const gl::Context *context)
4988 {
4989 mState.updateActiveSamplers();
4990 mState.updateActiveImages();
4991
4992 if (context->getExtensions().multiDraw)
4993 {
4994 mState.mDrawIDLocation = getUniformLocation("gl_DrawID");
4995 }
4996
4997 if (context->getExtensions().baseVertexBaseInstance)
4998 {
4999 mState.mBaseVertexLocation = getUniformLocation("gl_BaseVertex");
5000 mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance");
5001 }
5002 }
5003
5004 } // namespace gl
5005