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