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/angle_version_info.h"
16 #include "common/bitset_utils.h"
17 #include "common/debug.h"
18 #include "common/platform.h"
19 #include "common/string_utils.h"
20 #include "common/utilities.h"
21 #include "compiler/translator/blocklayout.h"
22 #include "libANGLE/Context.h"
23 #include "libANGLE/ErrorStrings.h"
24 #include "libANGLE/MemoryProgramCache.h"
25 #include "libANGLE/ProgramLinkedResources.h"
26 #include "libANGLE/ResourceManager.h"
27 #include "libANGLE/Uniform.h"
28 #include "libANGLE/VaryingPacking.h"
29 #include "libANGLE/Version.h"
30 #include "libANGLE/capture/FrameCapture.h"
31 #include "libANGLE/features.h"
32 #include "libANGLE/histogram_macros.h"
33 #include "libANGLE/queryconversions.h"
34 #include "libANGLE/renderer/GLImplFactory.h"
35 #include "libANGLE/renderer/ProgramImpl.h"
36 #include "platform/FrontendFeatures.h"
37 #include "platform/PlatformMethods.h"
38
39 namespace gl
40 {
41
42 namespace
43 {
44
45 // This simplified cast function doesn't need to worry about advanced concepts like
46 // depth range values, or casting to bool.
47 template <typename DestT, typename SrcT>
48 DestT UniformStateQueryCast(SrcT value);
49
50 // From-Float-To-Integer Casts
51 template <>
UniformStateQueryCast(GLfloat value)52 GLint UniformStateQueryCast(GLfloat value)
53 {
54 return clampCast<GLint>(roundf(value));
55 }
56
57 template <>
UniformStateQueryCast(GLfloat value)58 GLuint UniformStateQueryCast(GLfloat value)
59 {
60 return clampCast<GLuint>(roundf(value));
61 }
62
63 // From-Integer-to-Integer Casts
64 template <>
UniformStateQueryCast(GLuint value)65 GLint UniformStateQueryCast(GLuint value)
66 {
67 return clampCast<GLint>(value);
68 }
69
70 template <>
UniformStateQueryCast(GLint value)71 GLuint UniformStateQueryCast(GLint value)
72 {
73 return clampCast<GLuint>(value);
74 }
75
76 // From-Boolean-to-Anything Casts
77 template <>
UniformStateQueryCast(GLboolean value)78 GLfloat UniformStateQueryCast(GLboolean value)
79 {
80 return (ConvertToBool(value) ? 1.0f : 0.0f);
81 }
82
83 template <>
UniformStateQueryCast(GLboolean value)84 GLint UniformStateQueryCast(GLboolean value)
85 {
86 return (ConvertToBool(value) ? 1 : 0);
87 }
88
89 template <>
UniformStateQueryCast(GLboolean value)90 GLuint UniformStateQueryCast(GLboolean value)
91 {
92 return (ConvertToBool(value) ? 1u : 0u);
93 }
94
95 // Default to static_cast
96 template <typename DestT, typename SrcT>
UniformStateQueryCast(SrcT value)97 DestT UniformStateQueryCast(SrcT value)
98 {
99 return static_cast<DestT>(value);
100 }
101
102 template <typename SrcT, typename DestT>
UniformStateQueryCastLoop(DestT * dataOut,const uint8_t * srcPointer,int components)103 void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
104 {
105 for (int comp = 0; comp < components; ++comp)
106 {
107 // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
108 // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
109 size_t offset = comp * 4;
110 const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
111 dataOut[comp] = UniformStateQueryCast<DestT>(*typedSrcPointer);
112 }
113 }
114
115 template <typename VarT>
GetResourceIndexFromName(const std::vector<VarT> & list,const std::string & name)116 GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
117 {
118 std::string nameAsArrayName = name + "[0]";
119 for (size_t index = 0; index < list.size(); index++)
120 {
121 const VarT &resource = list[index];
122 if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
123 {
124 return static_cast<GLuint>(index);
125 }
126 }
127
128 return GL_INVALID_INDEX;
129 }
130
GetVariableLocation(const std::vector<sh::ShaderVariable> & list,const std::vector<VariableLocation> & locationList,const std::string & name)131 GLint GetVariableLocation(const std::vector<sh::ShaderVariable> &list,
132 const std::vector<VariableLocation> &locationList,
133 const std::string &name)
134 {
135 size_t nameLengthWithoutArrayIndex;
136 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
137
138 for (size_t location = 0u; location < locationList.size(); ++location)
139 {
140 const VariableLocation &variableLocation = locationList[location];
141 if (!variableLocation.used())
142 {
143 continue;
144 }
145
146 const sh::ShaderVariable &variable = list[variableLocation.index];
147
148 // Array output variables may be bound out of order, so we need to ensure we only pick the
149 // first element if given the base name.
150 if ((variable.name == name) && (variableLocation.arrayIndex == 0))
151 {
152 return static_cast<GLint>(location);
153 }
154 if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
155 angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
156 {
157 return static_cast<GLint>(location);
158 }
159 }
160
161 return -1;
162 }
163
GetVariableLocation(const std::vector<LinkedUniform> & list,const std::vector<VariableLocation> & locationList,const std::string & name)164 GLint GetVariableLocation(const std::vector<LinkedUniform> &list,
165 const std::vector<VariableLocation> &locationList,
166 const std::string &name)
167 {
168 size_t nameLengthWithoutArrayIndex;
169 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
170
171 for (size_t location = 0u; location < locationList.size(); ++location)
172 {
173 const VariableLocation &variableLocation = locationList[location];
174 if (!variableLocation.used())
175 {
176 continue;
177 }
178
179 const LinkedUniform &variable = list[variableLocation.index];
180
181 // Array output variables may be bound out of order, so we need to ensure we only pick the
182 // first element if given the base name. Uniforms don't allow this behavior and some code
183 // seemingly depends on the opposite behavior, so only enable it for output variables.
184 if (angle::BeginsWith(variable.name, name) && (variableLocation.arrayIndex == 0))
185 {
186 if (name.length() == variable.name.length())
187 {
188 ASSERT(name == variable.name);
189 // GLES 3.1 November 2016 page 87.
190 // The string exactly matches the name of the active variable.
191 return static_cast<GLint>(location);
192 }
193 if (name.length() + 3u == variable.name.length() && variable.isArray())
194 {
195 ASSERT(name + "[0]" == variable.name);
196 // The string identifies the base name of an active array, where the string would
197 // exactly match the name of the variable if the suffix "[0]" were appended to the
198 // string.
199 return static_cast<GLint>(location);
200 }
201 }
202 if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
203 nameLengthWithoutArrayIndex + 3u == variable.name.length() &&
204 angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
205 {
206 ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name);
207 // The string identifies an active element of the array, where the string ends with the
208 // concatenation of the "[" character, an integer (with no "+" sign, extra leading
209 // zeroes, or whitespace) identifying an array element, and the "]" character, the
210 // integer is less than the number of active elements of the array variable, and where
211 // the string would exactly match the enumerated name of the array if the decimal
212 // integer were replaced with zero.
213 return static_cast<GLint>(location);
214 }
215 }
216
217 return -1;
218 }
219
CopyStringToBuffer(GLchar * buffer,const std::string & string,GLsizei bufSize,GLsizei * lengthOut)220 void CopyStringToBuffer(GLchar *buffer,
221 const std::string &string,
222 GLsizei bufSize,
223 GLsizei *lengthOut)
224 {
225 ASSERT(bufSize > 0);
226 size_t length = std::min<size_t>(bufSize - 1, string.length());
227 memcpy(buffer, string.c_str(), length);
228 buffer[length] = '\0';
229
230 if (lengthOut)
231 {
232 *lengthOut = static_cast<GLsizei>(length);
233 }
234 }
235
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)236 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
237 {
238 std::vector<unsigned int> subscripts;
239 std::string baseName = ParseResourceName(name, &subscripts);
240
241 unsigned int numBlocks = static_cast<unsigned int>(list.size());
242 for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
243 {
244 const auto &block = list[blockIndex];
245 if (block.name == baseName)
246 {
247 const bool arrayElementZero =
248 (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
249 const bool arrayElementMatches =
250 (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
251 if (arrayElementMatches || arrayElementZero)
252 {
253 return blockIndex;
254 }
255 }
256 }
257
258 return GL_INVALID_INDEX;
259 }
260
GetInterfaceBlockName(const UniformBlockIndex index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)261 void GetInterfaceBlockName(const UniformBlockIndex index,
262 const std::vector<InterfaceBlock> &list,
263 GLsizei bufSize,
264 GLsizei *length,
265 GLchar *name)
266 {
267 ASSERT(index.value < list.size());
268
269 const auto &block = list[index.value];
270
271 if (bufSize > 0)
272 {
273 std::string blockName = block.name;
274
275 if (block.isArray)
276 {
277 blockName += ArrayString(block.arrayElement);
278 }
279 CopyStringToBuffer(name, blockName, bufSize, length);
280 }
281 }
282
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)283 void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
284 {
285 for (ShaderType shaderType : AllShaderTypes())
286 {
287 Shader *shader = state.getAttachedShader(shaderType);
288 if (shader)
289 {
290 blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks());
291 }
292 }
293 }
294
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)295 void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
296 {
297 for (ShaderType shaderType : AllShaderTypes())
298 {
299 Shader *shader = state.getAttachedShader(shaderType);
300 if (shader != nullptr)
301 {
302 blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks());
303 }
304 }
305 }
306 } // anonymous namespace
307
GetLinkMismatchErrorString(LinkMismatchError linkError)308 const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
309 {
310 switch (linkError)
311 {
312 case LinkMismatchError::TYPE_MISMATCH:
313 return "Type";
314 case LinkMismatchError::ARRAYNESS_MISMATCH:
315 return "Array-ness";
316 case LinkMismatchError::ARRAY_SIZE_MISMATCH:
317 return "Array size";
318 case LinkMismatchError::PRECISION_MISMATCH:
319 return "Precision";
320 case LinkMismatchError::STRUCT_NAME_MISMATCH:
321 return "Structure name";
322 case LinkMismatchError::FIELD_NUMBER_MISMATCH:
323 return "Field number";
324 case LinkMismatchError::FIELD_NAME_MISMATCH:
325 return "Field name";
326
327 case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
328 return "Interpolation type";
329 case LinkMismatchError::INVARIANCE_MISMATCH:
330 return "Invariance";
331
332 case LinkMismatchError::BINDING_MISMATCH:
333 return "Binding layout qualifier";
334 case LinkMismatchError::LOCATION_MISMATCH:
335 return "Location layout qualifier";
336 case LinkMismatchError::OFFSET_MISMATCH:
337 return "Offset layout qualifier";
338 case LinkMismatchError::INSTANCE_NAME_MISMATCH:
339 return "Instance name qualifier";
340 case LinkMismatchError::FORMAT_MISMATCH:
341 return "Format qualifier";
342
343 case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
344 return "Layout qualifier";
345 case LinkMismatchError::MATRIX_PACKING_MISMATCH:
346 return "Matrix Packing";
347
348 case LinkMismatchError::FIELD_LOCATION_MISMATCH:
349 return "Field location";
350 case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
351 return "Field structure name";
352 default:
353 UNREACHABLE();
354 return "";
355 }
356 }
357
UpdateInterfaceVariable(std::vector<sh::ShaderVariable> * block,const sh::ShaderVariable & var)358 void UpdateInterfaceVariable(std::vector<sh::ShaderVariable> *block, const sh::ShaderVariable &var)
359 {
360 if (!var.isStruct())
361 {
362 block->emplace_back(var);
363 block->back().resetEffectiveLocation();
364 }
365
366 for (const sh::ShaderVariable &field : var.fields)
367 {
368 ASSERT(!var.name.empty() || var.isShaderIOBlock);
369
370 // Shader I/O block naming is similar to UBOs and SSBOs:
371 //
372 // in Block
373 // {
374 // type field; // produces "field"
375 // };
376 //
377 // in Block2
378 // {
379 // type field; // produces "Block2.field"
380 // } block2;
381 //
382 const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
383 const std::string prefix = var.name.empty() ? "" : baseName + ".";
384
385 if (!field.isStruct())
386 {
387 sh::ShaderVariable fieldCopy = field;
388 fieldCopy.updateEffectiveLocation(var);
389 fieldCopy.name = prefix + field.name;
390 block->emplace_back(fieldCopy);
391 }
392
393 for (const sh::ShaderVariable &nested : field.fields)
394 {
395 sh::ShaderVariable nestedCopy = nested;
396 nestedCopy.updateEffectiveLocation(field);
397 nestedCopy.name = prefix + field.name + "." + nested.name;
398 block->emplace_back(nestedCopy);
399 }
400 }
401 }
402
WriteShaderVariableBuffer(BinaryOutputStream * stream,const ShaderVariableBuffer & var)403 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
404 {
405 stream->writeInt(var.binding);
406 stream->writeInt(var.dataSize);
407
408 for (ShaderType shaderType : AllShaderTypes())
409 {
410 stream->writeBool(var.isActive(shaderType));
411 }
412
413 stream->writeInt(var.memberIndexes.size());
414 for (unsigned int memberCounterIndex : var.memberIndexes)
415 {
416 stream->writeInt(memberCounterIndex);
417 }
418 }
419
LoadShaderVariableBuffer(BinaryInputStream * stream,ShaderVariableBuffer * var)420 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
421 {
422 var->binding = stream->readInt<int>();
423 var->dataSize = stream->readInt<unsigned int>();
424
425 for (ShaderType shaderType : AllShaderTypes())
426 {
427 var->setActive(shaderType, stream->readBool());
428 }
429
430 size_t numMembers = stream->readInt<size_t>();
431 for (size_t blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
432 {
433 var->memberIndexes.push_back(stream->readInt<unsigned int>());
434 }
435 }
436
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)437 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
438 {
439 WriteShaderVar(stream, var);
440
441 stream->writeInt(var.bufferIndex);
442 WriteBlockMemberInfo(stream, var.blockInfo);
443 stream->writeInt(var.topLevelArraySize);
444
445 for (ShaderType shaderType : AllShaderTypes())
446 {
447 stream->writeBool(var.isActive(shaderType));
448 }
449 }
450
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)451 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
452 {
453 LoadShaderVar(stream, var);
454
455 var->bufferIndex = stream->readInt<int>();
456 LoadBlockMemberInfo(stream, &var->blockInfo);
457 var->topLevelArraySize = stream->readInt<int>();
458
459 for (ShaderType shaderType : AllShaderTypes())
460 {
461 var->setActive(shaderType, stream->readBool());
462 }
463 }
464
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)465 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
466 {
467 stream->writeString(block.name);
468 stream->writeString(block.mappedName);
469 stream->writeBool(block.isArray);
470 stream->writeInt(block.arrayElement);
471
472 WriteShaderVariableBuffer(stream, block);
473 }
474
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)475 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
476 {
477 block->name = stream->readString();
478 block->mappedName = stream->readString();
479 block->isArray = stream->readBool();
480 block->arrayElement = stream->readInt<unsigned int>();
481
482 LoadShaderVariableBuffer(stream, block);
483 }
484
WriteShInterfaceBlock(BinaryOutputStream * stream,const sh::InterfaceBlock & block)485 void WriteShInterfaceBlock(BinaryOutputStream *stream, const sh::InterfaceBlock &block)
486 {
487 stream->writeString(block.name);
488 stream->writeString(block.mappedName);
489 stream->writeString(block.instanceName);
490 stream->writeInt(block.arraySize);
491 stream->writeEnum(block.layout);
492 stream->writeBool(block.isRowMajorLayout);
493 stream->writeInt(block.binding);
494 stream->writeBool(block.staticUse);
495 stream->writeBool(block.active);
496 stream->writeEnum(block.blockType);
497
498 stream->writeInt<size_t>(block.fields.size());
499 for (const sh::ShaderVariable &shaderVariable : block.fields)
500 {
501 WriteShaderVar(stream, shaderVariable);
502 }
503 }
504
LoadShInterfaceBlock(BinaryInputStream * stream,sh::InterfaceBlock * block)505 void LoadShInterfaceBlock(BinaryInputStream *stream, sh::InterfaceBlock *block)
506 {
507 block->name = stream->readString();
508 block->mappedName = stream->readString();
509 block->instanceName = stream->readString();
510 block->arraySize = stream->readInt<unsigned int>();
511 block->layout = stream->readEnum<sh::BlockLayoutType>();
512 block->isRowMajorLayout = stream->readBool();
513 block->binding = stream->readInt<int>();
514 block->staticUse = stream->readBool();
515 block->active = stream->readBool();
516 block->blockType = stream->readEnum<sh::BlockType>();
517
518 block->fields.resize(stream->readInt<size_t>());
519 for (sh::ShaderVariable &variable : block->fields)
520 {
521 LoadShaderVar(stream, &variable);
522 }
523 }
524
525 // Saves the linking context for later use in resolveLink().
526 struct Program::LinkingState
527 {
528 std::shared_ptr<ProgramExecutable> linkedExecutable;
529 ProgramLinkedResources resources;
530 egl::BlobCache::Key programHash;
531 std::unique_ptr<rx::LinkEvent> linkEvent;
532 bool linkingFromBinary;
533 };
534
535 const char *const g_fakepath = "C:\\fakepath";
536
537 // InfoLog implementation.
InfoLog()538 InfoLog::InfoLog() : mLazyStream(nullptr) {}
539
~InfoLog()540 InfoLog::~InfoLog() {}
541
getLength() const542 size_t InfoLog::getLength() const
543 {
544 if (!mLazyStream)
545 {
546 return 0;
547 }
548
549 const std::string &logString = mLazyStream->str();
550 return logString.empty() ? 0 : logString.length() + 1;
551 }
552
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const553 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
554 {
555 size_t index = 0;
556
557 if (bufSize > 0)
558 {
559 const std::string logString(str());
560
561 if (!logString.empty())
562 {
563 index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
564 memcpy(infoLog, logString.c_str(), index);
565 }
566
567 infoLog[index] = '\0';
568 }
569
570 if (length)
571 {
572 *length = static_cast<GLsizei>(index);
573 }
574 }
575
576 // append a santized message to the program info log.
577 // The D3D compiler includes a fake file path in some of the warning or error
578 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)579 void InfoLog::appendSanitized(const char *message)
580 {
581 ensureInitialized();
582
583 std::string msg(message);
584
585 size_t found;
586 do
587 {
588 found = msg.find(g_fakepath);
589 if (found != std::string::npos)
590 {
591 msg.erase(found, strlen(g_fakepath));
592 }
593 } while (found != std::string::npos);
594
595 if (!msg.empty())
596 {
597 *mLazyStream << message << std::endl;
598 }
599 }
600
reset()601 void InfoLog::reset()
602 {
603 if (mLazyStream)
604 {
605 mLazyStream.reset(nullptr);
606 }
607 }
608
empty() const609 bool InfoLog::empty() const
610 {
611 if (!mLazyStream)
612 {
613 return true;
614 }
615
616 return mLazyStream->rdbuf()->in_avail() == 0;
617 }
618
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)619 void LogLinkMismatch(InfoLog &infoLog,
620 const std::string &variableName,
621 const char *variableType,
622 LinkMismatchError linkError,
623 const std::string &mismatchedStructOrBlockFieldName,
624 ShaderType shaderType1,
625 ShaderType shaderType2)
626 {
627 std::ostringstream stream;
628 stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
629 << variableName;
630
631 if (!mismatchedStructOrBlockFieldName.empty())
632 {
633 stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
634 }
635
636 stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
637 << GetShaderTypeString(shaderType2) << " shaders.";
638
639 infoLog << stream.str();
640 }
641
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)642 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
643 {
644 // Only 'packed' blocks are allowed to be considered inactive.
645 return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
646 }
647
WriteBlockMemberInfo(BinaryOutputStream * stream,const sh::BlockMemberInfo & var)648 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var)
649 {
650 stream->writeInt(var.arrayStride);
651 stream->writeBool(var.isRowMajorMatrix);
652 stream->writeInt(var.matrixStride);
653 stream->writeInt(var.offset);
654 stream->writeInt(var.topLevelArrayStride);
655 }
656
LoadBlockMemberInfo(BinaryInputStream * stream,sh::BlockMemberInfo * var)657 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
658 {
659 var->arrayStride = stream->readInt<int>();
660 var->isRowMajorMatrix = stream->readBool();
661 var->matrixStride = stream->readInt<int>();
662 var->offset = stream->readInt<int>();
663 var->topLevelArrayStride = stream->readInt<int>();
664 }
665
WriteShaderVar(BinaryOutputStream * stream,const sh::ShaderVariable & var)666 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
667 {
668 stream->writeInt(var.type);
669 stream->writeInt(var.precision);
670 stream->writeString(var.name);
671 stream->writeString(var.mappedName);
672 stream->writeIntVector(var.arraySizes);
673 stream->writeBool(var.staticUse);
674 stream->writeBool(var.active);
675 stream->writeInt<size_t>(var.fields.size());
676 for (const sh::ShaderVariable &shaderVariable : var.fields)
677 {
678 WriteShaderVar(stream, shaderVariable);
679 }
680 stream->writeString(var.structOrBlockName);
681 stream->writeString(var.mappedStructOrBlockName);
682 stream->writeBool(var.isRowMajorLayout);
683 stream->writeInt(var.location);
684 stream->writeBool(var.hasImplicitLocation);
685 stream->writeInt(var.binding);
686 stream->writeInt(var.imageUnitFormat);
687 stream->writeInt(var.offset);
688 stream->writeBool(var.readonly);
689 stream->writeBool(var.writeonly);
690 stream->writeBool(var.isFragmentInOut);
691 stream->writeInt(var.index);
692 stream->writeBool(var.yuv);
693 stream->writeEnum(var.interpolation);
694 stream->writeBool(var.isInvariant);
695 stream->writeBool(var.isShaderIOBlock);
696 stream->writeBool(var.isPatch);
697 stream->writeBool(var.texelFetchStaticUse);
698 stream->writeInt(var.getFlattenedOffsetInParentArrays());
699 }
700
LoadShaderVar(gl::BinaryInputStream * stream,sh::ShaderVariable * var)701 void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
702 {
703 var->type = stream->readInt<GLenum>();
704 var->precision = stream->readInt<GLenum>();
705 stream->readString(&var->name);
706 stream->readString(&var->mappedName);
707 stream->readIntVector<unsigned int>(&var->arraySizes);
708 var->staticUse = stream->readBool();
709 var->active = stream->readBool();
710 size_t elementCount = stream->readInt<size_t>();
711 var->fields.resize(elementCount);
712 for (sh::ShaderVariable &variable : var->fields)
713 {
714 LoadShaderVar(stream, &variable);
715 }
716 stream->readString(&var->structOrBlockName);
717 stream->readString(&var->mappedStructOrBlockName);
718 var->isRowMajorLayout = stream->readBool();
719 var->location = stream->readInt<int>();
720 var->hasImplicitLocation = stream->readBool();
721 var->binding = stream->readInt<int>();
722 var->imageUnitFormat = stream->readInt<GLenum>();
723 var->offset = stream->readInt<int>();
724 var->readonly = stream->readBool();
725 var->writeonly = stream->readBool();
726 var->isFragmentInOut = stream->readBool();
727 var->index = stream->readInt<int>();
728 var->yuv = stream->readBool();
729 var->interpolation = stream->readEnum<sh::InterpolationType>();
730 var->isInvariant = stream->readBool();
731 var->isShaderIOBlock = stream->readBool();
732 var->isPatch = stream->readBool();
733 var->texelFetchStaticUse = stream->readBool();
734 var->setParentArrayIndex(stream->readInt<int>());
735 }
736
737 // VariableLocation implementation.
VariableLocation()738 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
739
VariableLocation(unsigned int arrayIndex,unsigned int index)740 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
741 : arrayIndex(arrayIndex), index(index), ignored(false)
742 {
743 ASSERT(arrayIndex != GL_INVALID_INDEX);
744 }
745
746 // SamplerBindings implementation.
SamplerBinding(TextureType textureTypeIn,GLenum samplerTypeIn,SamplerFormat formatIn,size_t elementCount)747 SamplerBinding::SamplerBinding(TextureType textureTypeIn,
748 GLenum samplerTypeIn,
749 SamplerFormat formatIn,
750 size_t elementCount)
751 : textureType(textureTypeIn),
752 samplerType(samplerTypeIn),
753 format(formatIn),
754 boundTextureUnits(elementCount, 0)
755 {}
756
757 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
758
759 SamplerBinding::~SamplerBinding() = default;
760
761 // ProgramBindings implementation.
ProgramBindings()762 ProgramBindings::ProgramBindings() {}
763
~ProgramBindings()764 ProgramBindings::~ProgramBindings() {}
765
bindLocation(GLuint index,const std::string & name)766 void ProgramBindings::bindLocation(GLuint index, const std::string &name)
767 {
768 mBindings[name] = index;
769 }
770
getBindingByName(const std::string & name) const771 int ProgramBindings::getBindingByName(const std::string &name) const
772 {
773 auto iter = mBindings.find(name);
774 return (iter != mBindings.end()) ? iter->second : -1;
775 }
776
getBinding(const sh::ShaderVariable & variable) const777 int ProgramBindings::getBinding(const sh::ShaderVariable &variable) const
778 {
779 return getBindingByName(variable.name);
780 }
781
begin() const782 ProgramBindings::const_iterator ProgramBindings::begin() const
783 {
784 return mBindings.begin();
785 }
786
end() const787 ProgramBindings::const_iterator ProgramBindings::end() const
788 {
789 return mBindings.end();
790 }
791
getStableIterationMap() const792 std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
793 {
794 return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
795 }
796
797 // ProgramAliasedBindings implementation.
ProgramAliasedBindings()798 ProgramAliasedBindings::ProgramAliasedBindings() {}
799
~ProgramAliasedBindings()800 ProgramAliasedBindings::~ProgramAliasedBindings() {}
801
bindLocation(GLuint index,const std::string & name)802 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
803 {
804 mBindings[name] = ProgramBinding(index);
805
806 // EXT_blend_func_extended spec: "If it specifies the base name of an array,
807 // it identifies the resources associated with the first element of the array."
808 //
809 // Normalize array bindings so that "name" and "name[0]" map to the same entry.
810 // If this binding is of the form "name[0]", then mark the "name" binding as
811 // aliased but do not update it yet in case "name" is not actually an array.
812 size_t nameLengthWithoutArrayIndex;
813 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
814 if (arrayIndex == 0)
815 {
816 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
817 auto iter = mBindings.find(baseName);
818 if (iter != mBindings.end())
819 {
820 iter->second.aliased = true;
821 }
822 }
823 }
824
getBindingByName(const std::string & name) const825 int ProgramAliasedBindings::getBindingByName(const std::string &name) const
826 {
827 auto iter = mBindings.find(name);
828 return (iter != mBindings.end()) ? iter->second.location : -1;
829 }
830
getBindingByLocation(GLuint location) const831 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
832 {
833 for (const auto &iter : mBindings)
834 {
835 if (iter.second.location == location)
836 {
837 return iter.second.location;
838 }
839 }
840 return -1;
841 }
842
getBinding(const sh::ShaderVariable & variable) const843 int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const
844 {
845 const std::string &name = variable.name;
846
847 // Check with the normalized array name if applicable.
848 if (variable.isArray())
849 {
850 size_t nameLengthWithoutArrayIndex;
851 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
852 if (arrayIndex == 0)
853 {
854 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
855 auto iter = mBindings.find(baseName);
856 // If "name" exists and is not aliased, that means it was modified more
857 // recently than its "name[0]" form and should be used instead of that.
858 if (iter != mBindings.end() && !iter->second.aliased)
859 {
860 return iter->second.location;
861 }
862 }
863 else if (arrayIndex == GL_INVALID_INDEX)
864 {
865 auto iter = mBindings.find(variable.name);
866 // If "name" exists and is not aliased, that means it was modified more
867 // recently than its "name[0]" form and should be used instead of that.
868 if (iter != mBindings.end() && !iter->second.aliased)
869 {
870 return iter->second.location;
871 }
872 // The base name was aliased, so use the name with the array notation.
873 return getBindingByName(name + "[0]");
874 }
875 }
876
877 return getBindingByName(name);
878 }
879
begin() const880 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
881 {
882 return mBindings.begin();
883 }
884
end() const885 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
886 {
887 return mBindings.end();
888 }
889
getStableIterationMap() const890 std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
891 {
892 return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
893 }
894
895 // ImageBinding implementation.
ImageBinding(size_t count,TextureType textureTypeIn)896 ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn)
897 : textureType(textureTypeIn), boundImageUnits(count, 0)
898 {}
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)899 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
900 : textureType(textureTypeIn)
901 {
902 for (size_t index = 0; index < count; ++index)
903 {
904 boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
905 }
906 }
907
908 ImageBinding::ImageBinding(const ImageBinding &other) = default;
909
910 ImageBinding::~ImageBinding() = default;
911
912 // ProgramState implementation.
ProgramState()913 ProgramState::ProgramState()
914 : mLabel(),
915 mAttachedShaders{},
916 mLocationsUsedForXfbExtension(0),
917 mBinaryRetrieveableHint(false),
918 mSeparable(false),
919 mNumViews(-1),
920 mDrawIDLocation(-1),
921 mBaseVertexLocation(-1),
922 mBaseInstanceLocation(-1),
923 mCachedBaseVertex(0),
924 mCachedBaseInstance(0),
925 mExecutable(new ProgramExecutable())
926 {
927 mComputeShaderLocalSize.fill(1);
928 }
929
~ProgramState()930 ProgramState::~ProgramState()
931 {
932 ASSERT(!hasAttachedShader());
933 }
934
getLabel()935 const std::string &ProgramState::getLabel()
936 {
937 return mLabel;
938 }
939
getAttachedShader(ShaderType shaderType) const940 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
941 {
942 ASSERT(shaderType != ShaderType::InvalidEnum);
943 return mAttachedShaders[shaderType];
944 }
945
getUniformIndexFromName(const std::string & name) const946 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
947 {
948 return GetResourceIndexFromName(mExecutable->mUniforms, name);
949 }
950
getBufferVariableIndexFromName(const std::string & name) const951 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
952 {
953 return GetResourceIndexFromName(mBufferVariables, name);
954 }
955
getUniformIndexFromLocation(UniformLocation location) const956 GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const
957 {
958 ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
959 return mUniformLocations[location.value].index;
960 }
961
getSamplerIndex(UniformLocation location) const962 Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
963 {
964 GLuint index = getUniformIndexFromLocation(location);
965 if (!isSamplerUniformIndex(index))
966 {
967 return Optional<GLuint>::Invalid();
968 }
969
970 return getSamplerIndexFromUniformIndex(index);
971 }
972
isSamplerUniformIndex(GLuint index) const973 bool ProgramState::isSamplerUniformIndex(GLuint index) const
974 {
975 return mExecutable->mSamplerUniformRange.contains(index);
976 }
977
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const978 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
979 {
980 ASSERT(isSamplerUniformIndex(uniformIndex));
981 return uniformIndex - mExecutable->mSamplerUniformRange.low();
982 }
983
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const984 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
985 {
986 return mExecutable->getUniformIndexFromSamplerIndex(samplerIndex);
987 }
988
isImageUniformIndex(GLuint index) const989 bool ProgramState::isImageUniformIndex(GLuint index) const
990 {
991 return mExecutable->mImageUniformRange.contains(index);
992 }
993
getImageIndexFromUniformIndex(GLuint uniformIndex) const994 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
995 {
996 ASSERT(isImageUniformIndex(uniformIndex));
997 return uniformIndex - mExecutable->mImageUniformRange.low();
998 }
999
getAttributeLocation(const std::string & name) const1000 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1001 {
1002 for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
1003 {
1004 if (attribute.name == name)
1005 {
1006 return attribute.location;
1007 }
1008 }
1009
1010 return static_cast<GLuint>(-1);
1011 }
1012
hasAttachedShader() const1013 bool ProgramState::hasAttachedShader() const
1014 {
1015 for (const Shader *shader : mAttachedShaders)
1016 {
1017 if (shader)
1018 {
1019 return true;
1020 }
1021 }
1022 return false;
1023 }
1024
getFirstAttachedShaderStageType() const1025 ShaderType ProgramState::getFirstAttachedShaderStageType() const
1026 {
1027 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1028 if (linkedStages.none())
1029 {
1030 return ShaderType::InvalidEnum;
1031 }
1032
1033 return linkedStages.first();
1034 }
1035
getLastAttachedShaderStageType() const1036 ShaderType ProgramState::getLastAttachedShaderStageType() const
1037 {
1038 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1039 if (linkedStages.none())
1040 {
1041 return ShaderType::InvalidEnum;
1042 }
1043
1044 return linkedStages.last();
1045 }
1046
getAttachedTransformFeedbackStage() const1047 ShaderType ProgramState::getAttachedTransformFeedbackStage() const
1048 {
1049 if (mAttachedShaders[ShaderType::Geometry])
1050 {
1051 return ShaderType::Geometry;
1052 }
1053 if (mAttachedShaders[ShaderType::TessEvaluation])
1054 {
1055 return ShaderType::TessEvaluation;
1056 }
1057 return ShaderType::Vertex;
1058 }
1059
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)1060 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
1061 : mSerial(factory->generateSerial()),
1062 mProgram(factory->createProgram(mState)),
1063 mValidated(false),
1064 mLinked(false),
1065 mDeleteStatus(false),
1066 mRefCount(0),
1067 mResourceManager(manager),
1068 mHandle(handle)
1069 {
1070 ASSERT(mProgram);
1071
1072 unlink();
1073 }
1074
~Program()1075 Program::~Program()
1076 {
1077 ASSERT(!mProgram);
1078 }
1079
onDestroy(const Context * context)1080 void Program::onDestroy(const Context *context)
1081 {
1082 resolveLink(context);
1083 for (ShaderType shaderType : AllShaderTypes())
1084 {
1085 if (mState.mAttachedShaders[shaderType])
1086 {
1087 mState.mAttachedShaders[shaderType]->release(context);
1088 mState.mAttachedShaders[shaderType] = nullptr;
1089 }
1090 }
1091
1092 mProgram->destroy(context);
1093
1094 ASSERT(!mState.hasAttachedShader());
1095 SafeDelete(mProgram);
1096
1097 delete this;
1098 }
id() const1099 ShaderProgramID Program::id() const
1100 {
1101 ASSERT(!mLinkingState);
1102 return mHandle;
1103 }
1104
setLabel(const Context * context,const std::string & label)1105 void Program::setLabel(const Context *context, const std::string &label)
1106 {
1107 ASSERT(!mLinkingState);
1108 mState.mLabel = label;
1109 }
1110
getLabel() const1111 const std::string &Program::getLabel() const
1112 {
1113 ASSERT(!mLinkingState);
1114 return mState.mLabel;
1115 }
1116
attachShader(Shader * shader)1117 void Program::attachShader(Shader *shader)
1118 {
1119 ShaderType shaderType = shader->getType();
1120 ASSERT(shaderType != ShaderType::InvalidEnum);
1121
1122 mState.mAttachedShaders[shaderType] = shader;
1123 mState.mAttachedShaders[shaderType]->addRef();
1124 }
1125
detachShader(const Context * context,Shader * shader)1126 void Program::detachShader(const Context *context, Shader *shader)
1127 {
1128 resolveLink(context);
1129 ShaderType shaderType = shader->getType();
1130 ASSERT(shaderType != ShaderType::InvalidEnum);
1131
1132 ASSERT(mState.mAttachedShaders[shaderType] == shader);
1133 shader->release(context);
1134 mState.mAttachedShaders[shaderType] = nullptr;
1135 }
1136
getAttachedShadersCount() const1137 int Program::getAttachedShadersCount() const
1138 {
1139 ASSERT(!mLinkingState);
1140 int numAttachedShaders = 0;
1141 for (const Shader *shader : mState.mAttachedShaders)
1142 {
1143 if (shader)
1144 {
1145 ++numAttachedShaders;
1146 }
1147 }
1148
1149 return numAttachedShaders;
1150 }
1151
getAttachedShader(ShaderType shaderType) const1152 Shader *Program::getAttachedShader(ShaderType shaderType) const
1153 {
1154 ASSERT(!mLinkingState);
1155 return mState.getAttachedShader(shaderType);
1156 }
1157
bindAttributeLocation(GLuint index,const char * name)1158 void Program::bindAttributeLocation(GLuint index, const char *name)
1159 {
1160 ASSERT(!mLinkingState);
1161 mAttributeBindings.bindLocation(index, name);
1162 }
1163
bindUniformLocation(UniformLocation location,const char * name)1164 void Program::bindUniformLocation(UniformLocation location, const char *name)
1165 {
1166 ASSERT(!mLinkingState);
1167 mState.mUniformLocationBindings.bindLocation(location.value, name);
1168 }
1169
bindFragmentOutputLocation(GLuint index,const char * name)1170 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1171 {
1172 mFragmentOutputLocations.bindLocation(index, name);
1173 }
1174
bindFragmentOutputIndex(GLuint index,const char * name)1175 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1176 {
1177 mFragmentOutputIndexes.bindLocation(index, name);
1178 }
1179
link(const Context * context)1180 angle::Result Program::link(const Context *context)
1181 {
1182 angle::Result result = linkImpl(context);
1183
1184 // Avoid having two ProgramExecutables if the link failed and the Program had successfully
1185 // linked previously.
1186 if (mLinkingState && mLinkingState->linkedExecutable)
1187 {
1188 mState.mExecutable = mLinkingState->linkedExecutable;
1189 }
1190
1191 return result;
1192 }
1193
1194 // The attached shaders are checked for linking errors by matching up their variables.
1195 // Uniform, input and output variables get collected.
1196 // The code gets compiled into binaries.
linkImpl(const Context * context)1197 angle::Result Program::linkImpl(const Context *context)
1198 {
1199 ASSERT(!mLinkingState);
1200 // Don't make any local variables pointing to anything within the ProgramExecutable, since
1201 // unlink() could make a new ProgramExecutable making any references/pointers invalid.
1202 auto *platform = ANGLEPlatformCurrent();
1203 double startTime = platform->currentTime(platform);
1204
1205 // Unlink the program, but do not clear the validation-related caching yet, since we can still
1206 // use the previously linked program if linking the shaders fails.
1207 mLinked = false;
1208
1209 mState.mExecutable->getInfoLog().reset();
1210
1211 // Validate we have properly attached shaders before checking the cache.
1212 if (!linkValidateShaders(mState.mExecutable->getInfoLog()))
1213 {
1214 return angle::Result::Continue;
1215 }
1216
1217 egl::BlobCache::Key programHash = {0};
1218 MemoryProgramCache *cache = context->getMemoryProgramCache();
1219
1220 // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1221 if (cache && !isSeparable())
1222 {
1223 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1224 angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1225 ANGLE_TRY(cacheResult);
1226
1227 // Check explicitly for Continue, Incomplete means a cache miss
1228 if (cacheResult == angle::Result::Continue)
1229 {
1230 // Succeeded in loading the binaries in the front-end, back end may still be loading
1231 // asynchronously
1232 double delta = platform->currentTime(platform) - startTime;
1233 int us = static_cast<int>(delta * 1000000.0);
1234 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1235 return angle::Result::Continue;
1236 }
1237 }
1238
1239 // Cache load failed, fall through to normal linking.
1240 unlink();
1241 InfoLog &infoLog = mState.mExecutable->getInfoLog();
1242
1243 // Re-link shaders after the unlink call.
1244 bool result = linkValidateShaders(infoLog);
1245 ASSERT(result);
1246
1247 std::unique_ptr<LinkingState> linkingState(new LinkingState());
1248 ProgramMergedVaryings mergedVaryings;
1249 LinkingVariables linkingVariables(mState);
1250 ProgramLinkedResources &resources = linkingState->resources;
1251
1252 resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1253 &mState.mExecutable->mShaderStorageBlocks, &mState.mBufferVariables,
1254 &mState.mExecutable->mAtomicCounterBuffers);
1255
1256 // TODO: Fix incomplete linking. http://anglebug.com/6358
1257 updateLinkedShaderStages();
1258
1259 InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1260 InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1261
1262 if (mState.mAttachedShaders[ShaderType::Compute])
1263 {
1264 GLuint combinedImageUniforms = 0;
1265 if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog))
1266 {
1267 return angle::Result::Continue;
1268 }
1269
1270 GLuint combinedShaderStorageBlocks = 0u;
1271 if (!LinkValidateProgramInterfaceBlocks(context,
1272 mState.mExecutable->getLinkedShaderStages(),
1273 resources, infoLog, &combinedShaderStorageBlocks))
1274 {
1275 return angle::Result::Continue;
1276 }
1277
1278 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1279 // A link error will be generated if the sum of the number of active image uniforms used in
1280 // all shaders, the number of active shader storage blocks, and the number of active
1281 // fragment shader outputs exceeds the implementation-dependent value of
1282 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1283 if (combinedImageUniforms + combinedShaderStorageBlocks >
1284 static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
1285 {
1286 infoLog
1287 << "The sum of the number of active image uniforms, active shader storage blocks "
1288 "and active fragment shader outputs exceeds "
1289 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1290 << context->getCaps().maxCombinedShaderOutputResources << ")";
1291 return angle::Result::Continue;
1292 }
1293 }
1294 else
1295 {
1296 if (!linkAttributes(context, infoLog))
1297 {
1298 return angle::Result::Continue;
1299 }
1300
1301 if (!linkVaryings(infoLog))
1302 {
1303 return angle::Result::Continue;
1304 }
1305
1306 GLuint combinedImageUniforms = 0;
1307 if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog))
1308 {
1309 return angle::Result::Continue;
1310 }
1311
1312 GLuint combinedShaderStorageBlocks = 0u;
1313 if (!LinkValidateProgramInterfaceBlocks(context,
1314 mState.mExecutable->getLinkedShaderStages(),
1315 resources, infoLog, &combinedShaderStorageBlocks))
1316 {
1317 return angle::Result::Continue;
1318 }
1319
1320 if (!LinkValidateProgramGlobalNames(infoLog, getExecutable(), linkingVariables))
1321 {
1322 return angle::Result::Continue;
1323 }
1324
1325 gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1326 if (vertexShader)
1327 {
1328 mState.mNumViews = vertexShader->getNumViews();
1329 mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
1330 }
1331
1332 gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1333 if (fragmentShader)
1334 {
1335 if (!mState.mExecutable->linkValidateOutputVariables(
1336 context->getCaps(), context->getExtensions(), context->getClientVersion(),
1337 combinedImageUniforms, combinedShaderStorageBlocks,
1338 fragmentShader->getActiveOutputVariables(), fragmentShader->getShaderVersion(),
1339 mFragmentOutputLocations, mFragmentOutputIndexes))
1340 {
1341 return angle::Result::Continue;
1342 }
1343
1344 mState.mExecutable->mUsesEarlyFragmentTestsOptimization =
1345 fragmentShader->hasEarlyFragmentTestsOptimization();
1346 mState.mExecutable->mAdvancedBlendEquations =
1347 fragmentShader->getAdvancedBlendEquations();
1348 mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
1349 }
1350
1351 mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
1352 if (!mState.mExecutable->linkMergedVaryings(
1353 context, mergedVaryings, mState.mTransformFeedbackVaryingNames, linkingVariables,
1354 isSeparable(), &resources.varyingPacking))
1355 {
1356 return angle::Result::Continue;
1357 }
1358 }
1359
1360 mState.mExecutable->saveLinkedStateInfo(mState);
1361
1362 mLinkingState = std::move(linkingState);
1363 mLinkingState->linkingFromBinary = false;
1364 mLinkingState->programHash = programHash;
1365 mLinkingState->linkEvent = mProgram->link(context, resources, infoLog, mergedVaryings);
1366
1367 // Must be after mProgram->link() to avoid misleading the linker about output variables.
1368 mState.updateProgramInterfaceInputs();
1369 mState.updateProgramInterfaceOutputs();
1370
1371 if (mState.mSeparable)
1372 {
1373 mLinkingState->linkedExecutable = mState.mExecutable;
1374 }
1375
1376 return angle::Result::Continue;
1377 }
1378
isLinking() const1379 bool Program::isLinking() const
1380 {
1381 return (mLinkingState.get() && mLinkingState->linkEvent &&
1382 mLinkingState->linkEvent->isLinking());
1383 }
1384
resolveLinkImpl(const Context * context)1385 void Program::resolveLinkImpl(const Context *context)
1386 {
1387 ASSERT(mLinkingState.get());
1388
1389 angle::Result result = mLinkingState->linkEvent->wait(context);
1390
1391 mLinked = result == angle::Result::Continue;
1392 std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1393 if (!mLinked)
1394 {
1395 return;
1396 }
1397
1398 if (linkingState->linkingFromBinary)
1399 {
1400 // All internal Program state is already loaded from the binary.
1401 return;
1402 }
1403
1404 initInterfaceBlockBindings();
1405
1406 // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1407 // Only successfully linked program can replace the executables.
1408 ASSERT(mLinked);
1409
1410 // Mark implementation-specific unreferenced uniforms as ignored.
1411 std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1412 mProgram->markUnusedUniformLocations(&mState.mUniformLocations,
1413 &mState.mExecutable->mSamplerBindings, imageBindings);
1414
1415 // Must be called after markUnusedUniformLocations.
1416 postResolveLink(context);
1417
1418 // Save to the program cache.
1419 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1420 MemoryProgramCache *cache = context->getMemoryProgramCache();
1421 // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1422 if (cache && !isSeparable() &&
1423 (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
1424 !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
1425 {
1426 if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
1427 {
1428 // Don't fail linking if putting the program binary into the cache fails, the program is
1429 // still usable.
1430 WARN() << "Failed to save linked program to memory program cache.";
1431 }
1432 }
1433 }
1434
updateLinkedShaderStages()1435 void Program::updateLinkedShaderStages()
1436 {
1437 mState.mExecutable->resetLinkedShaderStages();
1438
1439 for (const Shader *shader : mState.mAttachedShaders)
1440 {
1441 if (shader)
1442 {
1443 mState.mExecutable->setLinkedShaderStages(shader->getType());
1444 }
1445 }
1446 }
1447
updateActiveSamplers()1448 void ProgramState::updateActiveSamplers()
1449 {
1450 mExecutable->mActiveSamplerRefCounts.fill(0);
1451 mExecutable->updateActiveSamplers(*this);
1452 }
1453
updateProgramInterfaceInputs()1454 void ProgramState::updateProgramInterfaceInputs()
1455 {
1456 const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType();
1457
1458 if (firstAttachedShaderType == ShaderType::Vertex)
1459 {
1460 // Vertex attributes are already what we need, so nothing to do
1461 return;
1462 }
1463
1464 Shader *shader = getAttachedShader(firstAttachedShaderType);
1465 ASSERT(shader);
1466
1467 // Copy over each input varying, since the Shader could go away
1468 if (shader->getType() == ShaderType::Compute)
1469 {
1470 for (const sh::ShaderVariable &attribute : shader->getAllAttributes())
1471 {
1472 // Compute Shaders have the following built-in input variables.
1473 //
1474 // in uvec3 gl_NumWorkGroups;
1475 // in uvec3 gl_WorkGroupID;
1476 // in uvec3 gl_LocalInvocationID;
1477 // in uvec3 gl_GlobalInvocationID;
1478 // in uint gl_LocalInvocationIndex;
1479 // They are all vecs or uints, so no special handling is required.
1480 mExecutable->mProgramInputs.emplace_back(attribute);
1481 }
1482 }
1483 else
1484 {
1485 for (const sh::ShaderVariable &varying : shader->getInputVaryings())
1486 {
1487 UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1488 }
1489 }
1490 }
1491
updateProgramInterfaceOutputs()1492 void ProgramState::updateProgramInterfaceOutputs()
1493 {
1494 const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType();
1495
1496 if (lastAttachedShaderType == ShaderType::Fragment)
1497 {
1498 // Fragment outputs are already what we need, so nothing to do
1499 return;
1500 }
1501 if (lastAttachedShaderType == ShaderType::Compute)
1502 {
1503 // If the program only contains a Compute Shader, then there are no user-defined outputs.
1504 return;
1505 }
1506
1507 Shader *shader = getAttachedShader(lastAttachedShaderType);
1508 ASSERT(shader);
1509
1510 // Copy over each output varying, since the Shader could go away
1511 for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
1512 {
1513 UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1514 }
1515 }
1516
1517 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1518 void Program::unlink()
1519 {
1520 if (mLinkingState && mLinkingState->linkedExecutable)
1521 {
1522 // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of
1523 // the last successfully linked ProgramExecutable, so we don't lose any state information.
1524 mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable));
1525 }
1526 mState.mExecutable->reset();
1527
1528 mState.mUniformLocations.clear();
1529 mState.mBufferVariables.clear();
1530 mState.mComputeShaderLocalSize.fill(1);
1531 mState.mNumViews = -1;
1532 mState.mDrawIDLocation = -1;
1533 mState.mBaseVertexLocation = -1;
1534 mState.mBaseInstanceLocation = -1;
1535 mState.mCachedBaseVertex = 0;
1536 mState.mCachedBaseInstance = 0;
1537 mState.mSpecConstUsageBits.reset();
1538
1539 mValidated = false;
1540
1541 mLinked = false;
1542 }
1543
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1544 angle::Result Program::loadBinary(const Context *context,
1545 GLenum binaryFormat,
1546 const void *binary,
1547 GLsizei length)
1548 {
1549 ASSERT(!mLinkingState);
1550 unlink();
1551 InfoLog &infoLog = mState.mExecutable->getInfoLog();
1552
1553 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1554 return angle::Result::Continue;
1555 #else
1556 ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1557 if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1558 {
1559 infoLog << "Invalid program binary format.";
1560 return angle::Result::Continue;
1561 }
1562
1563 BinaryInputStream stream(binary, length);
1564 ANGLE_TRY(deserialize(context, stream, infoLog));
1565 // Currently we require the full shader text to compute the program hash.
1566 // We could also store the binary in the internal program cache.
1567
1568 for (size_t uniformBlockIndex = 0;
1569 uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
1570 {
1571 mDirtyBits.set(uniformBlockIndex);
1572 }
1573
1574 // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple
1575 // implementations. In some implementations, a background thread is used to compile the
1576 // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with
1577 // the operation.
1578
1579 // We do not want to call LinkEvent::wait because that will cause the background thread
1580 // to finish its task before returning, thus defeating the purpose of background compilation.
1581 // We need to defer waiting on background compilation until the very last minute when we
1582 // absolutely need the results, such as when the developer binds the program or queries
1583 // for the completion status.
1584
1585 // If load returns nullptr, we know for sure that the binary is not compatible with the backend.
1586 // The loaded binary could have been read from the on-disk shader cache and be corrupted or
1587 // serialized with different revision and subsystem id than the currently loaded backend.
1588 // Returning 'Incomplete' to the caller results in link happening using the original shader
1589 // sources.
1590 angle::Result result;
1591 std::unique_ptr<LinkingState> linkingState;
1592 std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog);
1593 if (linkEvent)
1594 {
1595 linkingState = std::make_unique<LinkingState>();
1596 linkingState->linkingFromBinary = true;
1597 linkingState->linkEvent = std::move(linkEvent);
1598 result = angle::Result::Continue;
1599 }
1600 else
1601 {
1602 result = angle::Result::Incomplete;
1603 }
1604 mLinkingState = std::move(linkingState);
1605
1606 return result;
1607 #endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1608 }
1609
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1610 angle::Result Program::saveBinary(Context *context,
1611 GLenum *binaryFormat,
1612 void *binary,
1613 GLsizei bufSize,
1614 GLsizei *length) const
1615 {
1616 ASSERT(!mLinkingState);
1617 if (binaryFormat)
1618 {
1619 *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1620 }
1621
1622 angle::MemoryBuffer memoryBuf;
1623 ANGLE_TRY(serialize(context, &memoryBuf));
1624
1625 GLsizei streamLength = static_cast<GLsizei>(memoryBuf.size());
1626 const uint8_t *streamState = memoryBuf.data();
1627
1628 if (streamLength > bufSize)
1629 {
1630 if (length)
1631 {
1632 *length = 0;
1633 }
1634
1635 // TODO: This should be moved to the validation layer but computing the size of the binary
1636 // before saving it causes the save to happen twice. It may be possible to write the binary
1637 // to a separate buffer, validate sizes and then copy it.
1638 ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1639 }
1640
1641 if (binary)
1642 {
1643 char *ptr = reinterpret_cast<char *>(binary);
1644
1645 memcpy(ptr, streamState, streamLength);
1646 ptr += streamLength;
1647
1648 ASSERT(ptr - streamLength == binary);
1649 }
1650
1651 if (length)
1652 {
1653 *length = streamLength;
1654 }
1655
1656 return angle::Result::Continue;
1657 }
1658
getBinaryLength(Context * context) const1659 GLint Program::getBinaryLength(Context *context) const
1660 {
1661 ASSERT(!mLinkingState);
1662 if (!mLinked)
1663 {
1664 return 0;
1665 }
1666
1667 GLint length;
1668 angle::Result result =
1669 saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1670 if (result != angle::Result::Continue)
1671 {
1672 return 0;
1673 }
1674
1675 return length;
1676 }
1677
setBinaryRetrievableHint(bool retrievable)1678 void Program::setBinaryRetrievableHint(bool retrievable)
1679 {
1680 ASSERT(!mLinkingState);
1681 // TODO(jmadill) : replace with dirty bits
1682 mProgram->setBinaryRetrievableHint(retrievable);
1683 mState.mBinaryRetrieveableHint = retrievable;
1684 }
1685
getBinaryRetrievableHint() const1686 bool Program::getBinaryRetrievableHint() const
1687 {
1688 ASSERT(!mLinkingState);
1689 return mState.mBinaryRetrieveableHint;
1690 }
1691
setSeparable(bool separable)1692 void Program::setSeparable(bool separable)
1693 {
1694 ASSERT(!mLinkingState);
1695 // TODO(yunchao) : replace with dirty bits
1696 if (mState.mSeparable != separable)
1697 {
1698 mProgram->setSeparable(separable);
1699 mState.mSeparable = separable;
1700 }
1701 }
1702
isSeparable() const1703 bool Program::isSeparable() const
1704 {
1705 ASSERT(!mLinkingState);
1706 return mState.mSeparable;
1707 }
1708
deleteSelf(const Context * context)1709 void Program::deleteSelf(const Context *context)
1710 {
1711 ASSERT(mRefCount == 0 && mDeleteStatus);
1712 mResourceManager->deleteProgram(context, mHandle);
1713 }
1714
getRefCount() const1715 unsigned int Program::getRefCount() const
1716 {
1717 return mRefCount;
1718 }
1719
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const1720 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
1721 {
1722 ASSERT(!mLinkingState);
1723 int total = 0;
1724
1725 for (const Shader *shader : mState.mAttachedShaders)
1726 {
1727 if (shader && (total < maxCount))
1728 {
1729 shaders[total] = shader->getHandle();
1730 ++total;
1731 }
1732 }
1733
1734 if (count)
1735 {
1736 *count = total;
1737 }
1738 }
1739
getAttributeLocation(const std::string & name) const1740 GLuint Program::getAttributeLocation(const std::string &name) const
1741 {
1742 ASSERT(!mLinkingState);
1743 return mState.getAttributeLocation(name);
1744 }
1745
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const1746 void Program::getActiveAttribute(GLuint index,
1747 GLsizei bufsize,
1748 GLsizei *length,
1749 GLint *size,
1750 GLenum *type,
1751 GLchar *name) const
1752 {
1753 ASSERT(!mLinkingState);
1754 if (!mLinked)
1755 {
1756 if (bufsize > 0)
1757 {
1758 name[0] = '\0';
1759 }
1760
1761 if (length)
1762 {
1763 *length = 0;
1764 }
1765
1766 *type = GL_NONE;
1767 *size = 1;
1768 return;
1769 }
1770
1771 ASSERT(index < mState.mExecutable->getProgramInputs().size());
1772 const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
1773
1774 if (bufsize > 0)
1775 {
1776 CopyStringToBuffer(name, attrib.name, bufsize, length);
1777 }
1778
1779 // Always a single 'type' instance
1780 *size = 1;
1781 *type = attrib.type;
1782 }
1783
getActiveAttributeCount() const1784 GLint Program::getActiveAttributeCount() const
1785 {
1786 ASSERT(!mLinkingState);
1787 if (!mLinked)
1788 {
1789 return 0;
1790 }
1791
1792 return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
1793 }
1794
getActiveAttributeMaxLength() const1795 GLint Program::getActiveAttributeMaxLength() const
1796 {
1797 ASSERT(!mLinkingState);
1798 if (!mLinked)
1799 {
1800 return 0;
1801 }
1802
1803 size_t maxLength = 0;
1804
1805 for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
1806 {
1807 maxLength = std::max(attrib.name.length() + 1, maxLength);
1808 }
1809
1810 return static_cast<GLint>(maxLength);
1811 }
1812
getAttributes() const1813 const std::vector<sh::ShaderVariable> &Program::getAttributes() const
1814 {
1815 ASSERT(!mLinkingState);
1816 return mState.mExecutable->getProgramInputs();
1817 }
1818
getComputeShaderLocalSize() const1819 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
1820 {
1821 ASSERT(!mLinkingState);
1822 return mState.mComputeShaderLocalSize;
1823 }
1824
getGeometryShaderInputPrimitiveType() const1825 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
1826 {
1827 ASSERT(!mLinkingState && mState.mExecutable);
1828 return mState.mExecutable->getGeometryShaderInputPrimitiveType();
1829 }
getGeometryShaderOutputPrimitiveType() const1830 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
1831 {
1832 ASSERT(!mLinkingState && mState.mExecutable);
1833 return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
1834 }
getGeometryShaderInvocations() const1835 GLint Program::getGeometryShaderInvocations() const
1836 {
1837 ASSERT(!mLinkingState && mState.mExecutable);
1838 return mState.mExecutable->getGeometryShaderInvocations();
1839 }
getGeometryShaderMaxVertices() const1840 GLint Program::getGeometryShaderMaxVertices() const
1841 {
1842 ASSERT(!mLinkingState && mState.mExecutable);
1843 return mState.mExecutable->getGeometryShaderMaxVertices();
1844 }
1845
getTessControlShaderVertices() const1846 GLint Program::getTessControlShaderVertices() const
1847 {
1848 ASSERT(!mLinkingState && mState.mExecutable);
1849 return mState.mExecutable->mTessControlShaderVertices;
1850 }
1851
getTessGenMode() const1852 GLenum Program::getTessGenMode() const
1853 {
1854 ASSERT(!mLinkingState && mState.mExecutable);
1855 return mState.mExecutable->mTessGenMode;
1856 }
1857
getTessGenPointMode() const1858 GLenum Program::getTessGenPointMode() const
1859 {
1860 ASSERT(!mLinkingState && mState.mExecutable);
1861 return mState.mExecutable->mTessGenPointMode;
1862 }
1863
getTessGenSpacing() const1864 GLenum Program::getTessGenSpacing() const
1865 {
1866 ASSERT(!mLinkingState && mState.mExecutable);
1867 return mState.mExecutable->mTessGenSpacing;
1868 }
1869
getTessGenVertexOrder() const1870 GLenum Program::getTessGenVertexOrder() const
1871 {
1872 ASSERT(!mLinkingState && mState.mExecutable);
1873 return mState.mExecutable->mTessGenVertexOrder;
1874 }
1875
getInputResource(size_t index) const1876 const sh::ShaderVariable &Program::getInputResource(size_t index) const
1877 {
1878 ASSERT(!mLinkingState);
1879 ASSERT(index < mState.mExecutable->getProgramInputs().size());
1880 return mState.mExecutable->getProgramInputs()[index];
1881 }
1882
getInputResourceIndex(const GLchar * name) const1883 GLuint Program::getInputResourceIndex(const GLchar *name) const
1884 {
1885 ASSERT(!mLinkingState);
1886 const std::string nameString = StripLastArrayIndex(name);
1887
1888 for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
1889 {
1890 sh::ShaderVariable resource = getInputResource(index);
1891 if (resource.name == nameString)
1892 {
1893 return static_cast<GLuint>(index);
1894 }
1895 }
1896
1897 return GL_INVALID_INDEX;
1898 }
1899
getResourceMaxNameSize(const sh::ShaderVariable & resource,GLint max) const1900 GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
1901 {
1902 if (resource.isArray())
1903 {
1904 return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
1905 }
1906 else
1907 {
1908 return std::max(max, clampCast<GLint>((resource.name).size()));
1909 }
1910 }
1911
getInputResourceMaxNameSize() const1912 GLuint Program::getInputResourceMaxNameSize() const
1913 {
1914 GLint max = 0;
1915
1916 for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
1917 {
1918 max = getResourceMaxNameSize(resource, max);
1919 }
1920
1921 return max;
1922 }
1923
getOutputResourceMaxNameSize() const1924 GLuint Program::getOutputResourceMaxNameSize() const
1925 {
1926 GLint max = 0;
1927
1928 for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
1929 {
1930 max = getResourceMaxNameSize(resource, max);
1931 }
1932
1933 return max;
1934 }
1935
getResourceLocation(const GLchar * name,const sh::ShaderVariable & variable) const1936 GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
1937 {
1938 if (variable.isBuiltIn())
1939 {
1940 return GL_INVALID_INDEX;
1941 }
1942
1943 GLint location = variable.location;
1944 if (variable.isArray())
1945 {
1946 size_t nameLengthWithoutArrayIndexOut;
1947 size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
1948 // The 'name' string may not contain the array notation "[0]"
1949 if (arrayIndex != GL_INVALID_INDEX)
1950 {
1951 location += arrayIndex;
1952 }
1953 }
1954
1955 return location;
1956 }
1957
getInputResourceLocation(const GLchar * name) const1958 GLuint Program::getInputResourceLocation(const GLchar *name) const
1959 {
1960 const GLuint index = getInputResourceIndex(name);
1961 if (index == GL_INVALID_INDEX)
1962 {
1963 return index;
1964 }
1965
1966 const sh::ShaderVariable &variable = getInputResource(index);
1967
1968 return getResourceLocation(name, variable);
1969 }
1970
getOutputResourceLocation(const GLchar * name) const1971 GLuint Program::getOutputResourceLocation(const GLchar *name) const
1972 {
1973 const GLuint index = getOutputResourceIndex(name);
1974 if (index == GL_INVALID_INDEX)
1975 {
1976 return index;
1977 }
1978
1979 const sh::ShaderVariable &variable = getOutputResource(index);
1980
1981 return getResourceLocation(name, variable);
1982 }
1983
getOutputResourceIndex(const GLchar * name) const1984 GLuint Program::getOutputResourceIndex(const GLchar *name) const
1985 {
1986 ASSERT(!mLinkingState);
1987 const std::string nameString = StripLastArrayIndex(name);
1988
1989 for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
1990 {
1991 sh::ShaderVariable resource = getOutputResource(index);
1992 if (resource.name == nameString)
1993 {
1994 return static_cast<GLuint>(index);
1995 }
1996 }
1997
1998 return GL_INVALID_INDEX;
1999 }
2000
getOutputResourceCount() const2001 size_t Program::getOutputResourceCount() const
2002 {
2003 ASSERT(!mLinkingState);
2004 return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
2005 }
2006
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2007 void Program::getResourceName(const std::string name,
2008 GLsizei bufSize,
2009 GLsizei *length,
2010 GLchar *dest) const
2011 {
2012 if (length)
2013 {
2014 *length = 0;
2015 }
2016
2017 if (!mLinked)
2018 {
2019 if (bufSize > 0)
2020 {
2021 dest[0] = '\0';
2022 }
2023 return;
2024 }
2025
2026 if (bufSize > 0)
2027 {
2028 CopyStringToBuffer(dest, name, bufSize, length);
2029 }
2030 }
2031
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2032 void Program::getInputResourceName(GLuint index,
2033 GLsizei bufSize,
2034 GLsizei *length,
2035 GLchar *name) const
2036 {
2037 ASSERT(!mLinkingState);
2038 getResourceName(getInputResourceName(index), bufSize, length, name);
2039 }
2040
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2041 void Program::getOutputResourceName(GLuint index,
2042 GLsizei bufSize,
2043 GLsizei *length,
2044 GLchar *name) const
2045 {
2046 ASSERT(!mLinkingState);
2047 getResourceName(getOutputResourceName(index), bufSize, length, name);
2048 }
2049
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2050 void Program::getUniformResourceName(GLuint index,
2051 GLsizei bufSize,
2052 GLsizei *length,
2053 GLchar *name) const
2054 {
2055 ASSERT(!mLinkingState);
2056 ASSERT(index < mState.mExecutable->getUniforms().size());
2057 getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
2058 }
2059
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2060 void Program::getBufferVariableResourceName(GLuint index,
2061 GLsizei bufSize,
2062 GLsizei *length,
2063 GLchar *name) const
2064 {
2065 ASSERT(!mLinkingState);
2066 ASSERT(index < mState.mBufferVariables.size());
2067 getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
2068 }
2069
getResourceName(const sh::ShaderVariable & resource) const2070 const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
2071 {
2072 std::string resourceName = resource.name;
2073
2074 if (resource.isArray())
2075 {
2076 resourceName += "[0]";
2077 }
2078
2079 return resourceName;
2080 }
2081
getInputResourceName(GLuint index) const2082 const std::string Program::getInputResourceName(GLuint index) const
2083 {
2084 ASSERT(!mLinkingState);
2085 const sh::ShaderVariable &resource = getInputResource(index);
2086
2087 return getResourceName(resource);
2088 }
2089
getOutputResourceName(GLuint index) const2090 const std::string Program::getOutputResourceName(GLuint index) const
2091 {
2092 ASSERT(!mLinkingState);
2093 const sh::ShaderVariable &resource = getOutputResource(index);
2094
2095 return getResourceName(resource);
2096 }
2097
getOutputResource(size_t index) const2098 const sh::ShaderVariable &Program::getOutputResource(size_t index) const
2099 {
2100 ASSERT(!mLinkingState);
2101 ASSERT(index < mState.mExecutable->getOutputVariables().size());
2102 return mState.mExecutable->getOutputVariables()[index];
2103 }
2104
getAttributeBindings() const2105 const ProgramBindings &Program::getAttributeBindings() const
2106 {
2107 ASSERT(!mLinkingState);
2108 return mAttributeBindings;
2109 }
getUniformLocationBindings() const2110 const ProgramAliasedBindings &Program::getUniformLocationBindings() const
2111 {
2112 ASSERT(!mLinkingState);
2113 return mState.mUniformLocationBindings;
2114 }
2115
getFragmentOutputLocations() const2116 const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
2117 {
2118 ASSERT(!mLinkingState);
2119 return mFragmentOutputLocations;
2120 }
2121
getFragmentOutputIndexes() const2122 const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
2123 {
2124 ASSERT(!mLinkingState);
2125 return mFragmentOutputIndexes;
2126 }
2127
getTransformFeedbackStrides() const2128 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2129 {
2130 ASSERT(!mLinkingState);
2131 return mState.mExecutable->getTransformFeedbackStrides();
2132 }
2133
getFragDataLocation(const std::string & name) const2134 GLint Program::getFragDataLocation(const std::string &name) const
2135 {
2136 ASSERT(!mLinkingState);
2137 GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
2138 mState.mExecutable->getOutputLocations(), name);
2139 if (primaryLocation != -1)
2140 {
2141 return primaryLocation;
2142 }
2143 return GetVariableLocation(mState.mExecutable->getOutputVariables(),
2144 mState.mExecutable->getSecondaryOutputLocations(), name);
2145 }
2146
getFragDataIndex(const std::string & name) const2147 GLint Program::getFragDataIndex(const std::string &name) const
2148 {
2149 ASSERT(!mLinkingState);
2150 if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2151 mState.mExecutable->getOutputLocations(), name) != -1)
2152 {
2153 return 0;
2154 }
2155 if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2156 mState.mExecutable->getSecondaryOutputLocations(), name) != -1)
2157 {
2158 return 1;
2159 }
2160 return -1;
2161 }
2162
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2163 void Program::getActiveUniform(GLuint index,
2164 GLsizei bufsize,
2165 GLsizei *length,
2166 GLint *size,
2167 GLenum *type,
2168 GLchar *name) const
2169 {
2170 ASSERT(!mLinkingState);
2171 if (mLinked)
2172 {
2173 // index must be smaller than getActiveUniformCount()
2174 ASSERT(index < mState.mExecutable->getUniforms().size());
2175 const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
2176
2177 if (bufsize > 0)
2178 {
2179 std::string string = uniform.name;
2180 CopyStringToBuffer(name, string, bufsize, length);
2181 }
2182
2183 *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2184 *type = uniform.type;
2185 }
2186 else
2187 {
2188 if (bufsize > 0)
2189 {
2190 name[0] = '\0';
2191 }
2192
2193 if (length)
2194 {
2195 *length = 0;
2196 }
2197
2198 *size = 0;
2199 *type = GL_NONE;
2200 }
2201 }
2202
getActiveUniformCount() const2203 GLint Program::getActiveUniformCount() const
2204 {
2205 ASSERT(!mLinkingState);
2206 if (mLinked)
2207 {
2208 return static_cast<GLint>(mState.mExecutable->getUniforms().size());
2209 }
2210 else
2211 {
2212 return 0;
2213 }
2214 }
2215
getActiveBufferVariableCount() const2216 size_t Program::getActiveBufferVariableCount() const
2217 {
2218 ASSERT(!mLinkingState);
2219 return mLinked ? mState.mBufferVariables.size() : 0;
2220 }
2221
getActiveUniformMaxLength() const2222 GLint Program::getActiveUniformMaxLength() const
2223 {
2224 ASSERT(!mLinkingState);
2225 size_t maxLength = 0;
2226
2227 if (mLinked)
2228 {
2229 for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
2230 {
2231 if (!uniform.name.empty())
2232 {
2233 size_t length = uniform.name.length() + 1u;
2234 if (uniform.isArray())
2235 {
2236 length += 3; // Counting in "[0]".
2237 }
2238 maxLength = std::max(length, maxLength);
2239 }
2240 }
2241 }
2242
2243 return static_cast<GLint>(maxLength);
2244 }
2245
isValidUniformLocation(UniformLocation location) const2246 bool Program::isValidUniformLocation(UniformLocation location) const
2247 {
2248 ASSERT(!mLinkingState);
2249 ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2250 return (location.value >= 0 &&
2251 static_cast<size_t>(location.value) < mState.mUniformLocations.size() &&
2252 mState.mUniformLocations[static_cast<size_t>(location.value)].used());
2253 }
2254
getUniformByLocation(UniformLocation location) const2255 const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const
2256 {
2257 ASSERT(!mLinkingState);
2258 ASSERT(location.value >= 0 &&
2259 static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2260 return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
2261 }
2262
getUniformLocation(UniformLocation location) const2263 const VariableLocation &Program::getUniformLocation(UniformLocation location) const
2264 {
2265 ASSERT(!mLinkingState);
2266 ASSERT(location.value >= 0 &&
2267 static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2268 return mState.mUniformLocations[location.value];
2269 }
2270
getBufferVariableByIndex(GLuint index) const2271 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2272 {
2273 ASSERT(!mLinkingState);
2274 ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2275 return mState.mBufferVariables[index];
2276 }
2277
getUniformLocation(const std::string & name) const2278 UniformLocation Program::getUniformLocation(const std::string &name) const
2279 {
2280 ASSERT(!mLinkingState);
2281 return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
2282 }
2283
getUniformIndex(const std::string & name) const2284 GLuint Program::getUniformIndex(const std::string &name) const
2285 {
2286 ASSERT(!mLinkingState);
2287 return mState.getUniformIndexFromName(name);
2288 }
2289
shouldIgnoreUniform(UniformLocation location) const2290 bool Program::shouldIgnoreUniform(UniformLocation location) const
2291 {
2292 if (location.value == -1)
2293 {
2294 return true;
2295 }
2296
2297 if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored)
2298 {
2299 return true;
2300 }
2301
2302 return false;
2303 }
2304
2305 template <typename UniformT,
2306 GLint UniformSize,
2307 void (rx::ProgramImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
setUniformGeneric(UniformLocation location,GLsizei count,const UniformT * v)2308 void Program::setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v)
2309 {
2310 ASSERT(!mLinkingState);
2311 if (shouldIgnoreUniform(location))
2312 {
2313 return;
2314 }
2315
2316 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2317 GLsizei clampedCount = clampUniformCount(locationInfo, count, UniformSize, v);
2318 (mProgram->*SetUniformFunc)(location.value, clampedCount, v);
2319 onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
2320 }
2321
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2322 void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2323 {
2324 setUniformGeneric<GLfloat, 1, &rx::ProgramImpl::setUniform1fv>(location, count, v);
2325 }
2326
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2327 void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2328 {
2329 setUniformGeneric<GLfloat, 2, &rx::ProgramImpl::setUniform2fv>(location, count, v);
2330 }
2331
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2332 void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2333 {
2334 setUniformGeneric<GLfloat, 3, &rx::ProgramImpl::setUniform3fv>(location, count, v);
2335 }
2336
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2337 void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2338 {
2339 setUniformGeneric<GLfloat, 4, &rx::ProgramImpl::setUniform4fv>(location, count, v);
2340 }
2341
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2342 void Program::setUniform1iv(Context *context,
2343 UniformLocation location,
2344 GLsizei count,
2345 const GLint *v)
2346 {
2347 ASSERT(!mLinkingState);
2348 if (shouldIgnoreUniform(location))
2349 {
2350 return;
2351 }
2352
2353 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2354 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2355
2356 mProgram->setUniform1iv(location.value, clampedCount, v);
2357
2358 if (mState.isSamplerUniformIndex(locationInfo.index))
2359 {
2360 updateSamplerUniform(context, locationInfo, clampedCount, v);
2361 }
2362 else
2363 {
2364 onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
2365 }
2366 }
2367
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2368 void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2369 {
2370 setUniformGeneric<GLint, 2, &rx::ProgramImpl::setUniform2iv>(location, count, v);
2371 }
2372
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2373 void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2374 {
2375 setUniformGeneric<GLint, 3, &rx::ProgramImpl::setUniform3iv>(location, count, v);
2376 }
2377
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2378 void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2379 {
2380 setUniformGeneric<GLint, 4, &rx::ProgramImpl::setUniform4iv>(location, count, v);
2381 }
2382
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2383 void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2384 {
2385 setUniformGeneric<GLuint, 1, &rx::ProgramImpl::setUniform1uiv>(location, count, v);
2386 }
2387
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2388 void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2389 {
2390 setUniformGeneric<GLuint, 2, &rx::ProgramImpl::setUniform2uiv>(location, count, v);
2391 }
2392
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2393 void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2394 {
2395 setUniformGeneric<GLuint, 3, &rx::ProgramImpl::setUniform3uiv>(location, count, v);
2396 }
2397
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2398 void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2399 {
2400 setUniformGeneric<GLuint, 4, &rx::ProgramImpl::setUniform4uiv>(location, count, v);
2401 }
2402
2403 template <
2404 typename UniformT,
2405 GLint MatrixC,
2406 GLint MatrixR,
2407 void (rx::ProgramImpl::*SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
setUniformMatrixGeneric(UniformLocation location,GLsizei count,GLboolean transpose,const UniformT * v)2408 void Program::setUniformMatrixGeneric(UniformLocation location,
2409 GLsizei count,
2410 GLboolean transpose,
2411 const UniformT *v)
2412 {
2413 ASSERT(!mLinkingState);
2414 if (shouldIgnoreUniform(location))
2415 {
2416 return;
2417 }
2418
2419 GLsizei clampedCount = clampMatrixUniformCount<MatrixC, MatrixR>(location, count, transpose, v);
2420 (mProgram->*SetUniformMatrixFunc)(location.value, clampedCount, transpose, v);
2421 onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
2422 }
2423
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2424 void Program::setUniformMatrix2fv(UniformLocation location,
2425 GLsizei count,
2426 GLboolean transpose,
2427 const GLfloat *v)
2428 {
2429 setUniformMatrixGeneric<GLfloat, 2, 2, &rx::ProgramImpl::setUniformMatrix2fv>(location, count,
2430 transpose, v);
2431 }
2432
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2433 void Program::setUniformMatrix3fv(UniformLocation location,
2434 GLsizei count,
2435 GLboolean transpose,
2436 const GLfloat *v)
2437 {
2438 setUniformMatrixGeneric<GLfloat, 3, 3, &rx::ProgramImpl::setUniformMatrix3fv>(location, count,
2439 transpose, v);
2440 }
2441
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2442 void Program::setUniformMatrix4fv(UniformLocation location,
2443 GLsizei count,
2444 GLboolean transpose,
2445 const GLfloat *v)
2446 {
2447 setUniformMatrixGeneric<GLfloat, 4, 4, &rx::ProgramImpl::setUniformMatrix4fv>(location, count,
2448 transpose, v);
2449 }
2450
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2451 void Program::setUniformMatrix2x3fv(UniformLocation location,
2452 GLsizei count,
2453 GLboolean transpose,
2454 const GLfloat *v)
2455 {
2456 setUniformMatrixGeneric<GLfloat, 2, 3, &rx::ProgramImpl::setUniformMatrix2x3fv>(location, count,
2457 transpose, v);
2458 }
2459
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2460 void Program::setUniformMatrix2x4fv(UniformLocation location,
2461 GLsizei count,
2462 GLboolean transpose,
2463 const GLfloat *v)
2464 {
2465 setUniformMatrixGeneric<GLfloat, 2, 4, &rx::ProgramImpl::setUniformMatrix2x4fv>(location, count,
2466 transpose, v);
2467 }
2468
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2469 void Program::setUniformMatrix3x2fv(UniformLocation location,
2470 GLsizei count,
2471 GLboolean transpose,
2472 const GLfloat *v)
2473 {
2474 setUniformMatrixGeneric<GLfloat, 3, 2, &rx::ProgramImpl::setUniformMatrix3x2fv>(location, count,
2475 transpose, v);
2476 }
2477
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2478 void Program::setUniformMatrix3x4fv(UniformLocation location,
2479 GLsizei count,
2480 GLboolean transpose,
2481 const GLfloat *v)
2482 {
2483 setUniformMatrixGeneric<GLfloat, 3, 4, &rx::ProgramImpl::setUniformMatrix3x4fv>(location, count,
2484 transpose, v);
2485 }
2486
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2487 void Program::setUniformMatrix4x2fv(UniformLocation location,
2488 GLsizei count,
2489 GLboolean transpose,
2490 const GLfloat *v)
2491 {
2492 setUniformMatrixGeneric<GLfloat, 4, 2, &rx::ProgramImpl::setUniformMatrix4x2fv>(location, count,
2493 transpose, v);
2494 }
2495
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2496 void Program::setUniformMatrix4x3fv(UniformLocation location,
2497 GLsizei count,
2498 GLboolean transpose,
2499 const GLfloat *v)
2500 {
2501 setUniformMatrixGeneric<GLfloat, 4, 3, &rx::ProgramImpl::setUniformMatrix4x3fv>(location, count,
2502 transpose, v);
2503 }
2504
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2505 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2506 {
2507 ASSERT(!mLinkingState);
2508 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2509 const std::vector<GLuint> &boundTextureUnits =
2510 mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
2511 return (uniformLocation.arrayIndex < boundTextureUnits.size())
2512 ? boundTextureUnits[uniformLocation.arrayIndex]
2513 : 0;
2514 }
2515
getImageUniformBinding(const VariableLocation & uniformLocation) const2516 GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
2517 {
2518 ASSERT(!mLinkingState);
2519 GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
2520
2521 const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings();
2522 const std::vector<GLuint> &boundImageUnits = imageBindings[imageIndex].boundImageUnits;
2523 return boundImageUnits[uniformLocation.arrayIndex];
2524 }
2525
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2526 void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const
2527 {
2528 ASSERT(!mLinkingState);
2529 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2530 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2531
2532 if (uniform.isSampler())
2533 {
2534 *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2535 return;
2536 }
2537 else if (uniform.isImage())
2538 {
2539 *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2540 return;
2541 }
2542
2543 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2544 if (nativeType == GL_FLOAT)
2545 {
2546 mProgram->getUniformfv(context, location.value, v);
2547 }
2548 else
2549 {
2550 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2551 }
2552 }
2553
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2554 void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const
2555 {
2556 ASSERT(!mLinkingState);
2557 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2558 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2559
2560 if (uniform.isSampler())
2561 {
2562 *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2563 return;
2564 }
2565 else if (uniform.isImage())
2566 {
2567 *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2568 return;
2569 }
2570
2571 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2572 if (nativeType == GL_INT || nativeType == GL_BOOL)
2573 {
2574 mProgram->getUniformiv(context, location.value, v);
2575 }
2576 else
2577 {
2578 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2579 }
2580 }
2581
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2582 void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const
2583 {
2584 ASSERT(!mLinkingState);
2585 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2586 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2587
2588 if (uniform.isSampler())
2589 {
2590 *v = getSamplerUniformBinding(uniformLocation);
2591 return;
2592 }
2593 else if (uniform.isImage())
2594 {
2595 *v = getImageUniformBinding(uniformLocation);
2596 return;
2597 }
2598
2599 const GLenum nativeType = VariableComponentType(uniform.type);
2600 if (nativeType == GL_UNSIGNED_INT)
2601 {
2602 mProgram->getUniformuiv(context, location.value, v);
2603 }
2604 else
2605 {
2606 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2607 }
2608 }
2609
flagForDeletion()2610 void Program::flagForDeletion()
2611 {
2612 ASSERT(!mLinkingState);
2613 mDeleteStatus = true;
2614 }
2615
isFlaggedForDeletion() const2616 bool Program::isFlaggedForDeletion() const
2617 {
2618 ASSERT(!mLinkingState);
2619 return mDeleteStatus;
2620 }
2621
validate(const Caps & caps)2622 void Program::validate(const Caps &caps)
2623 {
2624 ASSERT(!mLinkingState);
2625 mState.mExecutable->resetInfoLog();
2626 InfoLog &infoLog = mState.mExecutable->getInfoLog();
2627
2628 if (mLinked)
2629 {
2630 mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
2631 }
2632 else
2633 {
2634 infoLog << "Program has not been successfully linked.";
2635 }
2636 }
2637
isValidated() const2638 bool Program::isValidated() const
2639 {
2640 ASSERT(!mLinkingState);
2641 return mValidated;
2642 }
2643
getActiveUniformBlockName(const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2644 void Program::getActiveUniformBlockName(const UniformBlockIndex blockIndex,
2645 GLsizei bufSize,
2646 GLsizei *length,
2647 GLchar *blockName) const
2648 {
2649 ASSERT(!mLinkingState);
2650 GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
2651 blockName);
2652 }
2653
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const2654 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
2655 GLsizei bufSize,
2656 GLsizei *length,
2657 GLchar *blockName) const
2658 {
2659 ASSERT(!mLinkingState);
2660 GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize,
2661 length, blockName);
2662 }
2663
2664 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const2665 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
2666 {
2667 int maxLength = 0;
2668
2669 if (mLinked)
2670 {
2671 for (const T &resource : resources)
2672 {
2673 if (!resource.name.empty())
2674 {
2675 int length = static_cast<int>(resource.nameWithArrayIndex().length());
2676 maxLength = std::max(length + 1, maxLength);
2677 }
2678 }
2679 }
2680
2681 return maxLength;
2682 }
2683
getActiveUniformBlockMaxNameLength() const2684 GLint Program::getActiveUniformBlockMaxNameLength() const
2685 {
2686 ASSERT(!mLinkingState);
2687 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
2688 }
2689
getActiveShaderStorageBlockMaxNameLength() const2690 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
2691 {
2692 ASSERT(!mLinkingState);
2693 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
2694 }
2695
getUniformBlockIndex(const std::string & name) const2696 GLuint Program::getUniformBlockIndex(const std::string &name) const
2697 {
2698 ASSERT(!mLinkingState);
2699 return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
2700 }
2701
getShaderStorageBlockIndex(const std::string & name) const2702 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
2703 {
2704 ASSERT(!mLinkingState);
2705 return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
2706 }
2707
getUniformBlockByIndex(GLuint index) const2708 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
2709 {
2710 ASSERT(!mLinkingState);
2711 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
2712 return mState.mExecutable->getUniformBlocks()[index];
2713 }
2714
getShaderStorageBlockByIndex(GLuint index) const2715 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
2716 {
2717 ASSERT(!mLinkingState);
2718 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
2719 return mState.mExecutable->getShaderStorageBlocks()[index];
2720 }
2721
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)2722 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
2723 {
2724 ASSERT(!mLinkingState);
2725 mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding;
2726 mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value,
2727 uniformBlockBinding != 0);
2728 mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value);
2729 }
2730
getUniformBlockBinding(GLuint uniformBlockIndex) const2731 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
2732 {
2733 ASSERT(!mLinkingState);
2734 return mState.getUniformBlockBinding(uniformBlockIndex);
2735 }
2736
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const2737 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
2738 {
2739 ASSERT(!mLinkingState);
2740 return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
2741 }
2742
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2743 void Program::setTransformFeedbackVaryings(GLsizei count,
2744 const GLchar *const *varyings,
2745 GLenum bufferMode)
2746 {
2747 ASSERT(!mLinkingState);
2748 mState.mTransformFeedbackVaryingNames.resize(count);
2749 for (GLsizei i = 0; i < count; i++)
2750 {
2751 mState.mTransformFeedbackVaryingNames[i] = varyings[i];
2752 }
2753
2754 mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
2755 }
2756
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2757 void Program::getTransformFeedbackVarying(GLuint index,
2758 GLsizei bufSize,
2759 GLsizei *length,
2760 GLsizei *size,
2761 GLenum *type,
2762 GLchar *name) const
2763 {
2764 ASSERT(!mLinkingState);
2765 if (mLinked)
2766 {
2767 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
2768 const auto &var = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
2769 std::string varName = var.nameWithArrayIndex();
2770 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
2771 if (length)
2772 {
2773 *length = lastNameIdx;
2774 }
2775 if (size)
2776 {
2777 *size = var.size();
2778 }
2779 if (type)
2780 {
2781 *type = var.type;
2782 }
2783 if (name)
2784 {
2785 memcpy(name, varName.c_str(), lastNameIdx);
2786 name[lastNameIdx] = '\0';
2787 }
2788 }
2789 }
2790
getTransformFeedbackVaryingCount() const2791 GLsizei Program::getTransformFeedbackVaryingCount() const
2792 {
2793 ASSERT(!mLinkingState);
2794 if (mLinked)
2795 {
2796 return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
2797 }
2798 else
2799 {
2800 return 0;
2801 }
2802 }
2803
getTransformFeedbackVaryingMaxLength() const2804 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
2805 {
2806 ASSERT(!mLinkingState);
2807 if (mLinked)
2808 {
2809 GLsizei maxSize = 0;
2810 for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
2811 {
2812 maxSize =
2813 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
2814 }
2815
2816 return maxSize;
2817 }
2818 else
2819 {
2820 return 0;
2821 }
2822 }
2823
getTransformFeedbackBufferMode() const2824 GLenum Program::getTransformFeedbackBufferMode() const
2825 {
2826 ASSERT(!mLinkingState);
2827 return mState.mExecutable->getTransformFeedbackBufferMode();
2828 }
2829
linkValidateShaders(InfoLog & infoLog)2830 bool Program::linkValidateShaders(InfoLog &infoLog)
2831 {
2832 const ShaderMap<Shader *> &shaders = mState.mAttachedShaders;
2833
2834 bool isComputeShaderAttached = shaders[ShaderType::Compute] != nullptr;
2835 bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] ||
2836 shaders[ShaderType::TessControl] ||
2837 shaders[ShaderType::TessEvaluation] ||
2838 shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment];
2839 // Check whether we both have a compute and non-compute shaders attached.
2840 // If there are of both types attached, then linking should fail.
2841 // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
2842 if (isComputeShaderAttached && isGraphicsShaderAttached)
2843 {
2844 infoLog << "Both compute and graphics shaders are attached to the same program.";
2845 return false;
2846 }
2847
2848 Optional<int> version;
2849 for (ShaderType shaderType : kAllGraphicsShaderTypes)
2850 {
2851 Shader *shader = shaders[shaderType];
2852 ASSERT(!shader || shader->getType() == shaderType);
2853 if (!shader)
2854 {
2855 continue;
2856 }
2857
2858 if (!shader->isCompiled())
2859 {
2860 infoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
2861 return false;
2862 }
2863
2864 if (!version.valid())
2865 {
2866 version = shader->getShaderVersion();
2867 }
2868 else if (version != shader->getShaderVersion())
2869 {
2870 infoLog << ShaderTypeToString(shaderType)
2871 << " shader version does not match other shader versions.";
2872 return false;
2873 }
2874 }
2875
2876 if (isComputeShaderAttached)
2877 {
2878 ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute);
2879
2880 mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize();
2881
2882 // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
2883 // If the work group size is not specified, a link time error should occur.
2884 if (!mState.mComputeShaderLocalSize.isDeclared())
2885 {
2886 infoLog << "Work group size is not specified.";
2887 return false;
2888 }
2889 }
2890 else
2891 {
2892 if (!isGraphicsShaderAttached)
2893 {
2894 infoLog << "No compiled shaders.";
2895 return false;
2896 }
2897
2898 bool hasVertex = shaders[ShaderType::Vertex] != nullptr;
2899 bool hasFragment = shaders[ShaderType::Fragment] != nullptr;
2900 if (!isSeparable() && (!hasVertex || !hasFragment))
2901 {
2902 infoLog
2903 << "The program must contain objects to form both a vertex and fragment shader.";
2904 return false;
2905 }
2906
2907 bool hasTessControl = shaders[ShaderType::TessControl] != nullptr;
2908 bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr;
2909 if (!isSeparable() && (hasTessControl != hasTessEvaluation))
2910 {
2911 infoLog << "Tessellation control and evaluation shaders must be specified together.";
2912 return false;
2913 }
2914
2915 Shader *geometryShader = shaders[ShaderType::Geometry];
2916 if (shaders[ShaderType::Geometry])
2917 {
2918 // [GL_EXT_geometry_shader] Chapter 7
2919 // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
2920 // Language Specification, as well as any of the following reasons:
2921 // * One or more of the shader objects attached to <program> are not compiled
2922 // successfully.
2923 // * The shaders do not use the same shader language version.
2924 // * <program> contains objects to form a geometry shader, and
2925 // - <program> is not separable and contains no objects to form a vertex shader; or
2926 // - the input primitive type, output primitive type, or maximum output vertex count
2927 // is not specified in the compiled geometry shader object.
2928 ASSERT(geometryShader->getType() == ShaderType::Geometry);
2929
2930 Optional<PrimitiveMode> inputPrimitive =
2931 geometryShader->getGeometryShaderInputPrimitiveType();
2932 if (!inputPrimitive.valid())
2933 {
2934 infoLog << "Input primitive type is not specified in the geometry shader.";
2935 return false;
2936 }
2937
2938 Optional<PrimitiveMode> outputPrimitive =
2939 geometryShader->getGeometryShaderOutputPrimitiveType();
2940 if (!outputPrimitive.valid())
2941 {
2942 infoLog << "Output primitive type is not specified in the geometry shader.";
2943 return false;
2944 }
2945
2946 Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
2947 if (!maxVertices.valid())
2948 {
2949 infoLog << "'max_vertices' is not specified in the geometry shader.";
2950 return false;
2951 }
2952
2953 mState.mExecutable->mGeometryShaderInputPrimitiveType = inputPrimitive.value();
2954 mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
2955 mState.mExecutable->mGeometryShaderMaxVertices = maxVertices.value();
2956 mState.mExecutable->mGeometryShaderInvocations =
2957 geometryShader->getGeometryShaderInvocations();
2958 }
2959
2960 Shader *tessControlShader = shaders[ShaderType::TessControl];
2961 if (tessControlShader)
2962 {
2963 int tcsShaderVertices = tessControlShader->getTessControlShaderVertices();
2964 if (tcsShaderVertices == 0)
2965 {
2966 // In tessellation control shader, output vertices should be specified at least
2967 // once.
2968 // > GLSL ES Version 3.20.6 spec:
2969 // > 4.4.2. Output Layout Qualifiers
2970 // > Tessellation Control Outputs
2971 // > ...
2972 // > There must be at least one layout qualifier specifying an output patch vertex
2973 // > count in any program containing a tessellation control shader.
2974 infoLog << "In Tessellation Control Shader, at least one layout qualifier "
2975 "specifying an output patch vertex count must exist.";
2976 return false;
2977 }
2978
2979 mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
2980 }
2981
2982 Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
2983 if (tessEvaluationShader)
2984 {
2985 GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode();
2986 if (tesPrimitiveMode == 0)
2987 {
2988 // In tessellation evaluation shader, a primitive mode should be specified at least
2989 // once.
2990 // > GLSL ES Version 3.20.6 spec:
2991 // > 4.4.1. Input Layout Qualifiers
2992 // > Tessellation Evaluation Inputs
2993 // > ...
2994 // > The tessellation evaluation shader object in a program must declare a primitive
2995 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
2996 // > identifiers is optional.
2997 infoLog << "The Tessellation Evaluation Shader object in a program must declare a "
2998 "primitive mode in its input layout.";
2999 return false;
3000 }
3001
3002 mState.mExecutable->mTessGenMode = tesPrimitiveMode;
3003 mState.mExecutable->mTessGenSpacing = tessEvaluationShader->getTessGenSpacing();
3004 mState.mExecutable->mTessGenVertexOrder = tessEvaluationShader->getTessGenVertexOrder();
3005 mState.mExecutable->mTessGenPointMode = tessEvaluationShader->getTessGenPointMode();
3006 }
3007 }
3008
3009 return true;
3010 }
3011
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const3012 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
3013 {
3014 ASSERT(!mLinkingState);
3015 for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
3016 ++tfIndex)
3017 {
3018 const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
3019 if (tf.nameWithArrayIndex() == name)
3020 {
3021 return tfIndex;
3022 }
3023 }
3024 return GL_INVALID_INDEX;
3025 }
3026
getTransformFeedbackVaryingResource(GLuint index) const3027 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
3028 {
3029 ASSERT(!mLinkingState);
3030 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3031 return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3032 }
3033
hasDrawIDUniform() const3034 bool Program::hasDrawIDUniform() const
3035 {
3036 ASSERT(!mLinkingState);
3037 return mState.mDrawIDLocation >= 0;
3038 }
3039
setDrawIDUniform(GLint drawid)3040 void Program::setDrawIDUniform(GLint drawid)
3041 {
3042 ASSERT(!mLinkingState);
3043 ASSERT(mState.mDrawIDLocation >= 0);
3044 mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
3045 }
3046
hasBaseVertexUniform() const3047 bool Program::hasBaseVertexUniform() const
3048 {
3049 ASSERT(!mLinkingState);
3050 return mState.mBaseVertexLocation >= 0;
3051 }
3052
setBaseVertexUniform(GLint baseVertex)3053 void Program::setBaseVertexUniform(GLint baseVertex)
3054 {
3055 ASSERT(!mLinkingState);
3056 ASSERT(mState.mBaseVertexLocation >= 0);
3057 if (baseVertex == mState.mCachedBaseVertex)
3058 {
3059 return;
3060 }
3061 mState.mCachedBaseVertex = baseVertex;
3062 mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
3063 }
3064
hasBaseInstanceUniform() const3065 bool Program::hasBaseInstanceUniform() const
3066 {
3067 ASSERT(!mLinkingState);
3068 return mState.mBaseInstanceLocation >= 0;
3069 }
3070
setBaseInstanceUniform(GLuint baseInstance)3071 void Program::setBaseInstanceUniform(GLuint baseInstance)
3072 {
3073 ASSERT(!mLinkingState);
3074 ASSERT(mState.mBaseInstanceLocation >= 0);
3075 if (baseInstance == mState.mCachedBaseInstance)
3076 {
3077 return;
3078 }
3079 mState.mCachedBaseInstance = baseInstance;
3080 GLint baseInstanceInt = baseInstance;
3081 mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
3082 }
3083
linkVaryings(InfoLog & infoLog) const3084 bool Program::linkVaryings(InfoLog &infoLog) const
3085 {
3086 ShaderType previousShaderType = ShaderType::InvalidEnum;
3087 for (ShaderType shaderType : kAllGraphicsShaderTypes)
3088 {
3089 Shader *currentShader = mState.mAttachedShaders[shaderType];
3090 if (!currentShader)
3091 {
3092 continue;
3093 }
3094
3095 if (previousShaderType != ShaderType::InvalidEnum)
3096 {
3097 Shader *previousShader = mState.mAttachedShaders[previousShaderType];
3098 const std::vector<sh::ShaderVariable> &outputVaryings =
3099 previousShader->getOutputVaryings();
3100
3101 if (!LinkValidateShaderInterfaceMatching(
3102 outputVaryings, currentShader->getInputVaryings(), previousShaderType,
3103 currentShader->getType(), previousShader->getShaderVersion(),
3104 currentShader->getShaderVersion(), isSeparable(), infoLog))
3105 {
3106 return false;
3107 }
3108 }
3109 previousShaderType = currentShader->getType();
3110 }
3111
3112 // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
3113 // Need to move logic of validating builtin varyings inside the for-loop above.
3114 // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
3115 // can be redeclared in Geometry or Tessellation shaders as well.
3116 Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
3117 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
3118 if (vertexShader && fragmentShader &&
3119 !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
3120 fragmentShader->getInputVaryings(), vertexShader->getType(),
3121 fragmentShader->getType(), vertexShader->getShaderVersion(),
3122 fragmentShader->getShaderVersion(), infoLog))
3123 {
3124 return false;
3125 }
3126
3127 return true;
3128 }
3129
linkUniforms(const Context * context,std::vector<UnusedUniform> * unusedUniformsOutOrNull,GLuint * combinedImageUniformsOut,InfoLog & infoLog)3130 bool Program::linkUniforms(const Context *context,
3131 std::vector<UnusedUniform> *unusedUniformsOutOrNull,
3132 GLuint *combinedImageUniformsOut,
3133 InfoLog &infoLog)
3134 {
3135 // Initialize executable shader map.
3136 ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
3137 for (Shader *shader : mState.mAttachedShaders)
3138 {
3139 if (shader)
3140 {
3141 shaderUniforms[shader->getType()] = shader->getUniforms();
3142 }
3143 }
3144
3145 if (!mState.mExecutable->linkUniforms(context, shaderUniforms, infoLog,
3146 mState.mUniformLocationBindings, combinedImageUniformsOut,
3147 unusedUniformsOutOrNull, &mState.mUniformLocations))
3148 {
3149 return false;
3150 }
3151
3152 if (context->getClientVersion() >= Version(3, 1))
3153 {
3154 GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size());
3155
3156 if (locationSize > context->getCaps().maxUniformLocations)
3157 {
3158 infoLog << "Exceeded maximum uniform location size";
3159 return false;
3160 }
3161 }
3162
3163 return true;
3164 }
3165
3166 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3167 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3168 {
3169 const Caps &caps = context->getCaps();
3170 const Limitations &limitations = context->getLimitations();
3171 bool webglCompatibility = context->isWebGL();
3172 int shaderVersion = -1;
3173 unsigned int usedLocations = 0;
3174
3175 Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
3176
3177 if (!vertexShader)
3178 {
3179 // No vertex shader, so no attributes, so nothing to do
3180 return true;
3181 }
3182
3183 shaderVersion = vertexShader->getShaderVersion();
3184 if (shaderVersion >= 300)
3185 {
3186 // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
3187 // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
3188 // aliasing checks.
3189 mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes();
3190 }
3191 else
3192 {
3193 // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3194 mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes();
3195 }
3196
3197 GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
3198 std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
3199
3200 // Assign locations to attributes that have a binding location and check for attribute aliasing.
3201 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3202 {
3203 // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3204 // structures, so we don't need to worry about adjusting their names or generating entries
3205 // for each member/element (unlike uniforms for example).
3206 ASSERT(!attribute.isArray() && !attribute.isStruct());
3207
3208 int bindingLocation = mAttributeBindings.getBinding(attribute);
3209 if (attribute.location == -1 && bindingLocation != -1)
3210 {
3211 attribute.location = bindingLocation;
3212 }
3213
3214 if (attribute.location != -1)
3215 {
3216 // Location is set by glBindAttribLocation or by location layout qualifier
3217 const int regs = VariableRegisterCount(attribute.type);
3218
3219 if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3220 {
3221 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3222 << " is too big to fit";
3223
3224 return false;
3225 }
3226
3227 for (int reg = 0; reg < regs; reg++)
3228 {
3229 const int regLocation = attribute.location + reg;
3230 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3231
3232 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3233 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3234 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3235 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3236 if (linkedAttribute)
3237 {
3238 if (shaderVersion >= 300 || webglCompatibility ||
3239 limitations.noVertexAttributeAliasing)
3240 {
3241 infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3242 << linkedAttribute->name << "' at location " << regLocation;
3243 return false;
3244 }
3245 }
3246 else
3247 {
3248 usedAttribMap[regLocation] = &attribute;
3249 }
3250
3251 usedLocations |= 1 << regLocation;
3252 }
3253 }
3254 }
3255
3256 // Assign locations to attributes that don't have a binding location.
3257 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3258 {
3259 // Not set by glBindAttribLocation or by location layout qualifier
3260 if (attribute.location == -1)
3261 {
3262 int regs = VariableRegisterCount(attribute.type);
3263 int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3264
3265 if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3266 {
3267 infoLog << "Too many attributes (" << attribute.name << ")";
3268 return false;
3269 }
3270
3271 attribute.location = availableIndex;
3272 }
3273 }
3274
3275 ASSERT(mState.mExecutable->mAttributesTypeMask.none());
3276 ASSERT(mState.mExecutable->mAttributesMask.none());
3277
3278 // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3279 // shader versions we're only processing active attributes to begin with.
3280 if (shaderVersion >= 300)
3281 {
3282 for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
3283 attributeIter != mState.mExecutable->getProgramInputs().end();)
3284 {
3285 if (attributeIter->active)
3286 {
3287 ++attributeIter;
3288 }
3289 else
3290 {
3291 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
3292 }
3293 }
3294 }
3295
3296 for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
3297 {
3298 ASSERT(attribute.active);
3299 ASSERT(attribute.location != -1);
3300 unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3301
3302 unsigned int location = static_cast<unsigned int>(attribute.location);
3303 for (unsigned int r = 0; r < regs; r++)
3304 {
3305 // Built-in active program inputs don't have a bound attribute.
3306 if (!attribute.isBuiltIn())
3307 {
3308 mState.mExecutable->mActiveAttribLocationsMask.set(location);
3309 mState.mExecutable->mMaxActiveAttribLocation =
3310 std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
3311
3312 ComponentType componentType =
3313 GLenumToComponentType(VariableComponentType(attribute.type));
3314
3315 SetComponentTypeMask(componentType, location,
3316 &mState.mExecutable->mAttributesTypeMask);
3317 mState.mExecutable->mAttributesMask.set(location);
3318
3319 location++;
3320 }
3321 }
3322 }
3323
3324 return true;
3325 }
3326
setUniformValuesFromBindingQualifiers()3327 void Program::setUniformValuesFromBindingQualifiers()
3328 {
3329 for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
3330 {
3331 const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
3332 if (samplerUniform.binding != -1)
3333 {
3334 UniformLocation location = getUniformLocation(samplerUniform.name);
3335 ASSERT(location.value != -1);
3336 std::vector<GLint> boundTextureUnits;
3337 for (unsigned int elementIndex = 0;
3338 elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
3339 {
3340 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
3341 }
3342
3343 // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
3344 // We know it's safe not to notify the Context because this is only called after link.
3345 setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
3346 boundTextureUnits.data());
3347 }
3348 }
3349 }
3350
initInterfaceBlockBindings()3351 void Program::initInterfaceBlockBindings()
3352 {
3353 // Set initial bindings from shader.
3354 for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
3355 blockIndex++)
3356 {
3357 InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
3358 bindUniformBlock({blockIndex}, uniformBlock.binding);
3359 }
3360 }
3361
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)3362 void Program::updateSamplerUniform(Context *context,
3363 const VariableLocation &locationInfo,
3364 GLsizei clampedCount,
3365 const GLint *v)
3366 {
3367 ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
3368 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
3369 SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
3370 std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
3371
3372 if (locationInfo.arrayIndex >= boundTextureUnits.size())
3373 {
3374 return;
3375 }
3376 GLsizei safeUniformCount = std::min(
3377 clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
3378
3379 // Update the sampler uniforms.
3380 for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
3381 {
3382 GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
3383 GLint newTextureUnit = v[arrayIndex];
3384
3385 if (oldTextureUnit == newTextureUnit)
3386 {
3387 continue;
3388 }
3389
3390 boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
3391
3392 // Update the reference counts.
3393 uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
3394 uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit];
3395 ASSERT(oldRefCount > 0);
3396 ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
3397 oldRefCount--;
3398 newRefCount++;
3399
3400 // Check for binding type change.
3401 TextureType &newSamplerType = mState.mExecutable->mActiveSamplerTypes[newTextureUnit];
3402 TextureType &oldSamplerType = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit];
3403 SamplerFormat &newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit];
3404 SamplerFormat &oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit];
3405
3406 if (newRefCount == 1)
3407 {
3408 newSamplerType = samplerBinding.textureType;
3409 newSamplerFormat = samplerBinding.format;
3410 mState.mExecutable->mActiveSamplersMask.set(newTextureUnit);
3411 mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] =
3412 mState.mExecutable->getUniforms()[locationInfo.index].activeShaders();
3413 }
3414 else
3415 {
3416 if (newSamplerType != samplerBinding.textureType)
3417 {
3418 // Conflict detected. Ensure we reset it properly.
3419 newSamplerType = TextureType::InvalidEnum;
3420 }
3421 if (newSamplerFormat != samplerBinding.format)
3422 {
3423 newSamplerFormat = SamplerFormat::InvalidEnum;
3424 }
3425 }
3426
3427 // Unset previously active sampler.
3428 if (oldRefCount == 0)
3429 {
3430 oldSamplerType = TextureType::InvalidEnum;
3431 oldSamplerFormat = SamplerFormat::InvalidEnum;
3432 mState.mExecutable->mActiveSamplersMask.reset(oldTextureUnit);
3433 }
3434 else
3435 {
3436 if (oldSamplerType == TextureType::InvalidEnum ||
3437 oldSamplerFormat == SamplerFormat::InvalidEnum)
3438 {
3439 // Previous conflict. Check if this new change fixed the conflict.
3440 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
3441 }
3442 }
3443
3444 // Update the observing PPO's executable, if any.
3445 // Do this before any of the Context work, since that uses the current ProgramExecutable,
3446 // which will be the PPO's if this Program is bound to it, rather than this Program's.
3447 if (isSeparable())
3448 {
3449 onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
3450 }
3451
3452 // Notify context.
3453 if (context)
3454 {
3455 context->onSamplerUniformChange(newTextureUnit);
3456 context->onSamplerUniformChange(oldTextureUnit);
3457 }
3458 }
3459
3460 // Invalidate the validation cache.
3461 getExecutable().resetCachedValidateSamplersResult();
3462 // Inform any PPOs this Program may be bound to.
3463 onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
3464 }
3465
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)3466 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
3467 {
3468 mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
3469 mExecutable->mSamplerBindings);
3470 }
3471
3472 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)3473 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
3474 GLsizei count,
3475 int vectorSize,
3476 const T *v)
3477 {
3478 if (count == 1)
3479 return 1;
3480
3481 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
3482
3483 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
3484 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
3485 unsigned int remainingElements =
3486 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
3487 GLsizei maxElementCount =
3488 static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
3489
3490 if (count * vectorSize > maxElementCount)
3491 {
3492 return maxElementCount / vectorSize;
3493 }
3494
3495 return count;
3496 }
3497
3498 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)3499 GLsizei Program::clampMatrixUniformCount(UniformLocation location,
3500 GLsizei count,
3501 GLboolean transpose,
3502 const T *v)
3503 {
3504 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
3505
3506 if (!transpose)
3507 {
3508 return clampUniformCount(locationInfo, count, cols * rows, v);
3509 }
3510
3511 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
3512
3513 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
3514 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
3515 unsigned int remainingElements =
3516 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
3517 return std::min(count, static_cast<GLsizei>(remainingElements));
3518 }
3519
3520 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
3521 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
3522 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const3523 void Program::getUniformInternal(const Context *context,
3524 DestT *dataOut,
3525 UniformLocation location,
3526 GLenum nativeType,
3527 int components) const
3528 {
3529 switch (nativeType)
3530 {
3531 case GL_BOOL:
3532 {
3533 GLint tempValue[16] = {0};
3534 mProgram->getUniformiv(context, location.value, tempValue);
3535 UniformStateQueryCastLoop<GLboolean>(
3536 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3537 break;
3538 }
3539 case GL_INT:
3540 {
3541 GLint tempValue[16] = {0};
3542 mProgram->getUniformiv(context, location.value, tempValue);
3543 UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3544 components);
3545 break;
3546 }
3547 case GL_UNSIGNED_INT:
3548 {
3549 GLuint tempValue[16] = {0};
3550 mProgram->getUniformuiv(context, location.value, tempValue);
3551 UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3552 components);
3553 break;
3554 }
3555 case GL_FLOAT:
3556 {
3557 GLfloat tempValue[16] = {0};
3558 mProgram->getUniformfv(context, location.value, tempValue);
3559 UniformStateQueryCastLoop<GLfloat>(
3560 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3561 break;
3562 }
3563 default:
3564 UNREACHABLE();
3565 break;
3566 }
3567 }
3568
syncState(const Context * context)3569 angle::Result Program::syncState(const Context *context)
3570 {
3571 if (mDirtyBits.any())
3572 {
3573 ASSERT(!mLinkingState);
3574 ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
3575 mDirtyBits.reset();
3576 }
3577
3578 return angle::Result::Continue;
3579 }
3580
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const3581 angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
3582 {
3583 BinaryOutputStream stream;
3584
3585 stream.writeBytes(reinterpret_cast<const unsigned char *>(angle::GetANGLECommitHash()),
3586 angle::GetANGLECommitHashSize());
3587
3588 // nullptr context is supported when computing binary length.
3589 if (context)
3590 {
3591 stream.writeInt(context->getClientVersion().major);
3592 stream.writeInt(context->getClientVersion().minor);
3593 }
3594 else
3595 {
3596 stream.writeInt(2);
3597 stream.writeInt(0);
3598 }
3599
3600 // Must be before mExecutable->save(), since it uses the value.
3601 stream.writeBool(mState.mSeparable);
3602
3603 mState.mExecutable->save(mState.mSeparable, &stream);
3604
3605 const auto &computeLocalSize = mState.getComputeShaderLocalSize();
3606
3607 stream.writeInt(computeLocalSize[0]);
3608 stream.writeInt(computeLocalSize[1]);
3609 stream.writeInt(computeLocalSize[2]);
3610
3611 stream.writeInt(mState.mNumViews);
3612 stream.writeInt(mState.mSpecConstUsageBits.bits());
3613
3614 stream.writeInt(mState.getUniformLocations().size());
3615 for (const auto &variable : mState.getUniformLocations())
3616 {
3617 stream.writeInt(variable.arrayIndex);
3618 stream.writeIntOrNegOne(variable.index);
3619 stream.writeBool(variable.ignored);
3620 }
3621
3622 stream.writeInt(mState.getBufferVariables().size());
3623 for (const BufferVariable &bufferVariable : mState.getBufferVariables())
3624 {
3625 WriteBufferVariable(&stream, bufferVariable);
3626 }
3627
3628 // Warn the app layer if saving a binary with unsupported transform feedback.
3629 if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
3630 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
3631 {
3632 WARN() << "Saving program binary with transform feedback, which is not supported on this "
3633 "driver.";
3634 }
3635
3636 if (context->getShareGroup()->getFrameCaptureShared()->enabled())
3637 {
3638 // Serialize the source for each stage for re-use during capture
3639 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
3640 {
3641 gl::Shader *shader = getAttachedShader(shaderType);
3642 if (shader)
3643 {
3644 stream.writeString(shader->getSourceString());
3645 }
3646 else
3647 {
3648 // If we don't have an attached shader, which would occur if this program was
3649 // created via glProgramBinary, pull from our cached copy
3650 const angle::ProgramSources &cachedLinkedSources =
3651 context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id());
3652 const std::string &cachedSourceString = cachedLinkedSources[shaderType];
3653 ASSERT(!cachedSourceString.empty());
3654 stream.writeString(cachedSourceString.c_str());
3655 }
3656 }
3657 }
3658
3659 mProgram->save(context, &stream);
3660
3661 ASSERT(binaryOut);
3662 if (!binaryOut->resize(stream.length()))
3663 {
3664 WARN() << "Failed to allocate enough memory to serialize a program. (" << stream.length()
3665 << " bytes )";
3666 return angle::Result::Incomplete;
3667 }
3668 memcpy(binaryOut->data(), stream.data(), stream.length());
3669 return angle::Result::Continue;
3670 }
3671
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)3672 angle::Result Program::deserialize(const Context *context,
3673 BinaryInputStream &stream,
3674 InfoLog &infoLog)
3675 {
3676 std::vector<uint8_t> commitString(angle::GetANGLECommitHashSize(), 0);
3677 stream.readBytes(commitString.data(), commitString.size());
3678 if (memcmp(commitString.data(), angle::GetANGLECommitHash(), commitString.size()) != 0)
3679 {
3680 infoLog << "Invalid program binary version.";
3681 return angle::Result::Stop;
3682 }
3683
3684 int majorVersion = stream.readInt<int>();
3685 int minorVersion = stream.readInt<int>();
3686 if (majorVersion != context->getClientMajorVersion() ||
3687 minorVersion != context->getClientMinorVersion())
3688 {
3689 infoLog << "Cannot load program binaries across different ES context versions.";
3690 return angle::Result::Stop;
3691 }
3692
3693 // Must be before mExecutable->load(), since it uses the value.
3694 mState.mSeparable = stream.readBool();
3695
3696 mState.mExecutable->load(mState.mSeparable, &stream);
3697
3698 mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
3699 mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
3700 mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
3701
3702 mState.mNumViews = stream.readInt<int>();
3703
3704 static_assert(sizeof(mState.mSpecConstUsageBits.bits()) == sizeof(uint32_t));
3705 mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
3706
3707 const size_t uniformIndexCount = stream.readInt<size_t>();
3708 ASSERT(mState.mUniformLocations.empty());
3709 for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex)
3710 {
3711 VariableLocation variable;
3712 stream.readInt(&variable.arrayIndex);
3713 stream.readInt(&variable.index);
3714 stream.readBool(&variable.ignored);
3715
3716 mState.mUniformLocations.push_back(variable);
3717 }
3718
3719 size_t bufferVariableCount = stream.readInt<size_t>();
3720 ASSERT(mState.mBufferVariables.empty());
3721 for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
3722 {
3723 BufferVariable bufferVariable;
3724 LoadBufferVariable(&stream, &bufferVariable);
3725 mState.mBufferVariables.push_back(bufferVariable);
3726 }
3727
3728 static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
3729 "Too many shader types");
3730
3731 // Reject programs that use transform feedback varyings if the hardware cannot support them.
3732 if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
3733 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
3734 {
3735 infoLog << "Current driver does not support transform feedback in binary programs.";
3736 return angle::Result::Stop;
3737 }
3738
3739 if (!mState.mAttachedShaders[ShaderType::Compute])
3740 {
3741 mState.mExecutable->updateTransformFeedbackStrides();
3742 }
3743
3744 postResolveLink(context);
3745 mState.mExecutable->updateCanDrawWith();
3746
3747 if (context->getShareGroup()->getFrameCaptureShared()->enabled())
3748 {
3749 // Extract the source for each stage from the program binary
3750 angle::ProgramSources sources;
3751
3752 for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
3753 {
3754 std::string shaderSource = stream.readString();
3755 ASSERT(shaderSource.length() > 0);
3756 sources[shaderType] = std::move(shaderSource);
3757 }
3758
3759 // Store it for use during mid-execution capture
3760 context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(),
3761 std::move(sources));
3762 }
3763
3764 return angle::Result::Continue;
3765 }
3766
postResolveLink(const gl::Context * context)3767 void Program::postResolveLink(const gl::Context *context)
3768 {
3769 mState.updateActiveSamplers();
3770 mState.mExecutable->mActiveImageShaderBits.fill({});
3771 mState.mExecutable->updateActiveImages(getExecutable());
3772
3773 setUniformValuesFromBindingQualifiers();
3774
3775 if (context->getExtensions().multiDrawANGLE)
3776 {
3777 mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value;
3778 }
3779
3780 if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE)
3781 {
3782 mState.mBaseVertexLocation = getUniformLocation("gl_BaseVertex").value;
3783 mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value;
3784 }
3785 }
3786 } // namespace gl
3787