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