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