1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // Program.cpp: Implements the gl::Program class. Implements GL program objects
8 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
10 #include "libANGLE/Program.h"
11
12 #include <algorithm>
13 #include <utility>
14
15 #include "common/angle_version.h"
16 #include "common/bitset_utils.h"
17 #include "common/debug.h"
18 #include "common/platform.h"
19 #include "common/string_utils.h"
20 #include "common/utilities.h"
21 #include "compiler/translator/blocklayout.h"
22 #include "libANGLE/Context.h"
23 #include "libANGLE/ErrorStrings.h"
24 #include "libANGLE/MemoryProgramCache.h"
25 #include "libANGLE/ProgramLinkedResources.h"
26 #include "libANGLE/ResourceManager.h"
27 #include "libANGLE/Uniform.h"
28 #include "libANGLE/VaryingPacking.h"
29 #include "libANGLE/Version.h"
30 #include "libANGLE/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
GetInterfaceBlockLimitName(ShaderType shaderType,sh::BlockType blockType)235 std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
236 {
237 std::ostringstream stream;
238 stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
239
240 switch (blockType)
241 {
242 case sh::BlockType::BLOCK_UNIFORM:
243 stream << "UNIFORM_BUFFERS";
244 break;
245 case sh::BlockType::BLOCK_BUFFER:
246 stream << "SHADER_STORAGE_BLOCKS";
247 break;
248 default:
249 UNREACHABLE();
250 return "";
251 }
252
253 if (shaderType == ShaderType::Geometry)
254 {
255 stream << "_EXT";
256 }
257
258 return stream.str();
259 }
260
GetInterfaceBlockTypeString(sh::BlockType blockType)261 const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
262 {
263 switch (blockType)
264 {
265 case sh::BlockType::BLOCK_UNIFORM:
266 return "uniform block";
267 case sh::BlockType::BLOCK_BUFFER:
268 return "shader storage block";
269 default:
270 UNREACHABLE();
271 return "";
272 }
273 }
274
LogInterfaceBlocksExceedLimit(InfoLog & infoLog,ShaderType shaderType,sh::BlockType blockType,GLuint limit)275 void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
276 ShaderType shaderType,
277 sh::BlockType blockType,
278 GLuint limit)
279 {
280 infoLog << GetShaderTypeString(shaderType) << " shader "
281 << GetInterfaceBlockTypeString(blockType) << " count exceeds "
282 << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
283 }
284
ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,sh::BlockType blockType,GLuint * combinedInterfaceBlocksCount,InfoLog & infoLog)285 bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
286 const std::vector<sh::InterfaceBlock> &interfaceBlocks,
287 ShaderType shaderType,
288 sh::BlockType blockType,
289 GLuint *combinedInterfaceBlocksCount,
290 InfoLog &infoLog)
291 {
292 GLuint blockCount = 0;
293 for (const sh::InterfaceBlock &block : interfaceBlocks)
294 {
295 if (IsActiveInterfaceBlock(block))
296 {
297 blockCount += std::max(block.arraySize, 1u);
298 if (blockCount > maxInterfaceBlocks)
299 {
300 LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
301 return false;
302 }
303 }
304 }
305
306 // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
307 // If a uniform block is used by multiple shader stages, each such use counts separately
308 // against this combined limit.
309 // [OpenGL ES 3.1] Chapter 7.8 Page 111:
310 // If a shader storage block in a program is referenced by multiple shaders, each such
311 // reference counts separately against this combined limit.
312 if (combinedInterfaceBlocksCount)
313 {
314 *combinedInterfaceBlocksCount += blockCount;
315 }
316
317 return true;
318 }
319
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)320 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
321 {
322 std::vector<unsigned int> subscripts;
323 std::string baseName = ParseResourceName(name, &subscripts);
324
325 unsigned int numBlocks = static_cast<unsigned int>(list.size());
326 for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
327 {
328 const auto &block = list[blockIndex];
329 if (block.name == baseName)
330 {
331 const bool arrayElementZero =
332 (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
333 const bool arrayElementMatches =
334 (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
335 if (arrayElementMatches || arrayElementZero)
336 {
337 return blockIndex;
338 }
339 }
340 }
341
342 return GL_INVALID_INDEX;
343 }
344
GetInterfaceBlockName(const UniformBlockIndex index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)345 void GetInterfaceBlockName(const UniformBlockIndex index,
346 const std::vector<InterfaceBlock> &list,
347 GLsizei bufSize,
348 GLsizei *length,
349 GLchar *name)
350 {
351 ASSERT(index.value < list.size());
352
353 const auto &block = list[index.value];
354
355 if (bufSize > 0)
356 {
357 std::string blockName = block.name;
358
359 if (block.isArray)
360 {
361 blockName += ArrayString(block.arrayElement);
362 }
363 CopyStringToBuffer(name, blockName, bufSize, length);
364 }
365 }
366
InitUniformBlockLinker(const ProgramState & state,UniformBlockLinker * blockLinker)367 void InitUniformBlockLinker(const ProgramState &state, UniformBlockLinker *blockLinker)
368 {
369 for (ShaderType shaderType : AllShaderTypes())
370 {
371 Shader *shader = state.getAttachedShader(shaderType);
372 if (shader)
373 {
374 blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks());
375 }
376 }
377 }
378
InitShaderStorageBlockLinker(const ProgramState & state,ShaderStorageBlockLinker * blockLinker)379 void InitShaderStorageBlockLinker(const ProgramState &state, ShaderStorageBlockLinker *blockLinker)
380 {
381 for (ShaderType shaderType : AllShaderTypes())
382 {
383 Shader *shader = state.getAttachedShader(shaderType);
384 if (shader != nullptr)
385 {
386 blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks());
387 }
388 }
389 }
390 } // anonymous namespace
391
GetLinkMismatchErrorString(LinkMismatchError linkError)392 const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
393 {
394 switch (linkError)
395 {
396 case LinkMismatchError::TYPE_MISMATCH:
397 return "Type";
398 case LinkMismatchError::ARRAYNESS_MISMATCH:
399 return "Array-ness";
400 case LinkMismatchError::ARRAY_SIZE_MISMATCH:
401 return "Array size";
402 case LinkMismatchError::PRECISION_MISMATCH:
403 return "Precision";
404 case LinkMismatchError::STRUCT_NAME_MISMATCH:
405 return "Structure name";
406 case LinkMismatchError::FIELD_NUMBER_MISMATCH:
407 return "Field number";
408 case LinkMismatchError::FIELD_NAME_MISMATCH:
409 return "Field name";
410
411 case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
412 return "Interpolation type";
413 case LinkMismatchError::INVARIANCE_MISMATCH:
414 return "Invariance";
415
416 case LinkMismatchError::BINDING_MISMATCH:
417 return "Binding layout qualifier";
418 case LinkMismatchError::LOCATION_MISMATCH:
419 return "Location layout qualifier";
420 case LinkMismatchError::OFFSET_MISMATCH:
421 return "Offset layout qualifier";
422 case LinkMismatchError::INSTANCE_NAME_MISMATCH:
423 return "Instance name qualifier";
424 case LinkMismatchError::FORMAT_MISMATCH:
425 return "Format qualifier";
426
427 case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
428 return "Layout qualifier";
429 case LinkMismatchError::MATRIX_PACKING_MISMATCH:
430 return "Matrix Packing";
431
432 case LinkMismatchError::FIELD_LOCATION_MISMATCH:
433 return "Field location";
434 case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
435 return "Field structure name";
436 default:
437 UNREACHABLE();
438 return "";
439 }
440 }
441
LinkValidateInterfaceBlockFields(const sh::ShaderVariable & blockField1,const sh::ShaderVariable & blockField2,bool webglCompatibility,std::string * mismatchedBlockFieldName)442 LinkMismatchError LinkValidateInterfaceBlockFields(const sh::ShaderVariable &blockField1,
443 const sh::ShaderVariable &blockField2,
444 bool webglCompatibility,
445 std::string *mismatchedBlockFieldName)
446 {
447 if (blockField1.name != blockField2.name)
448 {
449 return LinkMismatchError::FIELD_NAME_MISMATCH;
450 }
451
452 // If webgl, validate precision of UBO fields, otherwise don't. See Khronos bug 10287.
453 LinkMismatchError linkError = LinkValidateProgramVariables(
454 blockField1, blockField2, webglCompatibility, false, false, mismatchedBlockFieldName);
455 if (linkError != LinkMismatchError::NO_MISMATCH)
456 {
457 AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
458 return linkError;
459 }
460
461 if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout)
462 {
463 AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
464 return LinkMismatchError::MATRIX_PACKING_MISMATCH;
465 }
466
467 return LinkMismatchError::NO_MISMATCH;
468 }
469
AreMatchingInterfaceBlocks(const sh::InterfaceBlock & interfaceBlock1,const sh::InterfaceBlock & interfaceBlock2,bool webglCompatibility,std::string * mismatchedBlockFieldName)470 LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1,
471 const sh::InterfaceBlock &interfaceBlock2,
472 bool webglCompatibility,
473 std::string *mismatchedBlockFieldName)
474 {
475 // validate blocks for the same member types
476 if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size())
477 {
478 return LinkMismatchError::FIELD_NUMBER_MISMATCH;
479 }
480 if (interfaceBlock1.arraySize != interfaceBlock2.arraySize)
481 {
482 return LinkMismatchError::ARRAY_SIZE_MISMATCH;
483 }
484 if (interfaceBlock1.layout != interfaceBlock2.layout ||
485 interfaceBlock1.binding != interfaceBlock2.binding)
486 {
487 return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH;
488 }
489 if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty())
490 {
491 return LinkMismatchError::INSTANCE_NAME_MISMATCH;
492 }
493 const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size());
494 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
495 {
496 const sh::ShaderVariable &member1 = interfaceBlock1.fields[blockMemberIndex];
497 const sh::ShaderVariable &member2 = interfaceBlock2.fields[blockMemberIndex];
498
499 LinkMismatchError linkError = LinkValidateInterfaceBlockFields(
500 member1, member2, webglCompatibility, mismatchedBlockFieldName);
501 if (linkError != LinkMismatchError::NO_MISMATCH)
502 {
503 return linkError;
504 }
505 }
506 return LinkMismatchError::NO_MISMATCH;
507 }
508
509 using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>;
510 using InterfaceBlockMap = std::map<std::string, ShaderInterfaceBlock>;
511
InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * linkedInterfaceBlocks)512 void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
513 ShaderType shaderType,
514 InterfaceBlockMap *linkedInterfaceBlocks)
515 {
516 ASSERT(linkedInterfaceBlocks);
517
518 for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
519 {
520 (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
521 }
522 }
523
ValidateGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocksToLink,ShaderType shaderType,bool webglCompatibility,InterfaceBlockMap * linkedBlocks,InfoLog & infoLog)524 bool ValidateGraphicsInterfaceBlocksPerShader(
525 const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
526 ShaderType shaderType,
527 bool webglCompatibility,
528 InterfaceBlockMap *linkedBlocks,
529 InfoLog &infoLog)
530 {
531 ASSERT(linkedBlocks);
532
533 for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
534 {
535 const auto &entry = linkedBlocks->find(block.name);
536 if (entry != linkedBlocks->end())
537 {
538 const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
539 std::string mismatchedStructFieldName;
540 LinkMismatchError linkError = AreMatchingInterfaceBlocks(
541 block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
542 if (linkError != LinkMismatchError::NO_MISMATCH)
543 {
544 LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
545 linkError, mismatchedStructFieldName, entry->second.first,
546 shaderType);
547 return false;
548 }
549 }
550 else
551 {
552 (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
553 }
554 }
555
556 return true;
557 }
558
LogAmbiguousFieldLinkMismatch(InfoLog & infoLog,const std::string & blockName1,const std::string & blockName2,const std::string & fieldName,ShaderType shaderType1,ShaderType shaderType2)559 void LogAmbiguousFieldLinkMismatch(InfoLog &infoLog,
560 const std::string &blockName1,
561 const std::string &blockName2,
562 const std::string &fieldName,
563 ShaderType shaderType1,
564 ShaderType shaderType2)
565 {
566 infoLog << "Ambiguous field '" << fieldName << "' in blocks '" << blockName1 << "' ("
567 << GetShaderTypeString(shaderType1) << " shader) and '" << blockName2 << "' ("
568 << GetShaderTypeString(shaderType2) << " shader) which don't have instance names.";
569 }
570
ValidateInstancelessGraphicsInterfaceBlocksPerShader(const std::vector<sh::InterfaceBlock> & interfaceBlocks,ShaderType shaderType,InterfaceBlockMap * instancelessBlocksFields,InfoLog & infoLog)571 bool ValidateInstancelessGraphicsInterfaceBlocksPerShader(
572 const std::vector<sh::InterfaceBlock> &interfaceBlocks,
573 ShaderType shaderType,
574 InterfaceBlockMap *instancelessBlocksFields,
575 InfoLog &infoLog)
576 {
577 ASSERT(instancelessBlocksFields);
578
579 for (const sh::InterfaceBlock &block : interfaceBlocks)
580 {
581 if (!block.instanceName.empty())
582 {
583 continue;
584 }
585
586 for (const sh::ShaderVariable &field : block.fields)
587 {
588 const auto &entry = instancelessBlocksFields->find(field.name);
589 if (entry != instancelessBlocksFields->end())
590 {
591 const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
592 if (block.name != linkedBlock.name)
593 {
594 LogAmbiguousFieldLinkMismatch(infoLog, block.name, linkedBlock.name, field.name,
595 entry->second.first, shaderType);
596 return false;
597 }
598 }
599 else
600 {
601 (*instancelessBlocksFields)[field.name] = std::make_pair(shaderType, &block);
602 }
603 }
604 }
605
606 return true;
607 }
608
ValidateInterfaceBlocksMatch(GLuint numShadersHasInterfaceBlocks,const ShaderMap<const std::vector<sh::InterfaceBlock> * > & shaderInterfaceBlocks,InfoLog & infoLog,bool webglCompatibility,InterfaceBlockMap * instancelessInterfaceBlocksFields)609 bool ValidateInterfaceBlocksMatch(
610 GLuint numShadersHasInterfaceBlocks,
611 const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
612 InfoLog &infoLog,
613 bool webglCompatibility,
614 InterfaceBlockMap *instancelessInterfaceBlocksFields)
615 {
616 for (ShaderType shaderType : kAllGraphicsShaderTypes)
617 {
618 // Validate that instanceless blocks of different names don't have fields of the same name.
619 if (shaderInterfaceBlocks[shaderType] &&
620 !ValidateInstancelessGraphicsInterfaceBlocksPerShader(
621 *shaderInterfaceBlocks[shaderType], shaderType, instancelessInterfaceBlocksFields,
622 infoLog))
623 {
624 return false;
625 }
626 }
627
628 if (numShadersHasInterfaceBlocks < 2u)
629 {
630 return true;
631 }
632
633 ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]);
634
635 // Check that interface blocks defined in the graphics shaders are identical
636
637 InterfaceBlockMap linkedInterfaceBlocks;
638
639 bool interfaceBlockMapInitialized = false;
640 for (ShaderType shaderType : kAllGraphicsShaderTypes)
641 {
642 if (!shaderInterfaceBlocks[shaderType])
643 {
644 continue;
645 }
646
647 if (!interfaceBlockMapInitialized)
648 {
649 InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
650 &linkedInterfaceBlocks);
651 interfaceBlockMapInitialized = true;
652 }
653 else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType],
654 shaderType, webglCompatibility,
655 &linkedInterfaceBlocks, infoLog))
656 {
657 return false;
658 }
659 }
660
661 return true;
662 }
663
UpdateInterfaceVariable(std::vector<sh::ShaderVariable> * block,const sh::ShaderVariable & var)664 void UpdateInterfaceVariable(std::vector<sh::ShaderVariable> *block, const sh::ShaderVariable &var)
665 {
666 if (!var.isStruct())
667 {
668 block->emplace_back(var);
669 block->back().resetEffectiveLocation();
670 }
671
672 for (const sh::ShaderVariable &field : var.fields)
673 {
674 ASSERT(!var.name.empty() || var.isShaderIOBlock);
675
676 // Shader I/O block naming is similar to UBOs and SSBOs:
677 //
678 // in Block
679 // {
680 // type field; // produces "field"
681 // };
682 //
683 // in Block2
684 // {
685 // type field; // produces "Block2.field"
686 // } block2;
687 //
688 const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
689 const std::string prefix = var.name.empty() ? "" : baseName + ".";
690
691 if (!field.isStruct())
692 {
693 sh::ShaderVariable fieldCopy = field;
694 fieldCopy.updateEffectiveLocation(var);
695 fieldCopy.name = prefix + field.name;
696 block->emplace_back(fieldCopy);
697 }
698
699 for (const sh::ShaderVariable &nested : field.fields)
700 {
701 sh::ShaderVariable nestedCopy = nested;
702 nestedCopy.updateEffectiveLocation(field);
703 nestedCopy.name = prefix + field.name + "." + nested.name;
704 block->emplace_back(nestedCopy);
705 }
706 }
707 }
708
WriteShaderVariableBuffer(BinaryOutputStream * stream,const ShaderVariableBuffer & var)709 void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
710 {
711 stream->writeInt(var.binding);
712 stream->writeInt(var.dataSize);
713
714 for (ShaderType shaderType : AllShaderTypes())
715 {
716 stream->writeBool(var.isActive(shaderType));
717 }
718
719 stream->writeInt(var.memberIndexes.size());
720 for (unsigned int memberCounterIndex : var.memberIndexes)
721 {
722 stream->writeInt(memberCounterIndex);
723 }
724 }
725
LoadShaderVariableBuffer(BinaryInputStream * stream,ShaderVariableBuffer * var)726 void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
727 {
728 var->binding = stream->readInt<int>();
729 var->dataSize = stream->readInt<unsigned int>();
730
731 for (ShaderType shaderType : AllShaderTypes())
732 {
733 var->setActive(shaderType, stream->readBool());
734 }
735
736 size_t numMembers = stream->readInt<size_t>();
737 for (size_t blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
738 {
739 var->memberIndexes.push_back(stream->readInt<unsigned int>());
740 }
741 }
742
WriteBufferVariable(BinaryOutputStream * stream,const BufferVariable & var)743 void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
744 {
745 WriteShaderVar(stream, var);
746
747 stream->writeInt(var.bufferIndex);
748 WriteBlockMemberInfo(stream, var.blockInfo);
749 stream->writeInt(var.topLevelArraySize);
750
751 for (ShaderType shaderType : AllShaderTypes())
752 {
753 stream->writeBool(var.isActive(shaderType));
754 }
755 }
756
LoadBufferVariable(BinaryInputStream * stream,BufferVariable * var)757 void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
758 {
759 LoadShaderVar(stream, var);
760
761 var->bufferIndex = stream->readInt<int>();
762 LoadBlockMemberInfo(stream, &var->blockInfo);
763 var->topLevelArraySize = stream->readInt<int>();
764
765 for (ShaderType shaderType : AllShaderTypes())
766 {
767 var->setActive(shaderType, stream->readBool());
768 }
769 }
770
WriteInterfaceBlock(BinaryOutputStream * stream,const InterfaceBlock & block)771 void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
772 {
773 stream->writeString(block.name);
774 stream->writeString(block.mappedName);
775 stream->writeBool(block.isArray);
776 stream->writeInt(block.arrayElement);
777
778 WriteShaderVariableBuffer(stream, block);
779 }
780
LoadInterfaceBlock(BinaryInputStream * stream,InterfaceBlock * block)781 void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
782 {
783 block->name = stream->readString();
784 block->mappedName = stream->readString();
785 block->isArray = stream->readBool();
786 block->arrayElement = stream->readInt<unsigned int>();
787
788 LoadShaderVariableBuffer(stream, block);
789 }
790
791 // Saves the linking context for later use in resolveLink().
792 struct Program::LinkingState
793 {
794 std::shared_ptr<ProgramExecutable> linkedExecutable;
795 ProgramLinkedResources resources;
796 egl::BlobCache::Key programHash;
797 std::unique_ptr<rx::LinkEvent> linkEvent;
798 bool linkingFromBinary;
799 };
800
801 const char *const g_fakepath = "C:\\fakepath";
802
803 // InfoLog implementation.
InfoLog()804 InfoLog::InfoLog() : mLazyStream(nullptr) {}
805
~InfoLog()806 InfoLog::~InfoLog() {}
807
getLength() const808 size_t InfoLog::getLength() const
809 {
810 if (!mLazyStream)
811 {
812 return 0;
813 }
814
815 const std::string &logString = mLazyStream->str();
816 return logString.empty() ? 0 : logString.length() + 1;
817 }
818
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const819 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
820 {
821 size_t index = 0;
822
823 if (bufSize > 0)
824 {
825 const std::string logString(str());
826
827 if (!logString.empty())
828 {
829 index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
830 memcpy(infoLog, logString.c_str(), index);
831 }
832
833 infoLog[index] = '\0';
834 }
835
836 if (length)
837 {
838 *length = static_cast<GLsizei>(index);
839 }
840 }
841
842 // append a santized message to the program info log.
843 // The D3D compiler includes a fake file path in some of the warning or error
844 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)845 void InfoLog::appendSanitized(const char *message)
846 {
847 ensureInitialized();
848
849 std::string msg(message);
850
851 size_t found;
852 do
853 {
854 found = msg.find(g_fakepath);
855 if (found != std::string::npos)
856 {
857 msg.erase(found, strlen(g_fakepath));
858 }
859 } while (found != std::string::npos);
860
861 if (!msg.empty())
862 {
863 *mLazyStream << message << std::endl;
864 }
865 }
866
reset()867 void InfoLog::reset()
868 {
869 if (mLazyStream)
870 {
871 mLazyStream.reset(nullptr);
872 }
873 }
874
empty() const875 bool InfoLog::empty() const
876 {
877 if (!mLazyStream)
878 {
879 return true;
880 }
881
882 return mLazyStream->rdbuf()->in_avail() == 0;
883 }
884
LogLinkMismatch(InfoLog & infoLog,const std::string & variableName,const char * variableType,LinkMismatchError linkError,const std::string & mismatchedStructOrBlockFieldName,ShaderType shaderType1,ShaderType shaderType2)885 void LogLinkMismatch(InfoLog &infoLog,
886 const std::string &variableName,
887 const char *variableType,
888 LinkMismatchError linkError,
889 const std::string &mismatchedStructOrBlockFieldName,
890 ShaderType shaderType1,
891 ShaderType shaderType2)
892 {
893 std::ostringstream stream;
894 stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
895 << variableName;
896
897 if (!mismatchedStructOrBlockFieldName.empty())
898 {
899 stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
900 }
901
902 stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
903 << GetShaderTypeString(shaderType2) << " shaders.";
904
905 infoLog << stream.str();
906 }
907
IsActiveInterfaceBlock(const sh::InterfaceBlock & interfaceBlock)908 bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
909 {
910 // Only 'packed' blocks are allowed to be considered inactive.
911 return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
912 }
913
WriteBlockMemberInfo(BinaryOutputStream * stream,const sh::BlockMemberInfo & var)914 void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var)
915 {
916 stream->writeInt(var.arrayStride);
917 stream->writeBool(var.isRowMajorMatrix);
918 stream->writeInt(var.matrixStride);
919 stream->writeInt(var.offset);
920 stream->writeInt(var.topLevelArrayStride);
921 }
922
LoadBlockMemberInfo(BinaryInputStream * stream,sh::BlockMemberInfo * var)923 void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
924 {
925 var->arrayStride = stream->readInt<int>();
926 var->isRowMajorMatrix = stream->readBool();
927 var->matrixStride = stream->readInt<int>();
928 var->offset = stream->readInt<int>();
929 var->topLevelArrayStride = stream->readInt<int>();
930 }
931
WriteShaderVar(BinaryOutputStream * stream,const sh::ShaderVariable & var)932 void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
933 {
934 stream->writeInt(var.type);
935 stream->writeInt(var.precision);
936 stream->writeString(var.name);
937 stream->writeString(var.mappedName);
938 stream->writeIntVector(var.arraySizes);
939 stream->writeBool(var.staticUse);
940 stream->writeBool(var.active);
941 stream->writeInt<size_t>(var.fields.size());
942 for (const sh::ShaderVariable &shaderVariable : var.fields)
943 {
944 WriteShaderVar(stream, shaderVariable);
945 }
946 stream->writeString(var.structOrBlockName);
947 stream->writeString(var.mappedStructOrBlockName);
948 stream->writeBool(var.isRowMajorLayout);
949 stream->writeInt(var.location);
950 stream->writeBool(var.hasImplicitLocation);
951 stream->writeInt(var.binding);
952 stream->writeInt(var.imageUnitFormat);
953 stream->writeInt(var.offset);
954 stream->writeBool(var.readonly);
955 stream->writeBool(var.writeonly);
956 stream->writeBool(var.isFragmentInOut);
957 stream->writeInt(var.index);
958 stream->writeBool(var.yuv);
959 stream->writeEnum(var.interpolation);
960 stream->writeBool(var.isInvariant);
961 stream->writeBool(var.isShaderIOBlock);
962 stream->writeBool(var.isPatch);
963 stream->writeBool(var.texelFetchStaticUse);
964 stream->writeInt(var.getFlattenedOffsetInParentArrays());
965 }
966
LoadShaderVar(gl::BinaryInputStream * stream,sh::ShaderVariable * var)967 void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
968 {
969 var->type = stream->readInt<GLenum>();
970 var->precision = stream->readInt<GLenum>();
971 stream->readString(&var->name);
972 stream->readString(&var->mappedName);
973 stream->readIntVector<unsigned int>(&var->arraySizes);
974 var->staticUse = stream->readBool();
975 var->active = stream->readBool();
976 size_t elementCount = stream->readInt<size_t>();
977 var->fields.resize(elementCount);
978 for (sh::ShaderVariable &variable : var->fields)
979 {
980 LoadShaderVar(stream, &variable);
981 }
982 stream->readString(&var->structOrBlockName);
983 stream->readString(&var->mappedStructOrBlockName);
984 var->isRowMajorLayout = stream->readBool();
985 var->location = stream->readInt<int>();
986 var->hasImplicitLocation = stream->readBool();
987 var->binding = stream->readInt<int>();
988 var->imageUnitFormat = stream->readInt<GLenum>();
989 var->offset = stream->readInt<int>();
990 var->readonly = stream->readBool();
991 var->writeonly = stream->readBool();
992 var->isFragmentInOut = stream->readBool();
993 var->index = stream->readInt<int>();
994 var->yuv = stream->readBool();
995 var->interpolation = stream->readEnum<sh::InterpolationType>();
996 var->isInvariant = stream->readBool();
997 var->isShaderIOBlock = stream->readBool();
998 var->isPatch = stream->readBool();
999 var->texelFetchStaticUse = stream->readBool();
1000 var->setParentArrayIndex(stream->readInt<int>());
1001 }
1002
1003 // VariableLocation implementation.
VariableLocation()1004 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
1005
VariableLocation(unsigned int arrayIndex,unsigned int index)1006 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
1007 : arrayIndex(arrayIndex), index(index), ignored(false)
1008 {
1009 ASSERT(arrayIndex != GL_INVALID_INDEX);
1010 }
1011
1012 // SamplerBindings implementation.
SamplerBinding(TextureType textureTypeIn,GLenum samplerTypeIn,SamplerFormat formatIn,size_t elementCount)1013 SamplerBinding::SamplerBinding(TextureType textureTypeIn,
1014 GLenum samplerTypeIn,
1015 SamplerFormat formatIn,
1016 size_t elementCount)
1017 : textureType(textureTypeIn),
1018 samplerType(samplerTypeIn),
1019 format(formatIn),
1020 boundTextureUnits(elementCount, 0)
1021 {}
1022
1023 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
1024
1025 SamplerBinding::~SamplerBinding() = default;
1026
1027 // ProgramBindings implementation.
ProgramBindings()1028 ProgramBindings::ProgramBindings() {}
1029
~ProgramBindings()1030 ProgramBindings::~ProgramBindings() {}
1031
bindLocation(GLuint index,const std::string & name)1032 void ProgramBindings::bindLocation(GLuint index, const std::string &name)
1033 {
1034 mBindings[name] = index;
1035 }
1036
getBindingByName(const std::string & name) const1037 int ProgramBindings::getBindingByName(const std::string &name) const
1038 {
1039 auto iter = mBindings.find(name);
1040 return (iter != mBindings.end()) ? iter->second : -1;
1041 }
1042
getBinding(const sh::ShaderVariable & variable) const1043 int ProgramBindings::getBinding(const sh::ShaderVariable &variable) const
1044 {
1045 return getBindingByName(variable.name);
1046 }
1047
begin() const1048 ProgramBindings::const_iterator ProgramBindings::begin() const
1049 {
1050 return mBindings.begin();
1051 }
1052
end() const1053 ProgramBindings::const_iterator ProgramBindings::end() const
1054 {
1055 return mBindings.end();
1056 }
1057
getStableIterationMap() const1058 std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
1059 {
1060 return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
1061 }
1062
1063 // ProgramAliasedBindings implementation.
ProgramAliasedBindings()1064 ProgramAliasedBindings::ProgramAliasedBindings() {}
1065
~ProgramAliasedBindings()1066 ProgramAliasedBindings::~ProgramAliasedBindings() {}
1067
bindLocation(GLuint index,const std::string & name)1068 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
1069 {
1070 mBindings[name] = ProgramBinding(index);
1071
1072 // EXT_blend_func_extended spec: "If it specifies the base name of an array,
1073 // it identifies the resources associated with the first element of the array."
1074 //
1075 // Normalize array bindings so that "name" and "name[0]" map to the same entry.
1076 // If this binding is of the form "name[0]", then mark the "name" binding as
1077 // aliased but do not update it yet in case "name" is not actually an array.
1078 size_t nameLengthWithoutArrayIndex;
1079 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1080 if (arrayIndex == 0)
1081 {
1082 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1083 auto iter = mBindings.find(baseName);
1084 if (iter != mBindings.end())
1085 {
1086 iter->second.aliased = true;
1087 }
1088 }
1089 }
1090
getBindingByName(const std::string & name) const1091 int ProgramAliasedBindings::getBindingByName(const std::string &name) const
1092 {
1093 auto iter = mBindings.find(name);
1094 return (iter != mBindings.end()) ? iter->second.location : -1;
1095 }
1096
getBindingByLocation(GLuint location) const1097 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
1098 {
1099 for (const auto &iter : mBindings)
1100 {
1101 if (iter.second.location == location)
1102 {
1103 return iter.second.location;
1104 }
1105 }
1106 return -1;
1107 }
1108
getBinding(const sh::ShaderVariable & variable) const1109 int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const
1110 {
1111 const std::string &name = variable.name;
1112
1113 // Check with the normalized array name if applicable.
1114 if (variable.isArray())
1115 {
1116 size_t nameLengthWithoutArrayIndex;
1117 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1118 if (arrayIndex == 0)
1119 {
1120 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1121 auto iter = mBindings.find(baseName);
1122 // If "name" exists and is not aliased, that means it was modified more
1123 // recently than its "name[0]" form and should be used instead of that.
1124 if (iter != mBindings.end() && !iter->second.aliased)
1125 {
1126 return iter->second.location;
1127 }
1128 }
1129 else if (arrayIndex == GL_INVALID_INDEX)
1130 {
1131 auto iter = mBindings.find(variable.name);
1132 // If "name" exists and is not aliased, that means it was modified more
1133 // recently than its "name[0]" form and should be used instead of that.
1134 if (iter != mBindings.end() && !iter->second.aliased)
1135 {
1136 return iter->second.location;
1137 }
1138 // The base name was aliased, so use the name with the array notation.
1139 return getBindingByName(name + "[0]");
1140 }
1141 }
1142
1143 return getBindingByName(name);
1144 }
1145
begin() const1146 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
1147 {
1148 return mBindings.begin();
1149 }
1150
end() const1151 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
1152 {
1153 return mBindings.end();
1154 }
1155
getStableIterationMap() const1156 std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
1157 {
1158 return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
1159 }
1160
1161 // ImageBinding implementation.
ImageBinding(size_t count,TextureType textureTypeIn)1162 ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn)
1163 : textureType(textureTypeIn), boundImageUnits(count, 0)
1164 {}
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)1165 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
1166 : textureType(textureTypeIn)
1167 {
1168 for (size_t index = 0; index < count; ++index)
1169 {
1170 boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
1171 }
1172 }
1173
1174 ImageBinding::ImageBinding(const ImageBinding &other) = default;
1175
1176 ImageBinding::~ImageBinding() = default;
1177
1178 // ProgramState implementation.
ProgramState()1179 ProgramState::ProgramState()
1180 : mLabel(),
1181 mAttachedShaders{},
1182 mLocationsUsedForXfbExtension(0),
1183 mAtomicCounterUniformRange(0, 0),
1184 mYUVOutput(false),
1185 mBinaryRetrieveableHint(false),
1186 mSeparable(false),
1187 mNumViews(-1),
1188 mDrawIDLocation(-1),
1189 mBaseVertexLocation(-1),
1190 mBaseInstanceLocation(-1),
1191 mCachedBaseVertex(0),
1192 mCachedBaseInstance(0),
1193 mExecutable(new ProgramExecutable())
1194 {
1195 mComputeShaderLocalSize.fill(1);
1196 }
1197
~ProgramState()1198 ProgramState::~ProgramState()
1199 {
1200 ASSERT(!hasAttachedShader());
1201 }
1202
getLabel()1203 const std::string &ProgramState::getLabel()
1204 {
1205 return mLabel;
1206 }
1207
getAttachedShader(ShaderType shaderType) const1208 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
1209 {
1210 ASSERT(shaderType != ShaderType::InvalidEnum);
1211 return mAttachedShaders[shaderType];
1212 }
1213
getUniformIndexFromName(const std::string & name) const1214 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
1215 {
1216 return GetResourceIndexFromName(mExecutable->mUniforms, name);
1217 }
1218
getBufferVariableIndexFromName(const std::string & name) const1219 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
1220 {
1221 return GetResourceIndexFromName(mBufferVariables, name);
1222 }
1223
getUniformIndexFromLocation(UniformLocation location) const1224 GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const
1225 {
1226 ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
1227 return mUniformLocations[location.value].index;
1228 }
1229
getSamplerIndex(UniformLocation location) const1230 Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
1231 {
1232 GLuint index = getUniformIndexFromLocation(location);
1233 if (!isSamplerUniformIndex(index))
1234 {
1235 return Optional<GLuint>::Invalid();
1236 }
1237
1238 return getSamplerIndexFromUniformIndex(index);
1239 }
1240
isSamplerUniformIndex(GLuint index) const1241 bool ProgramState::isSamplerUniformIndex(GLuint index) const
1242 {
1243 return mExecutable->mSamplerUniformRange.contains(index);
1244 }
1245
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const1246 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
1247 {
1248 ASSERT(isSamplerUniformIndex(uniformIndex));
1249 return uniformIndex - mExecutable->mSamplerUniformRange.low();
1250 }
1251
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const1252 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
1253 {
1254 ASSERT(samplerIndex < mExecutable->mSamplerUniformRange.length());
1255 return samplerIndex + mExecutable->mSamplerUniformRange.low();
1256 }
1257
isImageUniformIndex(GLuint index) const1258 bool ProgramState::isImageUniformIndex(GLuint index) const
1259 {
1260 return mExecutable->mImageUniformRange.contains(index);
1261 }
1262
getImageIndexFromUniformIndex(GLuint uniformIndex) const1263 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
1264 {
1265 ASSERT(isImageUniformIndex(uniformIndex));
1266 return uniformIndex - mExecutable->mImageUniformRange.low();
1267 }
1268
getAttributeLocation(const std::string & name) const1269 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1270 {
1271 for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
1272 {
1273 if (attribute.name == name)
1274 {
1275 return attribute.location;
1276 }
1277 }
1278
1279 return static_cast<GLuint>(-1);
1280 }
1281
hasAttachedShader() const1282 bool ProgramState::hasAttachedShader() const
1283 {
1284 for (const Shader *shader : mAttachedShaders)
1285 {
1286 if (shader)
1287 {
1288 return true;
1289 }
1290 }
1291 return false;
1292 }
1293
getFirstAttachedShaderStageType() const1294 ShaderType ProgramState::getFirstAttachedShaderStageType() const
1295 {
1296 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1297 if (linkedStages.none())
1298 {
1299 return ShaderType::InvalidEnum;
1300 }
1301
1302 return linkedStages.first();
1303 }
1304
getLastAttachedShaderStageType() const1305 ShaderType ProgramState::getLastAttachedShaderStageType() const
1306 {
1307 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1308 if (linkedStages.none())
1309 {
1310 return ShaderType::InvalidEnum;
1311 }
1312
1313 return linkedStages.last();
1314 }
1315
getAttachedTransformFeedbackStage() const1316 ShaderType ProgramState::getAttachedTransformFeedbackStage() const
1317 {
1318 if (mAttachedShaders[ShaderType::Geometry])
1319 {
1320 return ShaderType::Geometry;
1321 }
1322 if (mAttachedShaders[ShaderType::TessEvaluation])
1323 {
1324 return ShaderType::TessEvaluation;
1325 }
1326 return ShaderType::Vertex;
1327 }
1328
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)1329 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
1330 : mSerial(factory->generateSerial()),
1331 mProgram(factory->createProgram(mState)),
1332 mValidated(false),
1333 mLinked(false),
1334 mDeleteStatus(false),
1335 mRefCount(0),
1336 mResourceManager(manager),
1337 mHandle(handle)
1338 {
1339 ASSERT(mProgram);
1340
1341 unlink();
1342 }
1343
~Program()1344 Program::~Program()
1345 {
1346 ASSERT(!mProgram);
1347 }
1348
onDestroy(const Context * context)1349 void Program::onDestroy(const Context *context)
1350 {
1351 resolveLink(context);
1352 for (ShaderType shaderType : AllShaderTypes())
1353 {
1354 if (mState.mAttachedShaders[shaderType])
1355 {
1356 mState.mAttachedShaders[shaderType]->release(context);
1357 mState.mAttachedShaders[shaderType] = nullptr;
1358 }
1359 }
1360
1361 mProgram->destroy(context);
1362
1363 ASSERT(!mState.hasAttachedShader());
1364 SafeDelete(mProgram);
1365
1366 delete this;
1367 }
id() const1368 ShaderProgramID Program::id() const
1369 {
1370 ASSERT(!mLinkingState);
1371 return mHandle;
1372 }
1373
setLabel(const Context * context,const std::string & label)1374 void Program::setLabel(const Context *context, const std::string &label)
1375 {
1376 ASSERT(!mLinkingState);
1377 mState.mLabel = label;
1378 }
1379
getLabel() const1380 const std::string &Program::getLabel() const
1381 {
1382 ASSERT(!mLinkingState);
1383 return mState.mLabel;
1384 }
1385
attachShader(Shader * shader)1386 void Program::attachShader(Shader *shader)
1387 {
1388 ShaderType shaderType = shader->getType();
1389 ASSERT(shaderType != ShaderType::InvalidEnum);
1390
1391 mState.mAttachedShaders[shaderType] = shader;
1392 mState.mAttachedShaders[shaderType]->addRef();
1393 }
1394
detachShader(const Context * context,Shader * shader)1395 void Program::detachShader(const Context *context, Shader *shader)
1396 {
1397 resolveLink(context);
1398 ShaderType shaderType = shader->getType();
1399 ASSERT(shaderType != ShaderType::InvalidEnum);
1400
1401 ASSERT(mState.mAttachedShaders[shaderType] == shader);
1402 shader->release(context);
1403 mState.mAttachedShaders[shaderType] = nullptr;
1404 }
1405
getAttachedShadersCount() const1406 int Program::getAttachedShadersCount() const
1407 {
1408 ASSERT(!mLinkingState);
1409 int numAttachedShaders = 0;
1410 for (const Shader *shader : mState.mAttachedShaders)
1411 {
1412 if (shader)
1413 {
1414 ++numAttachedShaders;
1415 }
1416 }
1417
1418 return numAttachedShaders;
1419 }
1420
getAttachedShader(ShaderType shaderType) const1421 Shader *Program::getAttachedShader(ShaderType shaderType) const
1422 {
1423 ASSERT(!mLinkingState);
1424 return mState.getAttachedShader(shaderType);
1425 }
1426
bindAttributeLocation(GLuint index,const char * name)1427 void Program::bindAttributeLocation(GLuint index, const char *name)
1428 {
1429 ASSERT(!mLinkingState);
1430 mAttributeBindings.bindLocation(index, name);
1431 }
1432
bindUniformLocation(UniformLocation location,const char * name)1433 void Program::bindUniformLocation(UniformLocation location, const char *name)
1434 {
1435 ASSERT(!mLinkingState);
1436 mState.mUniformLocationBindings.bindLocation(location.value, name);
1437 }
1438
bindFragmentOutputLocation(GLuint index,const char * name)1439 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1440 {
1441 mFragmentOutputLocations.bindLocation(index, name);
1442 }
1443
bindFragmentOutputIndex(GLuint index,const char * name)1444 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1445 {
1446 mFragmentOutputIndexes.bindLocation(index, name);
1447 }
1448
link(const Context * context)1449 angle::Result Program::link(const Context *context)
1450 {
1451 angle::Result result = linkImpl(context);
1452
1453 // Avoid having two ProgramExecutables if the link failed and the Program had successfully
1454 // linked previously.
1455 if (mLinkingState && mLinkingState->linkedExecutable)
1456 {
1457 mState.mExecutable = mLinkingState->linkedExecutable;
1458 }
1459
1460 return result;
1461 }
1462
1463 // The attached shaders are checked for linking errors by matching up their variables.
1464 // Uniform, input and output variables get collected.
1465 // The code gets compiled into binaries.
linkImpl(const Context * context)1466 angle::Result Program::linkImpl(const Context *context)
1467 {
1468 ASSERT(!mLinkingState);
1469 // Don't make any local variables pointing to anything within the ProgramExecutable, since
1470 // unlink() could make a new ProgramExecutable making any references/pointers invalid.
1471 auto *platform = ANGLEPlatformCurrent();
1472 double startTime = platform->currentTime(platform);
1473
1474 // Unlink the program, but do not clear the validation-related caching yet, since we can still
1475 // use the previously linked program if linking the shaders fails.
1476 mLinked = false;
1477
1478 mState.mExecutable->getInfoLog().reset();
1479
1480 // Validate we have properly attached shaders before checking the cache.
1481 if (!linkValidateShaders(mState.mExecutable->getInfoLog()))
1482 {
1483 return angle::Result::Continue;
1484 }
1485
1486 egl::BlobCache::Key programHash = {0};
1487 MemoryProgramCache *cache = context->getMemoryProgramCache();
1488
1489 // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1490 if (cache && !isSeparable())
1491 {
1492 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1493 angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1494 ANGLE_TRY(cacheResult);
1495
1496 // Check explicitly for Continue, Incomplete means a cache miss
1497 if (cacheResult == angle::Result::Continue)
1498 {
1499 // Succeeded in loading the binaries in the front-end, back end may still be loading
1500 // asynchronously
1501 double delta = platform->currentTime(platform) - startTime;
1502 int us = static_cast<int>(delta * 1000000.0);
1503 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1504 return angle::Result::Continue;
1505 }
1506 }
1507
1508 // Cache load failed, fall through to normal linking.
1509 unlink();
1510 InfoLog &infoLog = mState.mExecutable->getInfoLog();
1511
1512 // Re-link shaders after the unlink call.
1513 bool result = linkValidateShaders(infoLog);
1514 ASSERT(result);
1515
1516 std::unique_ptr<LinkingState> linkingState(new LinkingState());
1517 ProgramMergedVaryings mergedVaryings;
1518 ProgramLinkedResources &resources = linkingState->resources;
1519
1520 if (mState.mAttachedShaders[ShaderType::Compute])
1521 {
1522 resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1523 &mState.mExecutable->mComputeShaderStorageBlocks, &mState.mBufferVariables,
1524 &mState.mExecutable->mAtomicCounterBuffers);
1525
1526 GLuint combinedImageUniforms = 0u;
1527 if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1528 mState.mUniformLocationBindings, &combinedImageUniforms,
1529 &resources.unusedUniforms))
1530 {
1531 return angle::Result::Continue;
1532 }
1533
1534 GLuint combinedShaderStorageBlocks = 0u;
1535 if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1536 context->getExtensions().webglCompatibility, infoLog,
1537 &combinedShaderStorageBlocks))
1538 {
1539 return angle::Result::Continue;
1540 }
1541
1542 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1543 // A link error will be generated if the sum of the number of active image uniforms used in
1544 // all shaders, the number of active shader storage blocks, and the number of active
1545 // fragment shader outputs exceeds the implementation-dependent value of
1546 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1547 if (combinedImageUniforms + combinedShaderStorageBlocks >
1548 static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
1549 {
1550 infoLog
1551 << "The sum of the number of active image uniforms, active shader storage blocks "
1552 "and active fragment shader outputs exceeds "
1553 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1554 << context->getCaps().maxCombinedShaderOutputResources << ")";
1555 return angle::Result::Continue;
1556 }
1557
1558 InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1559 InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1560 }
1561 else
1562 {
1563 resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1564 &mState.mExecutable->mGraphicsShaderStorageBlocks, &mState.mBufferVariables,
1565 &mState.mExecutable->mAtomicCounterBuffers);
1566
1567 if (!linkAttributes(context, infoLog))
1568 {
1569 return angle::Result::Continue;
1570 }
1571
1572 if (!linkVaryings(infoLog))
1573 {
1574 return angle::Result::Continue;
1575 }
1576
1577 GLuint combinedImageUniforms = 0u;
1578 if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1579 mState.mUniformLocationBindings, &combinedImageUniforms,
1580 &resources.unusedUniforms))
1581 {
1582 return angle::Result::Continue;
1583 }
1584
1585 GLuint combinedShaderStorageBlocks = 0u;
1586 if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1587 context->getExtensions().webglCompatibility, infoLog,
1588 &combinedShaderStorageBlocks))
1589 {
1590 return angle::Result::Continue;
1591 }
1592
1593 if (!LinkValidateProgramGlobalNames(infoLog, *this))
1594 {
1595 return angle::Result::Continue;
1596 }
1597
1598 if (!linkOutputVariables(context->getCaps(), context->getExtensions(),
1599 context->getClientVersion(), combinedImageUniforms,
1600 combinedShaderStorageBlocks))
1601 {
1602 return angle::Result::Continue;
1603 }
1604
1605 gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1606 if (vertexShader)
1607 {
1608 mState.mNumViews = vertexShader->getNumViews();
1609 mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
1610 }
1611
1612 gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1613 if (fragmentShader)
1614 {
1615 mState.mEarlyFramentTestsOptimization =
1616 fragmentShader->hasEarlyFragmentTestsOptimization();
1617 mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
1618 }
1619
1620 InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1621 InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1622
1623 mergedVaryings = GetMergedVaryingsFromShaders(*this, getExecutable());
1624 if (!mState.mExecutable->linkMergedVaryings(context, *this, mergedVaryings,
1625 mState.mTransformFeedbackVaryingNames,
1626 isSeparable(), &resources.varyingPacking))
1627 {
1628 return angle::Result::Continue;
1629 }
1630 }
1631
1632 updateLinkedShaderStages();
1633
1634 mLinkingState = std::move(linkingState);
1635 mLinkingState->linkingFromBinary = false;
1636 mLinkingState->programHash = programHash;
1637 mLinkingState->linkEvent = mProgram->link(context, resources, infoLog, mergedVaryings);
1638
1639 // Must be after mProgram->link() to avoid misleading the linker about output variables.
1640 mState.updateProgramInterfaceInputs();
1641 mState.updateProgramInterfaceOutputs();
1642
1643 // Linking has succeeded, so we need to save some information that may get overwritten by a
1644 // later linkProgram() that could fail.
1645 if (mState.mSeparable)
1646 {
1647 mState.mExecutable->saveLinkedStateInfo(mState);
1648 mLinkingState->linkedExecutable = mState.mExecutable;
1649 }
1650
1651 return angle::Result::Continue;
1652 }
1653
isLinking() const1654 bool Program::isLinking() const
1655 {
1656 return (mLinkingState.get() && mLinkingState->linkEvent &&
1657 mLinkingState->linkEvent->isLinking());
1658 }
1659
resolveLinkImpl(const Context * context)1660 void Program::resolveLinkImpl(const Context *context)
1661 {
1662 ASSERT(mLinkingState.get());
1663
1664 angle::Result result = mLinkingState->linkEvent->wait(context);
1665
1666 mLinked = result == angle::Result::Continue;
1667 std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1668 if (!mLinked)
1669 {
1670 return;
1671 }
1672
1673 if (linkingState->linkingFromBinary)
1674 {
1675 // All internal Program state is already loaded from the binary.
1676 return;
1677 }
1678
1679 initInterfaceBlockBindings();
1680
1681 // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1682 // Only successfully linked program can replace the executables.
1683 ASSERT(mLinked);
1684
1685 // Mark implementation-specific unreferenced uniforms as ignored.
1686 std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1687 mProgram->markUnusedUniformLocations(&mState.mUniformLocations,
1688 &mState.mExecutable->mSamplerBindings, imageBindings);
1689
1690 // Must be called after markUnusedUniformLocations.
1691 postResolveLink(context);
1692
1693 // Save to the program cache.
1694 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1695 MemoryProgramCache *cache = context->getMemoryProgramCache();
1696 // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1697 if (cache && !isSeparable() &&
1698 (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
1699 !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
1700 {
1701 if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
1702 {
1703 // Don't fail linking if putting the program binary into the cache fails, the program is
1704 // still usable.
1705 WARN() << "Failed to save linked program to memory program cache.";
1706 }
1707 }
1708 }
1709
updateLinkedShaderStages()1710 void Program::updateLinkedShaderStages()
1711 {
1712 mState.mExecutable->resetLinkedShaderStages();
1713
1714 for (const Shader *shader : mState.mAttachedShaders)
1715 {
1716 if (shader)
1717 {
1718 mState.mExecutable->setLinkedShaderStages(shader->getType());
1719 }
1720 }
1721
1722 if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
1723 {
1724 mState.mExecutable->setIsCompute(true);
1725 }
1726 else
1727 {
1728 mState.mExecutable->setIsCompute(false);
1729 }
1730 }
1731
updateActiveSamplers()1732 void ProgramState::updateActiveSamplers()
1733 {
1734 mExecutable->mActiveSamplerRefCounts.fill(0);
1735 mExecutable->updateActiveSamplers(*this);
1736 }
1737
updateProgramInterfaceInputs()1738 void ProgramState::updateProgramInterfaceInputs()
1739 {
1740 const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType();
1741
1742 if (firstAttachedShaderType == ShaderType::Vertex)
1743 {
1744 // Vertex attributes are already what we need, so nothing to do
1745 return;
1746 }
1747
1748 Shader *shader = getAttachedShader(firstAttachedShaderType);
1749 ASSERT(shader);
1750
1751 // Copy over each input varying, since the Shader could go away
1752 if (shader->getType() == ShaderType::Compute)
1753 {
1754 for (const sh::ShaderVariable &attribute : shader->getAllAttributes())
1755 {
1756 // Compute Shaders have the following built-in input variables.
1757 //
1758 // in uvec3 gl_NumWorkGroups;
1759 // in uvec3 gl_WorkGroupID;
1760 // in uvec3 gl_LocalInvocationID;
1761 // in uvec3 gl_GlobalInvocationID;
1762 // in uint gl_LocalInvocationIndex;
1763 // They are all vecs or uints, so no special handling is required.
1764 mExecutable->mProgramInputs.emplace_back(attribute);
1765 }
1766 }
1767 else
1768 {
1769 for (const sh::ShaderVariable &varying : shader->getInputVaryings())
1770 {
1771 UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1772 }
1773 }
1774 }
1775
updateProgramInterfaceOutputs()1776 void ProgramState::updateProgramInterfaceOutputs()
1777 {
1778 const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType();
1779
1780 if (lastAttachedShaderType == ShaderType::Fragment)
1781 {
1782 // Fragment outputs are already what we need, so nothing to do
1783 return;
1784 }
1785 if (lastAttachedShaderType == ShaderType::Compute)
1786 {
1787 // If the program only contains a Compute Shader, then there are no user-defined outputs.
1788 return;
1789 }
1790
1791 Shader *shader = getAttachedShader(lastAttachedShaderType);
1792 ASSERT(shader);
1793
1794 // Copy over each output varying, since the Shader could go away
1795 for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
1796 {
1797 UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1798 }
1799 }
1800
1801 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1802 void Program::unlink()
1803 {
1804 if (mLinkingState && mLinkingState->linkedExecutable)
1805 {
1806 // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of
1807 // the last successfully linked ProgramExecutable, so we don't lose any state information.
1808 mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable));
1809 }
1810 mState.mExecutable->reset();
1811
1812 mState.mUniformLocations.clear();
1813 mState.mBufferVariables.clear();
1814 mState.mOutputVariableTypes.clear();
1815 mState.mDrawBufferTypeMask.reset();
1816 mState.mYUVOutput = false;
1817 mState.mActiveOutputVariables.reset();
1818 mState.mComputeShaderLocalSize.fill(1);
1819 mState.mNumViews = -1;
1820 mState.mDrawIDLocation = -1;
1821 mState.mBaseVertexLocation = -1;
1822 mState.mBaseInstanceLocation = -1;
1823 mState.mCachedBaseVertex = 0;
1824 mState.mCachedBaseInstance = 0;
1825 mState.mEarlyFramentTestsOptimization = false;
1826 mState.mDrawIDLocation = -1;
1827 mState.mBaseVertexLocation = -1;
1828 mState.mBaseInstanceLocation = -1;
1829 mState.mCachedBaseVertex = 0;
1830 mState.mCachedBaseInstance = 0;
1831 mState.mEarlyFramentTestsOptimization = false;
1832 mState.mSpecConstUsageBits.reset();
1833
1834 mValidated = false;
1835
1836 mLinked = false;
1837 }
1838
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1839 angle::Result Program::loadBinary(const Context *context,
1840 GLenum binaryFormat,
1841 const void *binary,
1842 GLsizei length)
1843 {
1844 ASSERT(!mLinkingState);
1845 unlink();
1846 InfoLog &infoLog = mState.mExecutable->getInfoLog();
1847
1848 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1849 return angle::Result::Continue;
1850 #else
1851 ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1852 if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1853 {
1854 infoLog << "Invalid program binary format.";
1855 return angle::Result::Continue;
1856 }
1857
1858 BinaryInputStream stream(binary, length);
1859 ANGLE_TRY(deserialize(context, stream, infoLog));
1860
1861 // Currently we require the full shader text to compute the program hash.
1862 // We could also store the binary in the internal program cache.
1863
1864 for (size_t uniformBlockIndex = 0;
1865 uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
1866 {
1867 mDirtyBits.set(uniformBlockIndex);
1868 }
1869
1870 // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple
1871 // implementations. In some implementations, a background thread is used to compile the
1872 // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with
1873 // the operation.
1874
1875 // We do not want to call LinkEvent::wait because that will cause the background thread
1876 // to finish its task before returning, thus defeating the purpose of background compilation.
1877 // We need to defer waiting on background compilation until the very last minute when we
1878 // absolutely need the results, such as when the developer binds the program or queries
1879 // for the completion status.
1880
1881 // If load returns nullptr, we know for sure that the binary is not compatible with the backend.
1882 // The loaded binary could have been read from the on-disk shader cache and be corrupted or
1883 // serialized with different revision and subsystem id than the currently loaded backend.
1884 // Returning 'Incomplete' to the caller results in link happening using the original shader
1885 // sources.
1886 angle::Result result;
1887 std::unique_ptr<LinkingState> linkingState;
1888 std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog);
1889 if (linkEvent)
1890 {
1891 linkingState = std::make_unique<LinkingState>();
1892 linkingState->linkingFromBinary = true;
1893 linkingState->linkEvent = std::move(linkEvent);
1894 result = angle::Result::Continue;
1895 }
1896 else
1897 {
1898 result = angle::Result::Incomplete;
1899 }
1900 mLinkingState = std::move(linkingState);
1901
1902 return result;
1903 #endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1904 }
1905
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1906 angle::Result Program::saveBinary(Context *context,
1907 GLenum *binaryFormat,
1908 void *binary,
1909 GLsizei bufSize,
1910 GLsizei *length) const
1911 {
1912 ASSERT(!mLinkingState);
1913 if (binaryFormat)
1914 {
1915 *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1916 }
1917
1918 angle::MemoryBuffer memoryBuf;
1919 ANGLE_TRY(serialize(context, &memoryBuf));
1920
1921 GLsizei streamLength = static_cast<GLsizei>(memoryBuf.size());
1922 const uint8_t *streamState = memoryBuf.data();
1923
1924 if (streamLength > bufSize)
1925 {
1926 if (length)
1927 {
1928 *length = 0;
1929 }
1930
1931 // TODO: This should be moved to the validation layer but computing the size of the binary
1932 // before saving it causes the save to happen twice. It may be possible to write the binary
1933 // to a separate buffer, validate sizes and then copy it.
1934 ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1935 }
1936
1937 if (binary)
1938 {
1939 char *ptr = reinterpret_cast<char *>(binary);
1940
1941 memcpy(ptr, streamState, streamLength);
1942 ptr += streamLength;
1943
1944 ASSERT(ptr - streamLength == binary);
1945 }
1946
1947 if (length)
1948 {
1949 *length = streamLength;
1950 }
1951
1952 return angle::Result::Continue;
1953 }
1954
getBinaryLength(Context * context) const1955 GLint Program::getBinaryLength(Context *context) const
1956 {
1957 ASSERT(!mLinkingState);
1958 if (!mLinked)
1959 {
1960 return 0;
1961 }
1962
1963 GLint length;
1964 angle::Result result =
1965 saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1966 if (result != angle::Result::Continue)
1967 {
1968 return 0;
1969 }
1970
1971 return length;
1972 }
1973
setBinaryRetrievableHint(bool retrievable)1974 void Program::setBinaryRetrievableHint(bool retrievable)
1975 {
1976 ASSERT(!mLinkingState);
1977 // TODO(jmadill) : replace with dirty bits
1978 mProgram->setBinaryRetrievableHint(retrievable);
1979 mState.mBinaryRetrieveableHint = retrievable;
1980 }
1981
getBinaryRetrievableHint() const1982 bool Program::getBinaryRetrievableHint() const
1983 {
1984 ASSERT(!mLinkingState);
1985 return mState.mBinaryRetrieveableHint;
1986 }
1987
setSeparable(bool separable)1988 void Program::setSeparable(bool separable)
1989 {
1990 ASSERT(!mLinkingState);
1991 // TODO(yunchao) : replace with dirty bits
1992 if (mState.mSeparable != separable)
1993 {
1994 mProgram->setSeparable(separable);
1995 mState.mSeparable = separable;
1996 }
1997 }
1998
isSeparable() const1999 bool Program::isSeparable() const
2000 {
2001 ASSERT(!mLinkingState);
2002 return mState.mSeparable;
2003 }
2004
deleteSelf(const Context * context)2005 void Program::deleteSelf(const Context *context)
2006 {
2007 ASSERT(mRefCount == 0 && mDeleteStatus);
2008 mResourceManager->deleteProgram(context, mHandle);
2009 }
2010
getRefCount() const2011 unsigned int Program::getRefCount() const
2012 {
2013 return mRefCount;
2014 }
2015
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const2016 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
2017 {
2018 ASSERT(!mLinkingState);
2019 int total = 0;
2020
2021 for (const Shader *shader : mState.mAttachedShaders)
2022 {
2023 if (shader && (total < maxCount))
2024 {
2025 shaders[total] = shader->getHandle();
2026 ++total;
2027 }
2028 }
2029
2030 if (count)
2031 {
2032 *count = total;
2033 }
2034 }
2035
getAttributeLocation(const std::string & name) const2036 GLuint Program::getAttributeLocation(const std::string &name) const
2037 {
2038 ASSERT(!mLinkingState);
2039 return mState.getAttributeLocation(name);
2040 }
2041
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2042 void Program::getActiveAttribute(GLuint index,
2043 GLsizei bufsize,
2044 GLsizei *length,
2045 GLint *size,
2046 GLenum *type,
2047 GLchar *name) const
2048 {
2049 ASSERT(!mLinkingState);
2050 if (!mLinked)
2051 {
2052 if (bufsize > 0)
2053 {
2054 name[0] = '\0';
2055 }
2056
2057 if (length)
2058 {
2059 *length = 0;
2060 }
2061
2062 *type = GL_NONE;
2063 *size = 1;
2064 return;
2065 }
2066
2067 ASSERT(index < mState.mExecutable->getProgramInputs().size());
2068 const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
2069
2070 if (bufsize > 0)
2071 {
2072 CopyStringToBuffer(name, attrib.name, bufsize, length);
2073 }
2074
2075 // Always a single 'type' instance
2076 *size = 1;
2077 *type = attrib.type;
2078 }
2079
getActiveAttributeCount() const2080 GLint Program::getActiveAttributeCount() const
2081 {
2082 ASSERT(!mLinkingState);
2083 if (!mLinked)
2084 {
2085 return 0;
2086 }
2087
2088 return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
2089 }
2090
getActiveAttributeMaxLength() const2091 GLint Program::getActiveAttributeMaxLength() const
2092 {
2093 ASSERT(!mLinkingState);
2094 if (!mLinked)
2095 {
2096 return 0;
2097 }
2098
2099 size_t maxLength = 0;
2100
2101 for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
2102 {
2103 maxLength = std::max(attrib.name.length() + 1, maxLength);
2104 }
2105
2106 return static_cast<GLint>(maxLength);
2107 }
2108
getAttributes() const2109 const std::vector<sh::ShaderVariable> &Program::getAttributes() const
2110 {
2111 ASSERT(!mLinkingState);
2112 return mState.mExecutable->getProgramInputs();
2113 }
2114
getComputeShaderLocalSize() const2115 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
2116 {
2117 ASSERT(!mLinkingState);
2118 return mState.mComputeShaderLocalSize;
2119 }
2120
getGeometryShaderInputPrimitiveType() const2121 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
2122 {
2123 ASSERT(!mLinkingState && mState.mExecutable);
2124 return mState.mExecutable->getGeometryShaderInputPrimitiveType();
2125 }
getGeometryShaderOutputPrimitiveType() const2126 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
2127 {
2128 ASSERT(!mLinkingState && mState.mExecutable);
2129 return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
2130 }
getGeometryShaderInvocations() const2131 GLint Program::getGeometryShaderInvocations() const
2132 {
2133 ASSERT(!mLinkingState && mState.mExecutable);
2134 return mState.mExecutable->getGeometryShaderInvocations();
2135 }
getGeometryShaderMaxVertices() const2136 GLint Program::getGeometryShaderMaxVertices() const
2137 {
2138 ASSERT(!mLinkingState && mState.mExecutable);
2139 return mState.mExecutable->getGeometryShaderMaxVertices();
2140 }
2141
getTessControlShaderVertices() const2142 GLint Program::getTessControlShaderVertices() const
2143 {
2144 ASSERT(!mLinkingState && mState.mExecutable);
2145 return mState.mExecutable->mTessControlShaderVertices;
2146 }
2147
getTessGenMode() const2148 GLenum Program::getTessGenMode() const
2149 {
2150 ASSERT(!mLinkingState && mState.mExecutable);
2151 return mState.mExecutable->mTessGenMode;
2152 }
2153
getTessGenPointMode() const2154 GLenum Program::getTessGenPointMode() const
2155 {
2156 ASSERT(!mLinkingState && mState.mExecutable);
2157 return mState.mExecutable->mTessGenPointMode;
2158 }
2159
getTessGenSpacing() const2160 GLenum Program::getTessGenSpacing() const
2161 {
2162 ASSERT(!mLinkingState && mState.mExecutable);
2163 return mState.mExecutable->mTessGenSpacing;
2164 }
2165
getTessGenVertexOrder() const2166 GLenum Program::getTessGenVertexOrder() const
2167 {
2168 ASSERT(!mLinkingState && mState.mExecutable);
2169 return mState.mExecutable->mTessGenVertexOrder;
2170 }
2171
getInputResource(size_t index) const2172 const sh::ShaderVariable &Program::getInputResource(size_t index) const
2173 {
2174 ASSERT(!mLinkingState);
2175 ASSERT(index < mState.mExecutable->getProgramInputs().size());
2176 return mState.mExecutable->getProgramInputs()[index];
2177 }
2178
getInputResourceIndex(const GLchar * name) const2179 GLuint Program::getInputResourceIndex(const GLchar *name) const
2180 {
2181 ASSERT(!mLinkingState);
2182 const std::string nameString = StripLastArrayIndex(name);
2183
2184 for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
2185 {
2186 sh::ShaderVariable resource = getInputResource(index);
2187 if (resource.name == nameString)
2188 {
2189 return static_cast<GLuint>(index);
2190 }
2191 }
2192
2193 return GL_INVALID_INDEX;
2194 }
2195
getResourceMaxNameSize(const sh::ShaderVariable & resource,GLint max) const2196 GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
2197 {
2198 if (resource.isArray())
2199 {
2200 return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
2201 }
2202 else
2203 {
2204 return std::max(max, clampCast<GLint>((resource.name).size()));
2205 }
2206 }
2207
getInputResourceMaxNameSize() const2208 GLuint Program::getInputResourceMaxNameSize() const
2209 {
2210 GLint max = 0;
2211
2212 for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
2213 {
2214 max = getResourceMaxNameSize(resource, max);
2215 }
2216
2217 return max;
2218 }
2219
getOutputResourceMaxNameSize() const2220 GLuint Program::getOutputResourceMaxNameSize() const
2221 {
2222 GLint max = 0;
2223
2224 for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
2225 {
2226 max = getResourceMaxNameSize(resource, max);
2227 }
2228
2229 return max;
2230 }
2231
getResourceLocation(const GLchar * name,const sh::ShaderVariable & variable) const2232 GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
2233 {
2234 if (variable.isBuiltIn())
2235 {
2236 return GL_INVALID_INDEX;
2237 }
2238
2239 GLint location = variable.location;
2240 if (variable.isArray())
2241 {
2242 size_t nameLengthWithoutArrayIndexOut;
2243 size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
2244 // The 'name' string may not contain the array notation "[0]"
2245 if (arrayIndex != GL_INVALID_INDEX)
2246 {
2247 location += arrayIndex;
2248 }
2249 }
2250
2251 return location;
2252 }
2253
getInputResourceLocation(const GLchar * name) const2254 GLuint Program::getInputResourceLocation(const GLchar *name) const
2255 {
2256 const GLuint index = getInputResourceIndex(name);
2257 if (index == GL_INVALID_INDEX)
2258 {
2259 return index;
2260 }
2261
2262 const sh::ShaderVariable &variable = getInputResource(index);
2263
2264 return getResourceLocation(name, variable);
2265 }
2266
getOutputResourceLocation(const GLchar * name) const2267 GLuint Program::getOutputResourceLocation(const GLchar *name) const
2268 {
2269 const GLuint index = getOutputResourceIndex(name);
2270 if (index == GL_INVALID_INDEX)
2271 {
2272 return index;
2273 }
2274
2275 const sh::ShaderVariable &variable = getOutputResource(index);
2276
2277 return getResourceLocation(name, variable);
2278 }
2279
getOutputResourceIndex(const GLchar * name) const2280 GLuint Program::getOutputResourceIndex(const GLchar *name) const
2281 {
2282 ASSERT(!mLinkingState);
2283 const std::string nameString = StripLastArrayIndex(name);
2284
2285 for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
2286 {
2287 sh::ShaderVariable resource = getOutputResource(index);
2288 if (resource.name == nameString)
2289 {
2290 return static_cast<GLuint>(index);
2291 }
2292 }
2293
2294 return GL_INVALID_INDEX;
2295 }
2296
getOutputResourceCount() const2297 size_t Program::getOutputResourceCount() const
2298 {
2299 ASSERT(!mLinkingState);
2300 return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
2301 }
2302
getOutputVariableTypes() const2303 const std::vector<GLenum> &Program::getOutputVariableTypes() const
2304 {
2305 ASSERT(!mLinkingState);
2306 return mState.mOutputVariableTypes;
2307 }
2308
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2309 void Program::getResourceName(const std::string name,
2310 GLsizei bufSize,
2311 GLsizei *length,
2312 GLchar *dest) const
2313 {
2314 if (length)
2315 {
2316 *length = 0;
2317 }
2318
2319 if (!mLinked)
2320 {
2321 if (bufSize > 0)
2322 {
2323 dest[0] = '\0';
2324 }
2325 return;
2326 }
2327
2328 if (bufSize > 0)
2329 {
2330 CopyStringToBuffer(dest, name, bufSize, length);
2331 }
2332 }
2333
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2334 void Program::getInputResourceName(GLuint index,
2335 GLsizei bufSize,
2336 GLsizei *length,
2337 GLchar *name) const
2338 {
2339 ASSERT(!mLinkingState);
2340 getResourceName(getInputResourceName(index), bufSize, length, name);
2341 }
2342
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2343 void Program::getOutputResourceName(GLuint index,
2344 GLsizei bufSize,
2345 GLsizei *length,
2346 GLchar *name) const
2347 {
2348 ASSERT(!mLinkingState);
2349 getResourceName(getOutputResourceName(index), bufSize, length, name);
2350 }
2351
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2352 void Program::getUniformResourceName(GLuint index,
2353 GLsizei bufSize,
2354 GLsizei *length,
2355 GLchar *name) const
2356 {
2357 ASSERT(!mLinkingState);
2358 ASSERT(index < mState.mExecutable->getUniforms().size());
2359 getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
2360 }
2361
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2362 void Program::getBufferVariableResourceName(GLuint index,
2363 GLsizei bufSize,
2364 GLsizei *length,
2365 GLchar *name) const
2366 {
2367 ASSERT(!mLinkingState);
2368 ASSERT(index < mState.mBufferVariables.size());
2369 getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
2370 }
2371
getResourceName(const sh::ShaderVariable & resource) const2372 const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
2373 {
2374 std::string resourceName = resource.name;
2375
2376 if (resource.isArray())
2377 {
2378 resourceName += "[0]";
2379 }
2380
2381 return resourceName;
2382 }
2383
getInputResourceName(GLuint index) const2384 const std::string Program::getInputResourceName(GLuint index) const
2385 {
2386 ASSERT(!mLinkingState);
2387 const sh::ShaderVariable &resource = getInputResource(index);
2388
2389 return getResourceName(resource);
2390 }
2391
getOutputResourceName(GLuint index) const2392 const std::string Program::getOutputResourceName(GLuint index) const
2393 {
2394 ASSERT(!mLinkingState);
2395 const sh::ShaderVariable &resource = getOutputResource(index);
2396
2397 return getResourceName(resource);
2398 }
2399
getOutputResource(size_t index) const2400 const sh::ShaderVariable &Program::getOutputResource(size_t index) const
2401 {
2402 ASSERT(!mLinkingState);
2403 ASSERT(index < mState.mExecutable->getOutputVariables().size());
2404 return mState.mExecutable->getOutputVariables()[index];
2405 }
2406
getAttributeBindings() const2407 const ProgramBindings &Program::getAttributeBindings() const
2408 {
2409 ASSERT(!mLinkingState);
2410 return mAttributeBindings;
2411 }
getUniformLocationBindings() const2412 const ProgramAliasedBindings &Program::getUniformLocationBindings() const
2413 {
2414 ASSERT(!mLinkingState);
2415 return mState.mUniformLocationBindings;
2416 }
2417
getFragmentOutputLocations() const2418 const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
2419 {
2420 ASSERT(!mLinkingState);
2421 return mFragmentOutputLocations;
2422 }
2423
getFragmentOutputIndexes() const2424 const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
2425 {
2426 ASSERT(!mLinkingState);
2427 return mFragmentOutputIndexes;
2428 }
2429
getDrawBufferTypeMask() const2430 ComponentTypeMask Program::getDrawBufferTypeMask() const
2431 {
2432 ASSERT(!mLinkingState);
2433 return mState.mDrawBufferTypeMask;
2434 }
2435
getTransformFeedbackStrides() const2436 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2437 {
2438 ASSERT(!mLinkingState);
2439 return mState.mExecutable->getTransformFeedbackStrides();
2440 }
2441
getFragDataLocation(const std::string & name) const2442 GLint Program::getFragDataLocation(const std::string &name) const
2443 {
2444 ASSERT(!mLinkingState);
2445 GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
2446 mState.mExecutable->getOutputLocations(), name);
2447 if (primaryLocation != -1)
2448 {
2449 return primaryLocation;
2450 }
2451 return GetVariableLocation(mState.mExecutable->getOutputVariables(),
2452 mState.mExecutable->getSecondaryOutputLocations(), name);
2453 }
2454
getFragDataIndex(const std::string & name) const2455 GLint Program::getFragDataIndex(const std::string &name) const
2456 {
2457 ASSERT(!mLinkingState);
2458 if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2459 mState.mExecutable->getOutputLocations(), name) != -1)
2460 {
2461 return 0;
2462 }
2463 if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2464 mState.mExecutable->getSecondaryOutputLocations(), name) != -1)
2465 {
2466 return 1;
2467 }
2468 return -1;
2469 }
2470
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2471 void Program::getActiveUniform(GLuint index,
2472 GLsizei bufsize,
2473 GLsizei *length,
2474 GLint *size,
2475 GLenum *type,
2476 GLchar *name) const
2477 {
2478 ASSERT(!mLinkingState);
2479 if (mLinked)
2480 {
2481 // index must be smaller than getActiveUniformCount()
2482 ASSERT(index < mState.mExecutable->getUniforms().size());
2483 const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
2484
2485 if (bufsize > 0)
2486 {
2487 std::string string = uniform.name;
2488 CopyStringToBuffer(name, string, bufsize, length);
2489 }
2490
2491 *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2492 *type = uniform.type;
2493 }
2494 else
2495 {
2496 if (bufsize > 0)
2497 {
2498 name[0] = '\0';
2499 }
2500
2501 if (length)
2502 {
2503 *length = 0;
2504 }
2505
2506 *size = 0;
2507 *type = GL_NONE;
2508 }
2509 }
2510
getActiveUniformCount() const2511 GLint Program::getActiveUniformCount() const
2512 {
2513 ASSERT(!mLinkingState);
2514 if (mLinked)
2515 {
2516 return static_cast<GLint>(mState.mExecutable->getUniforms().size());
2517 }
2518 else
2519 {
2520 return 0;
2521 }
2522 }
2523
getActiveBufferVariableCount() const2524 size_t Program::getActiveBufferVariableCount() const
2525 {
2526 ASSERT(!mLinkingState);
2527 return mLinked ? mState.mBufferVariables.size() : 0;
2528 }
2529
getActiveUniformMaxLength() const2530 GLint Program::getActiveUniformMaxLength() const
2531 {
2532 ASSERT(!mLinkingState);
2533 size_t maxLength = 0;
2534
2535 if (mLinked)
2536 {
2537 for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
2538 {
2539 if (!uniform.name.empty())
2540 {
2541 size_t length = uniform.name.length() + 1u;
2542 if (uniform.isArray())
2543 {
2544 length += 3; // Counting in "[0]".
2545 }
2546 maxLength = std::max(length, maxLength);
2547 }
2548 }
2549 }
2550
2551 return static_cast<GLint>(maxLength);
2552 }
2553
isValidUniformLocation(UniformLocation location) const2554 bool Program::isValidUniformLocation(UniformLocation location) const
2555 {
2556 ASSERT(!mLinkingState);
2557 ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2558 return (location.value >= 0 &&
2559 static_cast<size_t>(location.value) < mState.mUniformLocations.size() &&
2560 mState.mUniformLocations[static_cast<size_t>(location.value)].used());
2561 }
2562
getUniformByLocation(UniformLocation location) const2563 const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const
2564 {
2565 ASSERT(!mLinkingState);
2566 ASSERT(location.value >= 0 &&
2567 static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2568 return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
2569 }
2570
getUniformLocation(UniformLocation location) const2571 const VariableLocation &Program::getUniformLocation(UniformLocation location) const
2572 {
2573 ASSERT(!mLinkingState);
2574 ASSERT(location.value >= 0 &&
2575 static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2576 return mState.mUniformLocations[location.value];
2577 }
2578
getBufferVariableByIndex(GLuint index) const2579 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2580 {
2581 ASSERT(!mLinkingState);
2582 ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2583 return mState.mBufferVariables[index];
2584 }
2585
getUniformLocation(const std::string & name) const2586 UniformLocation Program::getUniformLocation(const std::string &name) const
2587 {
2588 ASSERT(!mLinkingState);
2589 return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
2590 }
2591
getUniformIndex(const std::string & name) const2592 GLuint Program::getUniformIndex(const std::string &name) const
2593 {
2594 ASSERT(!mLinkingState);
2595 return mState.getUniformIndexFromName(name);
2596 }
2597
shouldIgnoreUniform(UniformLocation location) const2598 bool Program::shouldIgnoreUniform(UniformLocation location) const
2599 {
2600 if (location.value == -1)
2601 {
2602 return true;
2603 }
2604
2605 if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored)
2606 {
2607 return true;
2608 }
2609
2610 return false;
2611 }
2612
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2613 void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2614 {
2615 ASSERT(!mLinkingState);
2616 if (shouldIgnoreUniform(location))
2617 {
2618 return;
2619 }
2620
2621 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2622 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2623 mProgram->setUniform1fv(location.value, clampedCount, v);
2624 }
2625
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2626 void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2627 {
2628 ASSERT(!mLinkingState);
2629 if (shouldIgnoreUniform(location))
2630 {
2631 return;
2632 }
2633
2634 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2635 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2636 mProgram->setUniform2fv(location.value, clampedCount, v);
2637 }
2638
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2639 void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2640 {
2641 ASSERT(!mLinkingState);
2642 if (shouldIgnoreUniform(location))
2643 {
2644 return;
2645 }
2646
2647 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2648 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2649 mProgram->setUniform3fv(location.value, clampedCount, v);
2650 }
2651
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2652 void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2653 {
2654 ASSERT(!mLinkingState);
2655 if (shouldIgnoreUniform(location))
2656 {
2657 return;
2658 }
2659
2660 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2661 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2662 mProgram->setUniform4fv(location.value, clampedCount, v);
2663 }
2664
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2665 void Program::setUniform1iv(Context *context,
2666 UniformLocation location,
2667 GLsizei count,
2668 const GLint *v)
2669 {
2670 ASSERT(!mLinkingState);
2671 if (shouldIgnoreUniform(location))
2672 {
2673 return;
2674 }
2675
2676 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2677 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2678
2679 mProgram->setUniform1iv(location.value, clampedCount, v);
2680
2681 if (mState.isSamplerUniformIndex(locationInfo.index))
2682 {
2683 updateSamplerUniform(context, locationInfo, clampedCount, v);
2684 }
2685 }
2686
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2687 void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2688 {
2689 ASSERT(!mLinkingState);
2690 if (shouldIgnoreUniform(location))
2691 {
2692 return;
2693 }
2694
2695 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2696 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2697 mProgram->setUniform2iv(location.value, clampedCount, v);
2698 }
2699
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2700 void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2701 {
2702 ASSERT(!mLinkingState);
2703 if (shouldIgnoreUniform(location))
2704 {
2705 return;
2706 }
2707
2708 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2709 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2710 mProgram->setUniform3iv(location.value, clampedCount, v);
2711 }
2712
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2713 void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2714 {
2715 ASSERT(!mLinkingState);
2716 if (shouldIgnoreUniform(location))
2717 {
2718 return;
2719 }
2720
2721 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2722 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2723 mProgram->setUniform4iv(location.value, clampedCount, v);
2724 }
2725
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2726 void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2727 {
2728 ASSERT(!mLinkingState);
2729 if (shouldIgnoreUniform(location))
2730 {
2731 return;
2732 }
2733
2734 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2735 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2736 mProgram->setUniform1uiv(location.value, clampedCount, v);
2737 }
2738
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2739 void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2740 {
2741 ASSERT(!mLinkingState);
2742 if (shouldIgnoreUniform(location))
2743 {
2744 return;
2745 }
2746
2747 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2748 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2749 mProgram->setUniform2uiv(location.value, clampedCount, v);
2750 }
2751
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2752 void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2753 {
2754 ASSERT(!mLinkingState);
2755 if (shouldIgnoreUniform(location))
2756 {
2757 return;
2758 }
2759
2760 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2761 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2762 mProgram->setUniform3uiv(location.value, clampedCount, v);
2763 }
2764
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2765 void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2766 {
2767 ASSERT(!mLinkingState);
2768 if (shouldIgnoreUniform(location))
2769 {
2770 return;
2771 }
2772
2773 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2774 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2775 mProgram->setUniform4uiv(location.value, clampedCount, v);
2776 }
2777
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2778 void Program::setUniformMatrix2fv(UniformLocation location,
2779 GLsizei count,
2780 GLboolean transpose,
2781 const GLfloat *v)
2782 {
2783 ASSERT(!mLinkingState);
2784 if (shouldIgnoreUniform(location))
2785 {
2786 return;
2787 }
2788
2789 GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
2790 mProgram->setUniformMatrix2fv(location.value, clampedCount, transpose, v);
2791 }
2792
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2793 void Program::setUniformMatrix3fv(UniformLocation location,
2794 GLsizei count,
2795 GLboolean transpose,
2796 const GLfloat *v)
2797 {
2798 ASSERT(!mLinkingState);
2799 if (shouldIgnoreUniform(location))
2800 {
2801 return;
2802 }
2803
2804 GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
2805 mProgram->setUniformMatrix3fv(location.value, clampedCount, transpose, v);
2806 }
2807
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2808 void Program::setUniformMatrix4fv(UniformLocation location,
2809 GLsizei count,
2810 GLboolean transpose,
2811 const GLfloat *v)
2812 {
2813 ASSERT(!mLinkingState);
2814 if (shouldIgnoreUniform(location))
2815 {
2816 return;
2817 }
2818
2819 GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
2820 mProgram->setUniformMatrix4fv(location.value, clampedCount, transpose, v);
2821 }
2822
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2823 void Program::setUniformMatrix2x3fv(UniformLocation location,
2824 GLsizei count,
2825 GLboolean transpose,
2826 const GLfloat *v)
2827 {
2828 ASSERT(!mLinkingState);
2829 if (shouldIgnoreUniform(location))
2830 {
2831 return;
2832 }
2833
2834 GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
2835 mProgram->setUniformMatrix2x3fv(location.value, clampedCount, transpose, v);
2836 }
2837
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2838 void Program::setUniformMatrix2x4fv(UniformLocation location,
2839 GLsizei count,
2840 GLboolean transpose,
2841 const GLfloat *v)
2842 {
2843 ASSERT(!mLinkingState);
2844 if (shouldIgnoreUniform(location))
2845 {
2846 return;
2847 }
2848
2849 GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
2850 mProgram->setUniformMatrix2x4fv(location.value, clampedCount, transpose, v);
2851 }
2852
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2853 void Program::setUniformMatrix3x2fv(UniformLocation location,
2854 GLsizei count,
2855 GLboolean transpose,
2856 const GLfloat *v)
2857 {
2858 ASSERT(!mLinkingState);
2859 if (shouldIgnoreUniform(location))
2860 {
2861 return;
2862 }
2863
2864 GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
2865 mProgram->setUniformMatrix3x2fv(location.value, clampedCount, transpose, v);
2866 }
2867
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2868 void Program::setUniformMatrix3x4fv(UniformLocation location,
2869 GLsizei count,
2870 GLboolean transpose,
2871 const GLfloat *v)
2872 {
2873 ASSERT(!mLinkingState);
2874 if (shouldIgnoreUniform(location))
2875 {
2876 return;
2877 }
2878
2879 GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
2880 mProgram->setUniformMatrix3x4fv(location.value, clampedCount, transpose, v);
2881 }
2882
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2883 void Program::setUniformMatrix4x2fv(UniformLocation location,
2884 GLsizei count,
2885 GLboolean transpose,
2886 const GLfloat *v)
2887 {
2888 ASSERT(!mLinkingState);
2889 if (shouldIgnoreUniform(location))
2890 {
2891 return;
2892 }
2893
2894 GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
2895 mProgram->setUniformMatrix4x2fv(location.value, clampedCount, transpose, v);
2896 }
2897
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2898 void Program::setUniformMatrix4x3fv(UniformLocation location,
2899 GLsizei count,
2900 GLboolean transpose,
2901 const GLfloat *v)
2902 {
2903 ASSERT(!mLinkingState);
2904 if (shouldIgnoreUniform(location))
2905 {
2906 return;
2907 }
2908
2909 GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
2910 mProgram->setUniformMatrix4x3fv(location.value, clampedCount, transpose, v);
2911 }
2912
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2913 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2914 {
2915 ASSERT(!mLinkingState);
2916 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2917 const std::vector<GLuint> &boundTextureUnits =
2918 mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
2919 return (uniformLocation.arrayIndex < boundTextureUnits.size())
2920 ? boundTextureUnits[uniformLocation.arrayIndex]
2921 : 0;
2922 }
2923
getImageUniformBinding(const VariableLocation & uniformLocation) const2924 GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
2925 {
2926 ASSERT(!mLinkingState);
2927 GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
2928
2929 const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings();
2930 const std::vector<GLuint> &boundImageUnits = imageBindings[imageIndex].boundImageUnits;
2931 return boundImageUnits[uniformLocation.arrayIndex];
2932 }
2933
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2934 void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const
2935 {
2936 ASSERT(!mLinkingState);
2937 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2938 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2939
2940 if (uniform.isSampler())
2941 {
2942 *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2943 return;
2944 }
2945 else if (uniform.isImage())
2946 {
2947 *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2948 return;
2949 }
2950
2951 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2952 if (nativeType == GL_FLOAT)
2953 {
2954 mProgram->getUniformfv(context, location.value, v);
2955 }
2956 else
2957 {
2958 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2959 }
2960 }
2961
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2962 void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const
2963 {
2964 ASSERT(!mLinkingState);
2965 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2966 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2967
2968 if (uniform.isSampler())
2969 {
2970 *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2971 return;
2972 }
2973 else if (uniform.isImage())
2974 {
2975 *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2976 return;
2977 }
2978
2979 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2980 if (nativeType == GL_INT || nativeType == GL_BOOL)
2981 {
2982 mProgram->getUniformiv(context, location.value, v);
2983 }
2984 else
2985 {
2986 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2987 }
2988 }
2989
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2990 void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const
2991 {
2992 ASSERT(!mLinkingState);
2993 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2994 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2995
2996 if (uniform.isSampler())
2997 {
2998 *v = getSamplerUniformBinding(uniformLocation);
2999 return;
3000 }
3001 else if (uniform.isImage())
3002 {
3003 *v = getImageUniformBinding(uniformLocation);
3004 return;
3005 }
3006
3007 const GLenum nativeType = VariableComponentType(uniform.type);
3008 if (nativeType == GL_UNSIGNED_INT)
3009 {
3010 mProgram->getUniformuiv(context, location.value, v);
3011 }
3012 else
3013 {
3014 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
3015 }
3016 }
3017
flagForDeletion()3018 void Program::flagForDeletion()
3019 {
3020 ASSERT(!mLinkingState);
3021 mDeleteStatus = true;
3022 }
3023
isFlaggedForDeletion() const3024 bool Program::isFlaggedForDeletion() const
3025 {
3026 ASSERT(!mLinkingState);
3027 return mDeleteStatus;
3028 }
3029
validate(const Caps & caps)3030 void Program::validate(const Caps &caps)
3031 {
3032 ASSERT(!mLinkingState);
3033 mState.mExecutable->resetInfoLog();
3034 InfoLog &infoLog = mState.mExecutable->getInfoLog();
3035
3036 if (mLinked)
3037 {
3038 mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
3039 }
3040 else
3041 {
3042 infoLog << "Program has not been successfully linked.";
3043 }
3044 }
3045
isValidated() const3046 bool Program::isValidated() const
3047 {
3048 ASSERT(!mLinkingState);
3049 return mValidated;
3050 }
3051
getActiveUniformBlockName(const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3052 void Program::getActiveUniformBlockName(const UniformBlockIndex blockIndex,
3053 GLsizei bufSize,
3054 GLsizei *length,
3055 GLchar *blockName) const
3056 {
3057 ASSERT(!mLinkingState);
3058 GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
3059 blockName);
3060 }
3061
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3062 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
3063 GLsizei bufSize,
3064 GLsizei *length,
3065 GLchar *blockName) const
3066 {
3067 ASSERT(!mLinkingState);
3068 GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize,
3069 length, blockName);
3070 }
3071
3072 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const3073 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
3074 {
3075 int maxLength = 0;
3076
3077 if (mLinked)
3078 {
3079 for (const T &resource : resources)
3080 {
3081 if (!resource.name.empty())
3082 {
3083 int length = static_cast<int>(resource.nameWithArrayIndex().length());
3084 maxLength = std::max(length + 1, maxLength);
3085 }
3086 }
3087 }
3088
3089 return maxLength;
3090 }
3091
getActiveUniformBlockMaxNameLength() const3092 GLint Program::getActiveUniformBlockMaxNameLength() const
3093 {
3094 ASSERT(!mLinkingState);
3095 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
3096 }
3097
getActiveShaderStorageBlockMaxNameLength() const3098 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
3099 {
3100 ASSERT(!mLinkingState);
3101 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
3102 }
3103
getUniformBlockIndex(const std::string & name) const3104 GLuint Program::getUniformBlockIndex(const std::string &name) const
3105 {
3106 ASSERT(!mLinkingState);
3107 return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
3108 }
3109
getShaderStorageBlockIndex(const std::string & name) const3110 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
3111 {
3112 ASSERT(!mLinkingState);
3113 return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
3114 }
3115
getUniformBlockByIndex(GLuint index) const3116 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
3117 {
3118 ASSERT(!mLinkingState);
3119 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
3120 return mState.mExecutable->getUniformBlocks()[index];
3121 }
3122
getShaderStorageBlockByIndex(GLuint index) const3123 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
3124 {
3125 ASSERT(!mLinkingState);
3126 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
3127 return mState.mExecutable->getShaderStorageBlocks()[index];
3128 }
3129
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)3130 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
3131 {
3132 ASSERT(!mLinkingState);
3133 mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding;
3134 mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value,
3135 uniformBlockBinding != 0);
3136 mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value);
3137 }
3138
getUniformBlockBinding(GLuint uniformBlockIndex) const3139 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
3140 {
3141 ASSERT(!mLinkingState);
3142 return mState.getUniformBlockBinding(uniformBlockIndex);
3143 }
3144
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const3145 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
3146 {
3147 ASSERT(!mLinkingState);
3148 return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
3149 }
3150
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)3151 void Program::setTransformFeedbackVaryings(GLsizei count,
3152 const GLchar *const *varyings,
3153 GLenum bufferMode)
3154 {
3155 ASSERT(!mLinkingState);
3156 mState.mTransformFeedbackVaryingNames.resize(count);
3157 for (GLsizei i = 0; i < count; i++)
3158 {
3159 mState.mTransformFeedbackVaryingNames[i] = varyings[i];
3160 }
3161
3162 mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
3163 }
3164
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const3165 void Program::getTransformFeedbackVarying(GLuint index,
3166 GLsizei bufSize,
3167 GLsizei *length,
3168 GLsizei *size,
3169 GLenum *type,
3170 GLchar *name) const
3171 {
3172 ASSERT(!mLinkingState);
3173 if (mLinked)
3174 {
3175 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3176 const auto &var = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3177 std::string varName = var.nameWithArrayIndex();
3178 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
3179 if (length)
3180 {
3181 *length = lastNameIdx;
3182 }
3183 if (size)
3184 {
3185 *size = var.size();
3186 }
3187 if (type)
3188 {
3189 *type = var.type;
3190 }
3191 if (name)
3192 {
3193 memcpy(name, varName.c_str(), lastNameIdx);
3194 name[lastNameIdx] = '\0';
3195 }
3196 }
3197 }
3198
getTransformFeedbackVaryingCount() const3199 GLsizei Program::getTransformFeedbackVaryingCount() const
3200 {
3201 ASSERT(!mLinkingState);
3202 if (mLinked)
3203 {
3204 return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3205 }
3206 else
3207 {
3208 return 0;
3209 }
3210 }
3211
getTransformFeedbackVaryingMaxLength() const3212 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
3213 {
3214 ASSERT(!mLinkingState);
3215 if (mLinked)
3216 {
3217 GLsizei maxSize = 0;
3218 for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
3219 {
3220 maxSize =
3221 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
3222 }
3223
3224 return maxSize;
3225 }
3226 else
3227 {
3228 return 0;
3229 }
3230 }
3231
getTransformFeedbackBufferMode() const3232 GLenum Program::getTransformFeedbackBufferMode() const
3233 {
3234 ASSERT(!mLinkingState);
3235 return mState.mExecutable->getTransformFeedbackBufferMode();
3236 }
3237
linkValidateShaders(InfoLog & infoLog)3238 bool Program::linkValidateShaders(InfoLog &infoLog)
3239 {
3240 const ShaderMap<Shader *> &shaders = mState.mAttachedShaders;
3241
3242 bool isComputeShaderAttached = shaders[ShaderType::Compute] != nullptr;
3243 bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] ||
3244 shaders[ShaderType::TessControl] ||
3245 shaders[ShaderType::TessEvaluation] ||
3246 shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment];
3247 // Check whether we both have a compute and non-compute shaders attached.
3248 // If there are of both types attached, then linking should fail.
3249 // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
3250 if (isComputeShaderAttached && isGraphicsShaderAttached)
3251 {
3252 infoLog << "Both compute and graphics shaders are attached to the same program.";
3253 return false;
3254 }
3255
3256 Optional<int> version;
3257 for (ShaderType shaderType : kAllGraphicsShaderTypes)
3258 {
3259 Shader *shader = shaders[shaderType];
3260 ASSERT(!shader || shader->getType() == shaderType);
3261 if (!shader)
3262 {
3263 continue;
3264 }
3265
3266 if (!shader->isCompiled())
3267 {
3268 infoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
3269 return false;
3270 }
3271
3272 if (!version.valid())
3273 {
3274 version = shader->getShaderVersion();
3275 }
3276 else if (version != shader->getShaderVersion())
3277 {
3278 infoLog << ShaderTypeToString(shaderType)
3279 << " shader version does not match other shader versions.";
3280 return false;
3281 }
3282 }
3283
3284 if (isComputeShaderAttached)
3285 {
3286 ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute);
3287
3288 mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize();
3289
3290 // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
3291 // If the work group size is not specified, a link time error should occur.
3292 if (!mState.mComputeShaderLocalSize.isDeclared())
3293 {
3294 infoLog << "Work group size is not specified.";
3295 return false;
3296 }
3297 }
3298 else
3299 {
3300 if (!isGraphicsShaderAttached)
3301 {
3302 infoLog << "No compiled shaders.";
3303 return false;
3304 }
3305
3306 bool hasVertex = shaders[ShaderType::Vertex] != nullptr;
3307 bool hasFragment = shaders[ShaderType::Fragment] != nullptr;
3308 if (!isSeparable() && (!hasVertex || !hasFragment))
3309 {
3310 infoLog
3311 << "The program must contain objects to form both a vertex and fragment shader.";
3312 return false;
3313 }
3314
3315 bool hasTessControl = shaders[ShaderType::TessControl] != nullptr;
3316 bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr;
3317 if (!isSeparable() && (hasTessControl != hasTessEvaluation))
3318 {
3319 infoLog << "Tessellation control and evaluation shaders must be specified together.";
3320 return false;
3321 }
3322
3323 Shader *geometryShader = shaders[ShaderType::Geometry];
3324 if (shaders[ShaderType::Geometry])
3325 {
3326 // [GL_EXT_geometry_shader] Chapter 7
3327 // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
3328 // Language Specification, as well as any of the following reasons:
3329 // * One or more of the shader objects attached to <program> are not compiled
3330 // successfully.
3331 // * The shaders do not use the same shader language version.
3332 // * <program> contains objects to form a geometry shader, and
3333 // - <program> is not separable and contains no objects to form a vertex shader; or
3334 // - the input primitive type, output primitive type, or maximum output vertex count
3335 // is not specified in the compiled geometry shader object.
3336 ASSERT(geometryShader->getType() == ShaderType::Geometry);
3337
3338 Optional<PrimitiveMode> inputPrimitive =
3339 geometryShader->getGeometryShaderInputPrimitiveType();
3340 if (!inputPrimitive.valid())
3341 {
3342 infoLog << "Input primitive type is not specified in the geometry shader.";
3343 return false;
3344 }
3345
3346 Optional<PrimitiveMode> outputPrimitive =
3347 geometryShader->getGeometryShaderOutputPrimitiveType();
3348 if (!outputPrimitive.valid())
3349 {
3350 infoLog << "Output primitive type is not specified in the geometry shader.";
3351 return false;
3352 }
3353
3354 Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
3355 if (!maxVertices.valid())
3356 {
3357 infoLog << "'max_vertices' is not specified in the geometry shader.";
3358 return false;
3359 }
3360
3361 mState.mExecutable->mGeometryShaderInputPrimitiveType = inputPrimitive.value();
3362 mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
3363 mState.mExecutable->mGeometryShaderMaxVertices = maxVertices.value();
3364 mState.mExecutable->mGeometryShaderInvocations =
3365 geometryShader->getGeometryShaderInvocations();
3366 }
3367
3368 Shader *tessControlShader = shaders[ShaderType::TessControl];
3369 if (tessControlShader)
3370 {
3371 int tcsShaderVertices = tessControlShader->getTessControlShaderVertices();
3372 if (tcsShaderVertices == 0)
3373 {
3374 // In tessellation control shader, output vertices should be specified at least
3375 // once.
3376 // > GLSL ES Version 3.20.6 spec:
3377 // > 4.4.2. Output Layout Qualifiers
3378 // > Tessellation Control Outputs
3379 // > ...
3380 // > There must be at least one layout qualifier specifying an output patch vertex
3381 // > count in any program containing a tessellation control shader.
3382 infoLog << "In Tessellation Control Shader, at least one layout qualifier "
3383 "specifying an output patch vertex count must exist.";
3384 return false;
3385 }
3386
3387 mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
3388 }
3389
3390 Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
3391 if (tessEvaluationShader)
3392 {
3393 GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode();
3394 if (tesPrimitiveMode == 0)
3395 {
3396 // In tessellation evaluation shader, a primitive mode should be specified at least
3397 // once.
3398 // > GLSL ES Version 3.20.6 spec:
3399 // > 4.4.1. Input Layout Qualifiers
3400 // > Tessellation Evaluation Inputs
3401 // > ...
3402 // > The tessellation evaluation shader object in a program must declare a primitive
3403 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
3404 // > identifiers is optional.
3405 infoLog << "The Tessellation Evaluation Shader object in a program must declare a "
3406 "primitive mode in its input layout.";
3407 return false;
3408 }
3409
3410 mState.mExecutable->mTessGenMode = tesPrimitiveMode;
3411 mState.mExecutable->mTessGenSpacing = tessEvaluationShader->getTessGenSpacing();
3412 mState.mExecutable->mTessGenVertexOrder = tessEvaluationShader->getTessGenVertexOrder();
3413 mState.mExecutable->mTessGenPointMode = tessEvaluationShader->getTessGenPointMode();
3414 }
3415 }
3416
3417 return true;
3418 }
3419
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const3420 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
3421 {
3422 ASSERT(!mLinkingState);
3423 for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
3424 ++tfIndex)
3425 {
3426 const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
3427 if (tf.nameWithArrayIndex() == name)
3428 {
3429 return tfIndex;
3430 }
3431 }
3432 return GL_INVALID_INDEX;
3433 }
3434
getTransformFeedbackVaryingResource(GLuint index) const3435 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
3436 {
3437 ASSERT(!mLinkingState);
3438 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3439 return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3440 }
3441
hasDrawIDUniform() const3442 bool Program::hasDrawIDUniform() const
3443 {
3444 ASSERT(!mLinkingState);
3445 return mState.mDrawIDLocation >= 0;
3446 }
3447
setDrawIDUniform(GLint drawid)3448 void Program::setDrawIDUniform(GLint drawid)
3449 {
3450 ASSERT(!mLinkingState);
3451 ASSERT(mState.mDrawIDLocation >= 0);
3452 mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
3453 }
3454
hasBaseVertexUniform() const3455 bool Program::hasBaseVertexUniform() const
3456 {
3457 ASSERT(!mLinkingState);
3458 return mState.mBaseVertexLocation >= 0;
3459 }
3460
setBaseVertexUniform(GLint baseVertex)3461 void Program::setBaseVertexUniform(GLint baseVertex)
3462 {
3463 ASSERT(!mLinkingState);
3464 ASSERT(mState.mBaseVertexLocation >= 0);
3465 if (baseVertex == mState.mCachedBaseVertex)
3466 {
3467 return;
3468 }
3469 mState.mCachedBaseVertex = baseVertex;
3470 mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
3471 }
3472
hasBaseInstanceUniform() const3473 bool Program::hasBaseInstanceUniform() const
3474 {
3475 ASSERT(!mLinkingState);
3476 return mState.mBaseInstanceLocation >= 0;
3477 }
3478
setBaseInstanceUniform(GLuint baseInstance)3479 void Program::setBaseInstanceUniform(GLuint baseInstance)
3480 {
3481 ASSERT(!mLinkingState);
3482 ASSERT(mState.mBaseInstanceLocation >= 0);
3483 if (baseInstance == mState.mCachedBaseInstance)
3484 {
3485 return;
3486 }
3487 mState.mCachedBaseInstance = baseInstance;
3488 GLint baseInstanceInt = baseInstance;
3489 mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
3490 }
3491
linkVaryings(InfoLog & infoLog) const3492 bool Program::linkVaryings(InfoLog &infoLog) const
3493 {
3494 ShaderType previousShaderType = ShaderType::InvalidEnum;
3495 for (ShaderType shaderType : kAllGraphicsShaderTypes)
3496 {
3497 Shader *currentShader = mState.mAttachedShaders[shaderType];
3498 if (!currentShader)
3499 {
3500 continue;
3501 }
3502
3503 if (previousShaderType != ShaderType::InvalidEnum)
3504 {
3505 Shader *previousShader = mState.mAttachedShaders[previousShaderType];
3506 const std::vector<sh::ShaderVariable> &outputVaryings =
3507 previousShader->getOutputVaryings();
3508
3509 if (!LinkValidateShaderInterfaceMatching(
3510 outputVaryings, currentShader->getInputVaryings(), previousShaderType,
3511 currentShader->getType(), previousShader->getShaderVersion(),
3512 currentShader->getShaderVersion(), isSeparable(), infoLog))
3513 {
3514 return false;
3515 }
3516 }
3517 previousShaderType = currentShader->getType();
3518 }
3519
3520 // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
3521 // Need to move logic of validating builtin varyings inside the for-loop above.
3522 // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
3523 // can be redeclared in Geometry or Tessellation shaders as well.
3524 Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
3525 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
3526 if (vertexShader && fragmentShader &&
3527 !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
3528 fragmentShader->getInputVaryings(), vertexShader->getType(),
3529 fragmentShader->getType(), vertexShader->getShaderVersion(),
3530 fragmentShader->getShaderVersion(), infoLog))
3531 {
3532 return false;
3533 }
3534
3535 return true;
3536 }
3537
linkUniforms(const Caps & caps,const Version & version,InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings,GLuint * combinedImageUniformsCount,std::vector<UnusedUniform> * unusedUniforms)3538 bool Program::linkUniforms(const Caps &caps,
3539 const Version &version,
3540 InfoLog &infoLog,
3541 const ProgramAliasedBindings &uniformLocationBindings,
3542 GLuint *combinedImageUniformsCount,
3543 std::vector<UnusedUniform> *unusedUniforms)
3544 {
3545 UniformLinker linker(mState);
3546 if (!linker.link(caps, infoLog, uniformLocationBindings))
3547 {
3548 return false;
3549 }
3550
3551 linker.getResults(&mState.mExecutable->mUniforms, unusedUniforms, &mState.mUniformLocations);
3552
3553 linkSamplerAndImageBindings(combinedImageUniformsCount);
3554
3555 if (!linkAtomicCounterBuffers())
3556 {
3557 return false;
3558 }
3559
3560 if (version >= Version(3, 1))
3561 {
3562 GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size());
3563
3564 if (locationSize > caps.maxUniformLocations)
3565 {
3566 infoLog << "Exceeded maximum uniform location size";
3567 return false;
3568 }
3569 }
3570
3571 return true;
3572 }
3573
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)3574 void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
3575 {
3576 ASSERT(combinedImageUniforms);
3577
3578 // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
3579 // atomic counters, images and samplers in that order.
3580 auto highIter = mState.mExecutable->getUniforms().rbegin();
3581 auto lowIter = highIter;
3582
3583 unsigned int high = static_cast<unsigned int>(mState.mExecutable->getUniforms().size());
3584 unsigned int low = high;
3585
3586 // Note that uniform block uniforms are not yet appended to this list.
3587 ASSERT(mState.mExecutable->getUniforms().size() == 0 || highIter->isAtomicCounter() ||
3588 highIter->isImage() || highIter->isSampler() || highIter->isInDefaultBlock() ||
3589 highIter->isFragmentInOut);
3590
3591 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isFragmentInOut;
3592 ++lowIter)
3593 {
3594 --low;
3595 }
3596
3597 mState.mExecutable->mFragmentInoutRange = RangeUI(low, high);
3598
3599 highIter = lowIter;
3600 high = low;
3601
3602 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isAtomicCounter();
3603 ++lowIter)
3604 {
3605 --low;
3606 }
3607
3608 mState.mAtomicCounterUniformRange = RangeUI(low, high);
3609
3610 highIter = lowIter;
3611 high = low;
3612
3613 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isImage(); ++lowIter)
3614 {
3615 --low;
3616 }
3617
3618 mState.mExecutable->mImageUniformRange = RangeUI(low, high);
3619 *combinedImageUniforms = 0u;
3620 // The Program is still linking, so getExecutable().isCompute() isn't accurate yet.
3621 bool hasComputeShader = mState.mAttachedShaders[ShaderType::Compute] != nullptr;
3622 std::vector<ImageBinding> &imageBindings = hasComputeShader
3623 ? mState.mExecutable->mComputeImageBindings
3624 : mState.mExecutable->mGraphicsImageBindings;
3625 // If uniform is a image type, insert it into the mImageBindings array.
3626 for (unsigned int imageIndex : mState.mExecutable->getImageUniformRange())
3627 {
3628 // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
3629 // cannot load values into a uniform defined as an image. if declare without a
3630 // binding qualifier, any uniform image variable (include all elements of
3631 // unbound image array) shoud be bound to unit zero.
3632 auto &imageUniform = mState.mExecutable->getUniforms()[imageIndex];
3633 TextureType textureType = ImageTypeToTextureType(imageUniform.type);
3634 const GLuint arraySize = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
3635
3636 if (imageUniform.binding == -1)
3637 {
3638 imageBindings.emplace_back(
3639 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
3640 }
3641 else
3642 {
3643 // The arrays of arrays are flattened to arrays, it needs to record the array offset for
3644 // the correct binding image unit.
3645 imageBindings.emplace_back(
3646 ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize,
3647 imageUniform.getBasicTypeElementCount(), textureType));
3648 }
3649
3650 *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
3651 }
3652
3653 highIter = lowIter;
3654 high = low;
3655
3656 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isSampler(); ++lowIter)
3657 {
3658 --low;
3659 }
3660
3661 mState.mExecutable->mSamplerUniformRange = RangeUI(low, high);
3662
3663 // If uniform is a sampler type, insert it into the mSamplerBindings array.
3664 for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
3665 {
3666 const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
3667 TextureType textureType = SamplerTypeToTextureType(samplerUniform.type);
3668 GLenum samplerType = samplerUniform.typeInfo->type;
3669 unsigned int elementCount = samplerUniform.getBasicTypeElementCount();
3670 SamplerFormat format = samplerUniform.typeInfo->samplerFormat;
3671 mState.mExecutable->mSamplerBindings.emplace_back(textureType, samplerType, format,
3672 elementCount);
3673 }
3674
3675 // Whatever is left constitutes the default uniforms.
3676 mState.mExecutable->mDefaultUniformRange = RangeUI(0, low);
3677 }
3678
linkAtomicCounterBuffers()3679 bool Program::linkAtomicCounterBuffers()
3680 {
3681 for (unsigned int index : mState.mAtomicCounterUniformRange)
3682 {
3683 auto &uniform = mState.mExecutable->mUniforms[index];
3684 uniform.blockInfo.offset = uniform.offset;
3685 uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0);
3686 uniform.blockInfo.matrixStride = 0;
3687 uniform.blockInfo.isRowMajorMatrix = false;
3688
3689 bool found = false;
3690 for (unsigned int bufferIndex = 0;
3691 bufferIndex < mState.mExecutable->getActiveAtomicCounterBufferCount(); ++bufferIndex)
3692 {
3693 auto &buffer = mState.mExecutable->mAtomicCounterBuffers[bufferIndex];
3694 if (buffer.binding == uniform.binding)
3695 {
3696 buffer.memberIndexes.push_back(index);
3697 uniform.bufferIndex = bufferIndex;
3698 found = true;
3699 buffer.unionReferencesWith(uniform);
3700 break;
3701 }
3702 }
3703 if (!found)
3704 {
3705 AtomicCounterBuffer atomicCounterBuffer;
3706 atomicCounterBuffer.binding = uniform.binding;
3707 atomicCounterBuffer.memberIndexes.push_back(index);
3708 atomicCounterBuffer.unionReferencesWith(uniform);
3709 mState.mExecutable->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
3710 uniform.bufferIndex =
3711 static_cast<int>(mState.mExecutable->getActiveAtomicCounterBufferCount() - 1);
3712 }
3713 }
3714 // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
3715 // gl_Max[Vertex|Fragment|Compute|Geometry|Combined]AtomicCounterBuffers.
3716
3717 return true;
3718 }
3719
3720 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3721 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3722 {
3723 const Caps &caps = context->getCaps();
3724 const Limitations &limitations = context->getLimitations();
3725 bool webglCompatibility = context->getExtensions().webglCompatibility;
3726 int shaderVersion = -1;
3727 unsigned int usedLocations = 0;
3728
3729 Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
3730
3731 if (!vertexShader)
3732 {
3733 // No vertex shader, so no attributes, so nothing to do
3734 return true;
3735 }
3736
3737 shaderVersion = vertexShader->getShaderVersion();
3738 if (shaderVersion >= 300)
3739 {
3740 // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
3741 // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
3742 // aliasing checks.
3743 mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes();
3744 }
3745 else
3746 {
3747 // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3748 mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes();
3749 }
3750
3751 GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
3752 std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
3753
3754 // Assign locations to attributes that have a binding location and check for attribute aliasing.
3755 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3756 {
3757 // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3758 // structures, so we don't need to worry about adjusting their names or generating entries
3759 // for each member/element (unlike uniforms for example).
3760 ASSERT(!attribute.isArray() && !attribute.isStruct());
3761
3762 int bindingLocation = mAttributeBindings.getBinding(attribute);
3763 if (attribute.location == -1 && bindingLocation != -1)
3764 {
3765 attribute.location = bindingLocation;
3766 }
3767
3768 if (attribute.location != -1)
3769 {
3770 // Location is set by glBindAttribLocation or by location layout qualifier
3771 const int regs = VariableRegisterCount(attribute.type);
3772
3773 if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3774 {
3775 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3776 << " is too big to fit";
3777
3778 return false;
3779 }
3780
3781 for (int reg = 0; reg < regs; reg++)
3782 {
3783 const int regLocation = attribute.location + reg;
3784 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3785
3786 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3787 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3788 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3789 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3790 if (linkedAttribute)
3791 {
3792 if (shaderVersion >= 300 || webglCompatibility ||
3793 limitations.noVertexAttributeAliasing)
3794 {
3795 infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3796 << linkedAttribute->name << "' at location " << regLocation;
3797 return false;
3798 }
3799 }
3800 else
3801 {
3802 usedAttribMap[regLocation] = &attribute;
3803 }
3804
3805 usedLocations |= 1 << regLocation;
3806 }
3807 }
3808 }
3809
3810 // Assign locations to attributes that don't have a binding location.
3811 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3812 {
3813 // Not set by glBindAttribLocation or by location layout qualifier
3814 if (attribute.location == -1)
3815 {
3816 int regs = VariableRegisterCount(attribute.type);
3817 int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3818
3819 if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3820 {
3821 infoLog << "Too many attributes (" << attribute.name << ")";
3822 return false;
3823 }
3824
3825 attribute.location = availableIndex;
3826 }
3827 }
3828
3829 ASSERT(mState.mExecutable->mAttributesTypeMask.none());
3830 ASSERT(mState.mExecutable->mAttributesMask.none());
3831
3832 // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3833 // shader versions we're only processing active attributes to begin with.
3834 if (shaderVersion >= 300)
3835 {
3836 for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
3837 attributeIter != mState.mExecutable->getProgramInputs().end();)
3838 {
3839 if (attributeIter->active)
3840 {
3841 ++attributeIter;
3842 }
3843 else
3844 {
3845 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
3846 }
3847 }
3848 }
3849
3850 for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
3851 {
3852 ASSERT(attribute.active);
3853 ASSERT(attribute.location != -1);
3854 unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3855
3856 unsigned int location = static_cast<unsigned int>(attribute.location);
3857 for (unsigned int r = 0; r < regs; r++)
3858 {
3859 // Built-in active program inputs don't have a bound attribute.
3860 if (!attribute.isBuiltIn())
3861 {
3862 mState.mExecutable->mActiveAttribLocationsMask.set(location);
3863 mState.mExecutable->mMaxActiveAttribLocation =
3864 std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
3865
3866 ComponentType componentType =
3867 GLenumToComponentType(VariableComponentType(attribute.type));
3868
3869 SetComponentTypeMask(componentType, location,
3870 &mState.mExecutable->mAttributesTypeMask);
3871 mState.mExecutable->mAttributesMask.set(location);
3872
3873 location++;
3874 }
3875 }
3876 }
3877
3878 return true;
3879 }
3880
linkInterfaceBlocks(const Caps & caps,const Version & version,bool webglCompatibility,InfoLog & infoLog,GLuint * combinedShaderStorageBlocksCount)3881 bool Program::linkInterfaceBlocks(const Caps &caps,
3882 const Version &version,
3883 bool webglCompatibility,
3884 InfoLog &infoLog,
3885 GLuint *combinedShaderStorageBlocksCount)
3886 {
3887 ASSERT(combinedShaderStorageBlocksCount);
3888
3889 GLuint combinedUniformBlocksCount = 0u;
3890 GLuint numShadersHasUniformBlocks = 0u;
3891 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
3892 InterfaceBlockMap instancelessInterfaceBlocksFields;
3893
3894 for (ShaderType shaderType : AllShaderTypes())
3895 {
3896 Shader *shader = mState.mAttachedShaders[shaderType];
3897 if (!shader)
3898 {
3899 continue;
3900 }
3901
3902 const auto &uniformBlocks = shader->getUniformBlocks();
3903 if (!uniformBlocks.empty())
3904 {
3905 if (!ValidateInterfaceBlocksCount(
3906 static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks,
3907 shaderType, sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
3908 {
3909 return false;
3910 }
3911
3912 allShaderUniformBlocks[shaderType] = &uniformBlocks;
3913 ++numShadersHasUniformBlocks;
3914 }
3915 }
3916
3917 if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks))
3918 {
3919 infoLog << "The sum of the number of active uniform blocks exceeds "
3920 "MAX_COMBINED_UNIFORM_BLOCKS ("
3921 << caps.maxCombinedUniformBlocks << ").";
3922 return false;
3923 }
3924
3925 if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
3926 webglCompatibility, &instancelessInterfaceBlocksFields))
3927 {
3928 return false;
3929 }
3930
3931 if (version >= Version(3, 1))
3932 {
3933 *combinedShaderStorageBlocksCount = 0u;
3934 GLuint numShadersHasShaderStorageBlocks = 0u;
3935 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
3936 for (ShaderType shaderType : AllShaderTypes())
3937 {
3938 Shader *shader = mState.mAttachedShaders[shaderType];
3939 if (!shader)
3940 {
3941 continue;
3942 }
3943
3944 const auto &shaderStorageBlocks = shader->getShaderStorageBlocks();
3945 if (!shaderStorageBlocks.empty())
3946 {
3947 if (!ValidateInterfaceBlocksCount(
3948 static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]),
3949 shaderStorageBlocks, shaderType, sh::BlockType::BLOCK_BUFFER,
3950 combinedShaderStorageBlocksCount, infoLog))
3951 {
3952 return false;
3953 }
3954
3955 allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
3956 ++numShadersHasShaderStorageBlocks;
3957 }
3958 }
3959
3960 if (*combinedShaderStorageBlocksCount >
3961 static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks))
3962 {
3963 infoLog << "The sum of the number of active shader storage blocks exceeds "
3964 "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
3965 << caps.maxCombinedShaderStorageBlocks << ").";
3966 return false;
3967 }
3968
3969 if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
3970 infoLog, webglCompatibility,
3971 &instancelessInterfaceBlocksFields))
3972 {
3973 return false;
3974 }
3975 }
3976
3977 return true;
3978 }
3979
getOutputLocationForLink(const sh::ShaderVariable & outputVariable) const3980 int Program::getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const
3981 {
3982 if (outputVariable.location != -1)
3983 {
3984 return outputVariable.location;
3985 }
3986 int apiLocation = mFragmentOutputLocations.getBinding(outputVariable);
3987 if (apiLocation != -1)
3988 {
3989 return apiLocation;
3990 }
3991 return -1;
3992 }
3993
isOutputSecondaryForLink(const sh::ShaderVariable & outputVariable) const3994 bool Program::isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const
3995 {
3996 if (outputVariable.index != -1)
3997 {
3998 ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
3999 return (outputVariable.index == 1);
4000 }
4001 int apiIndex = mFragmentOutputIndexes.getBinding(outputVariable);
4002 if (apiIndex != -1)
4003 {
4004 // Index layout qualifier from the shader takes precedence, so the index from the API is
4005 // checked only if the index was not set in the shader. This is not specified in the EXT
4006 // spec, but is specified in desktop OpenGL specs.
4007 return (apiIndex == 1);
4008 }
4009 // EXT_blend_func_extended: Outputs get index 0 by default.
4010 return false;
4011 }
4012
4013 namespace
4014 {
4015
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)4016 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
4017 unsigned int baseLocation,
4018 unsigned int elementCount,
4019 const std::vector<VariableLocation> &reservedLocations,
4020 unsigned int variableIndex)
4021 {
4022 if (baseLocation + elementCount > outputLocations.size())
4023 {
4024 elementCount = baseLocation < outputLocations.size()
4025 ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
4026 : 0;
4027 }
4028 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4029 {
4030 const unsigned int location = baseLocation + elementIndex;
4031 if (outputLocations[location].used())
4032 {
4033 VariableLocation locationInfo(elementIndex, variableIndex);
4034 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4035 reservedLocations.end())
4036 {
4037 return true;
4038 }
4039 }
4040 }
4041 return false;
4042 }
4043
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex,sh::ShaderVariable & outputVariable)4044 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
4045 unsigned int baseLocation,
4046 unsigned int elementCount,
4047 const std::vector<VariableLocation> &reservedLocations,
4048 unsigned int variableIndex,
4049 sh::ShaderVariable &outputVariable)
4050 {
4051 if (baseLocation + elementCount > outputLocations.size())
4052 {
4053 outputLocations.resize(baseLocation + elementCount);
4054 }
4055 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4056 {
4057 VariableLocation locationInfo(elementIndex, variableIndex);
4058 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4059 reservedLocations.end())
4060 {
4061 outputVariable.location = baseLocation;
4062 const unsigned int location = baseLocation + elementIndex;
4063 outputLocations[location] = locationInfo;
4064 }
4065 }
4066 }
4067
4068 } // anonymous namespace
4069
linkOutputVariables(const Caps & caps,const Extensions & extensions,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount)4070 bool Program::linkOutputVariables(const Caps &caps,
4071 const Extensions &extensions,
4072 const Version &version,
4073 GLuint combinedImageUniformsCount,
4074 GLuint combinedShaderStorageBlocksCount)
4075 {
4076 InfoLog &infoLog = mState.mExecutable->getInfoLog();
4077 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
4078
4079 ASSERT(mState.mOutputVariableTypes.empty());
4080 ASSERT(mState.mActiveOutputVariables.none());
4081 ASSERT(mState.mDrawBufferTypeMask.none());
4082 ASSERT(!mState.mYUVOutput);
4083
4084 if (!fragmentShader)
4085 {
4086 // No fragment shader, so nothing to link
4087 return true;
4088 }
4089
4090 const std::vector<sh::ShaderVariable> &outputVariables =
4091 fragmentShader->getActiveOutputVariables();
4092
4093 // Gather output variable types
4094 for (const sh::ShaderVariable &outputVariable : outputVariables)
4095 {
4096 if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
4097 outputVariable.name != "gl_FragData")
4098 {
4099 continue;
4100 }
4101
4102 unsigned int baseLocation =
4103 (outputVariable.location == -1 ? 0u
4104 : static_cast<unsigned int>(outputVariable.location));
4105
4106 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4107 // structures, so we may use getBasicTypeElementCount().
4108 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4109 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4110 {
4111 const unsigned int location = baseLocation + elementIndex;
4112 if (location >= mState.mOutputVariableTypes.size())
4113 {
4114 mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
4115 }
4116 ASSERT(location < mState.mActiveOutputVariables.size());
4117 mState.mActiveOutputVariables.set(location);
4118 mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
4119 ComponentType componentType =
4120 GLenumToComponentType(mState.mOutputVariableTypes[location]);
4121 SetComponentTypeMask(componentType, location, &mState.mDrawBufferTypeMask);
4122 }
4123
4124 if (outputVariable.yuv)
4125 {
4126 ASSERT(outputVariables.size() == 1);
4127 mState.mYUVOutput = true;
4128 }
4129 }
4130
4131 if (version >= ES_3_1)
4132 {
4133 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
4134 // A link error will be generated if the sum of the number of active image uniforms used in
4135 // all shaders, the number of active shader storage blocks, and the number of active
4136 // fragment shader outputs exceeds the implementation-dependent value of
4137 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
4138 if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
4139 mState.mActiveOutputVariables.count() >
4140 static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
4141 {
4142 infoLog
4143 << "The sum of the number of active image uniforms, active shader storage blocks "
4144 "and active fragment shader outputs exceeds "
4145 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
4146 << caps.maxCombinedShaderOutputResources << ")";
4147 return false;
4148 }
4149 }
4150
4151 // Skip this step for GLES2 shaders.
4152 if (fragmentShader && fragmentShader->getShaderVersion() == 100)
4153 return true;
4154
4155 mState.mExecutable->mOutputVariables = outputVariables;
4156 mState.mExecutable->mYUVOutput = mState.mYUVOutput;
4157 // TODO(jmadill): any caps validation here?
4158
4159 // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
4160 // output array in explicit terms.
4161 //
4162 // Assuming fragData is an output array, you can defend the position that:
4163 // P1) you must support binding "fragData" because it's specified
4164 // P2) you must support querying "fragData[x]" because it's specified
4165 // P3) you must support binding "fragData[0]" because it's a frequently used pattern
4166 //
4167 // Then you can make the leap of faith:
4168 // P4) you must support binding "fragData[x]" because you support "fragData[0]"
4169 // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
4170 //
4171 // The spec brings in the "world of arrays" when it mentions binding the arrays and the
4172 // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
4173 // must infer the only possible interpretation (?). Note again: this need of interpretation
4174 // might be completely off of what GL spec logic is.
4175 //
4176 // The other complexity is that unless you implement this feature, it's hard to understand what
4177 // should happen when the client invokes the feature. You cannot add an additional error as it
4178 // is not specified. One can ignore it, but obviously it creates the discrepancies...
4179
4180 std::vector<VariableLocation> reservedLocations;
4181
4182 // Process any output API bindings for arrays that don't alias to the first element.
4183 for (const auto &binding : mFragmentOutputLocations)
4184 {
4185 size_t nameLengthWithoutArrayIndex;
4186 unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
4187 if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
4188 {
4189 continue;
4190 }
4191 for (unsigned int outputVariableIndex = 0;
4192 outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4193 outputVariableIndex++)
4194 {
4195 const sh::ShaderVariable &outputVariable =
4196 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4197 // Check that the binding corresponds to an output array and its array index fits.
4198 if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
4199 !angle::BeginsWith(outputVariable.name, binding.first,
4200 nameLengthWithoutArrayIndex) ||
4201 arrayIndex >= outputVariable.getOutermostArraySize())
4202 {
4203 continue;
4204 }
4205
4206 // Get the API index that corresponds to this exact binding.
4207 // This index may differ from the index used for the array's base.
4208 auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1
4209 ? mState.mExecutable->mSecondaryOutputLocations
4210 : mState.mExecutable->mOutputLocations;
4211 unsigned int location = binding.second.location;
4212 VariableLocation locationInfo(arrayIndex, outputVariableIndex);
4213 if (location >= outputLocations.size())
4214 {
4215 outputLocations.resize(location + 1);
4216 }
4217 if (outputLocations[location].used())
4218 {
4219 infoLog << "Location of variable " << outputVariable.name
4220 << " conflicts with another variable.";
4221 return false;
4222 }
4223 outputLocations[location] = locationInfo;
4224
4225 // Note the array binding location so that it can be skipped later.
4226 reservedLocations.push_back(locationInfo);
4227 }
4228 }
4229
4230 // Reserve locations for output variables whose location is fixed in the shader or through the
4231 // API. Otherwise, the remaining unallocated outputs will be processed later.
4232 for (unsigned int outputVariableIndex = 0;
4233 outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4234 outputVariableIndex++)
4235 {
4236 const sh::ShaderVariable &outputVariable =
4237 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4238
4239 // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4240 if (outputVariable.isBuiltIn())
4241 continue;
4242
4243 int fixedLocation = getOutputLocationForLink(outputVariable);
4244 if (fixedLocation == -1)
4245 {
4246 // Here we're only reserving locations for variables whose location is fixed.
4247 continue;
4248 }
4249 unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
4250
4251 auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4252 ? mState.mExecutable->mSecondaryOutputLocations
4253 : mState.mExecutable->mOutputLocations;
4254
4255 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4256 // structures, so we may use getBasicTypeElementCount().
4257 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4258 if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
4259 outputVariableIndex))
4260 {
4261 infoLog << "Location of variable " << outputVariable.name
4262 << " conflicts with another variable.";
4263 return false;
4264 }
4265 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4266 outputVariableIndex,
4267 mState.mExecutable->mOutputVariables[outputVariableIndex]);
4268 }
4269
4270 // Here we assign locations for the output variables that don't yet have them. Note that we're
4271 // not necessarily able to fit the variables optimally, since then we might have to try
4272 // different arrangements of output arrays. Now we just assign the locations in the order that
4273 // we got the output variables. The spec isn't clear on what kind of algorithm is required for
4274 // finding locations for the output variables, so this should be acceptable at least for now.
4275 GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
4276 if (!mState.mExecutable->getSecondaryOutputLocations().empty())
4277 {
4278 // EXT_blend_func_extended: Program outputs will be validated against
4279 // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
4280 maxLocation = extensions.maxDualSourceDrawBuffers;
4281 }
4282
4283 for (unsigned int outputVariableIndex = 0;
4284 outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4285 outputVariableIndex++)
4286 {
4287 const sh::ShaderVariable &outputVariable =
4288 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4289
4290 // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4291 if (outputVariable.isBuiltIn())
4292 continue;
4293
4294 int fixedLocation = getOutputLocationForLink(outputVariable);
4295 auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4296 ? mState.mExecutable->mSecondaryOutputLocations
4297 : mState.mExecutable->mOutputLocations;
4298 unsigned int baseLocation = 0;
4299 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4300 if (fixedLocation != -1)
4301 {
4302 // Secondary inputs might have caused the max location to drop below what has already
4303 // been explicitly assigned locations. Check for any fixed locations above the max
4304 // that should cause linking to fail.
4305 baseLocation = static_cast<unsigned int>(fixedLocation);
4306 }
4307 else
4308 {
4309 // No fixed location, so try to fit the output in unassigned locations.
4310 // Try baseLocations starting from 0 one at a time and see if the variable fits.
4311 while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
4312 reservedLocations, outputVariableIndex))
4313 {
4314 baseLocation++;
4315 }
4316 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4317 outputVariableIndex,
4318 mState.mExecutable->mOutputVariables[outputVariableIndex]);
4319 }
4320
4321 // Check for any elements assigned above the max location that are actually used.
4322 if (baseLocation + elementCount > maxLocation &&
4323 (baseLocation >= maxLocation ||
4324 FindUsedOutputLocation(outputLocations, maxLocation,
4325 baseLocation + elementCount - maxLocation, reservedLocations,
4326 outputVariableIndex)))
4327 {
4328 // EXT_blend_func_extended: Linking can fail:
4329 // "if the explicit binding assignments do not leave enough space for the linker to
4330 // automatically assign a location for a varying out array, which requires multiple
4331 // contiguous locations."
4332 infoLog << "Could not fit output variable into available locations: "
4333 << outputVariable.name;
4334 return false;
4335 }
4336 }
4337
4338 return true;
4339 }
4340
setUniformValuesFromBindingQualifiers()4341 void Program::setUniformValuesFromBindingQualifiers()
4342 {
4343 for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
4344 {
4345 const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
4346 if (samplerUniform.binding != -1)
4347 {
4348 UniformLocation location = getUniformLocation(samplerUniform.name);
4349 ASSERT(location.value != -1);
4350 std::vector<GLint> boundTextureUnits;
4351 for (unsigned int elementIndex = 0;
4352 elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
4353 {
4354 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
4355 }
4356
4357 // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
4358 // We know it's safe not to notify the Context because this is only called after link.
4359 setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
4360 boundTextureUnits.data());
4361 }
4362 }
4363 }
4364
initInterfaceBlockBindings()4365 void Program::initInterfaceBlockBindings()
4366 {
4367 // Set initial bindings from shader.
4368 for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
4369 blockIndex++)
4370 {
4371 InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
4372 bindUniformBlock({blockIndex}, uniformBlock.binding);
4373 }
4374 }
4375
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)4376 void Program::updateSamplerUniform(Context *context,
4377 const VariableLocation &locationInfo,
4378 GLsizei clampedCount,
4379 const GLint *v)
4380 {
4381 ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
4382 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
4383 SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
4384 std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
4385
4386 if (locationInfo.arrayIndex >= boundTextureUnits.size())
4387 {
4388 return;
4389 }
4390 GLsizei safeUniformCount = std::min(
4391 clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
4392
4393 // Update the sampler uniforms.
4394 for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
4395 {
4396 GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
4397 GLint newTextureUnit = v[arrayIndex];
4398
4399 if (oldTextureUnit == newTextureUnit)
4400 {
4401 continue;
4402 }
4403
4404 boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
4405
4406 // Update the reference counts.
4407 uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
4408 uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit];
4409 ASSERT(oldRefCount > 0);
4410 ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
4411 oldRefCount--;
4412 newRefCount++;
4413
4414 // Check for binding type change.
4415 TextureType &newSamplerType = mState.mExecutable->mActiveSamplerTypes[newTextureUnit];
4416 TextureType &oldSamplerType = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit];
4417 SamplerFormat &newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit];
4418 SamplerFormat &oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit];
4419
4420 if (newRefCount == 1)
4421 {
4422 newSamplerType = samplerBinding.textureType;
4423 newSamplerFormat = samplerBinding.format;
4424 mState.mExecutable->mActiveSamplersMask.set(newTextureUnit);
4425 mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] =
4426 mState.mExecutable->getUniforms()[locationInfo.index].activeShaders();
4427 }
4428 else
4429 {
4430 if (newSamplerType != samplerBinding.textureType)
4431 {
4432 // Conflict detected. Ensure we reset it properly.
4433 newSamplerType = TextureType::InvalidEnum;
4434 }
4435 if (newSamplerFormat != samplerBinding.format)
4436 {
4437 newSamplerFormat = SamplerFormat::InvalidEnum;
4438 }
4439 }
4440
4441 // Unset previously active sampler.
4442 if (oldRefCount == 0)
4443 {
4444 oldSamplerType = TextureType::InvalidEnum;
4445 oldSamplerFormat = SamplerFormat::InvalidEnum;
4446 mState.mExecutable->mActiveSamplersMask.reset(oldTextureUnit);
4447 }
4448 else
4449 {
4450 if (oldSamplerType == TextureType::InvalidEnum ||
4451 oldSamplerFormat == SamplerFormat::InvalidEnum)
4452 {
4453 // Previous conflict. Check if this new change fixed the conflict.
4454 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
4455 }
4456 }
4457
4458 // Update the observing PPO's executable, if any.
4459 // Do this before any of the Context work, since that uses the current ProgramExecutable,
4460 // which will be the PPO's if this Program is bound to it, rather than this Program's.
4461 if (isSeparable())
4462 {
4463 onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
4464 }
4465
4466 // Notify context.
4467 if (context)
4468 {
4469 context->onSamplerUniformChange(newTextureUnit);
4470 context->onSamplerUniformChange(oldTextureUnit);
4471 }
4472 }
4473
4474 // Invalidate the validation cache.
4475 getExecutable().resetCachedValidateSamplersResult();
4476 // Inform any PPOs this Program may be bound to.
4477 onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
4478 }
4479
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)4480 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
4481 {
4482 mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
4483 mExecutable->mSamplerBindings);
4484 }
4485
4486 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)4487 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
4488 GLsizei count,
4489 int vectorSize,
4490 const T *v)
4491 {
4492 if (count == 1)
4493 return 1;
4494
4495 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4496
4497 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4498 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4499 unsigned int remainingElements =
4500 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4501 GLsizei maxElementCount =
4502 static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
4503
4504 if (count * vectorSize > maxElementCount)
4505 {
4506 return maxElementCount / vectorSize;
4507 }
4508
4509 return count;
4510 }
4511
4512 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)4513 GLsizei Program::clampMatrixUniformCount(UniformLocation location,
4514 GLsizei count,
4515 GLboolean transpose,
4516 const T *v)
4517 {
4518 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
4519
4520 if (!transpose)
4521 {
4522 return clampUniformCount(locationInfo, count, cols * rows, v);
4523 }
4524
4525 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4526
4527 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4528 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4529 unsigned int remainingElements =
4530 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4531 return std::min(count, static_cast<GLsizei>(remainingElements));
4532 }
4533
4534 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
4535 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
4536 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const4537 void Program::getUniformInternal(const Context *context,
4538 DestT *dataOut,
4539 UniformLocation location,
4540 GLenum nativeType,
4541 int components) const
4542 {
4543 switch (nativeType)
4544 {
4545 case GL_BOOL:
4546 {
4547 GLint tempValue[16] = {0};
4548 mProgram->getUniformiv(context, location.value, tempValue);
4549 UniformStateQueryCastLoop<GLboolean>(
4550 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4551 break;
4552 }
4553 case GL_INT:
4554 {
4555 GLint tempValue[16] = {0};
4556 mProgram->getUniformiv(context, location.value, tempValue);
4557 UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4558 components);
4559 break;
4560 }
4561 case GL_UNSIGNED_INT:
4562 {
4563 GLuint tempValue[16] = {0};
4564 mProgram->getUniformuiv(context, location.value, tempValue);
4565 UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4566 components);
4567 break;
4568 }
4569 case GL_FLOAT:
4570 {
4571 GLfloat tempValue[16] = {0};
4572 mProgram->getUniformfv(context, location.value, tempValue);
4573 UniformStateQueryCastLoop<GLfloat>(
4574 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4575 break;
4576 }
4577 default:
4578 UNREACHABLE();
4579 break;
4580 }
4581 }
4582
syncState(const Context * context)4583 angle::Result Program::syncState(const Context *context)
4584 {
4585 if (mDirtyBits.any())
4586 {
4587 ASSERT(!mLinkingState);
4588 ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
4589 mDirtyBits.reset();
4590 }
4591
4592 return angle::Result::Continue;
4593 }
4594
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const4595 angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
4596 {
4597 BinaryOutputStream stream;
4598
4599 stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
4600 ANGLE_COMMIT_HASH_SIZE);
4601
4602 // nullptr context is supported when computing binary length.
4603 if (context)
4604 {
4605 stream.writeInt(context->getClientVersion().major);
4606 stream.writeInt(context->getClientVersion().minor);
4607 }
4608 else
4609 {
4610 stream.writeInt(2);
4611 stream.writeInt(0);
4612 }
4613
4614 // Must be before mExecutable->save(), since it uses the value.
4615 stream.writeBool(mState.mSeparable);
4616
4617 mState.mExecutable->save(mState.mSeparable, &stream);
4618
4619 const auto &computeLocalSize = mState.getComputeShaderLocalSize();
4620
4621 stream.writeInt(computeLocalSize[0]);
4622 stream.writeInt(computeLocalSize[1]);
4623 stream.writeInt(computeLocalSize[2]);
4624
4625 stream.writeInt(mState.mNumViews);
4626 stream.writeBool(mState.mEarlyFramentTestsOptimization);
4627 stream.writeInt(mState.mSpecConstUsageBits.bits());
4628
4629 stream.writeInt(mState.getUniformLocations().size());
4630 for (const auto &variable : mState.getUniformLocations())
4631 {
4632 stream.writeInt(variable.arrayIndex);
4633 stream.writeIntOrNegOne(variable.index);
4634 stream.writeBool(variable.ignored);
4635 }
4636
4637 stream.writeInt(mState.getBufferVariables().size());
4638 for (const BufferVariable &bufferVariable : mState.getBufferVariables())
4639 {
4640 WriteBufferVariable(&stream, bufferVariable);
4641 }
4642
4643 // Warn the app layer if saving a binary with unsupported transform feedback.
4644 if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
4645 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4646 {
4647 WARN() << "Saving program binary with transform feedback, which is not supported on this "
4648 "driver.";
4649 }
4650
4651 stream.writeInt(mState.mOutputVariableTypes.size());
4652 for (const auto &outputVariableType : mState.mOutputVariableTypes)
4653 {
4654 stream.writeInt(outputVariableType);
4655 }
4656
4657 static_assert(
4658 IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4659 "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
4660 stream.writeInt(static_cast<int>(mState.mDrawBufferTypeMask.to_ulong()));
4661 stream.writeInt(static_cast<int>(mState.mActiveOutputVariables.to_ulong()));
4662
4663 stream.writeBool(mState.isYUVOutput());
4664
4665 stream.writeInt(mState.getAtomicCounterUniformRange().low());
4666 stream.writeInt(mState.getAtomicCounterUniformRange().high());
4667
4668 mProgram->save(context, &stream);
4669
4670 ASSERT(binaryOut);
4671 if (!binaryOut->resize(stream.length()))
4672 {
4673 WARN() << "Failed to allocate enough memory to serialize a program. (" << stream.length()
4674 << " bytes )";
4675 return angle::Result::Incomplete;
4676 }
4677 memcpy(binaryOut->data(), stream.data(), stream.length());
4678 return angle::Result::Continue;
4679 }
4680
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)4681 angle::Result Program::deserialize(const Context *context,
4682 BinaryInputStream &stream,
4683 InfoLog &infoLog)
4684 {
4685 unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
4686 stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
4687 if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
4688 0)
4689 {
4690 infoLog << "Invalid program binary version.";
4691 return angle::Result::Stop;
4692 }
4693
4694 int majorVersion = stream.readInt<int>();
4695 int minorVersion = stream.readInt<int>();
4696 if (majorVersion != context->getClientMajorVersion() ||
4697 minorVersion != context->getClientMinorVersion())
4698 {
4699 infoLog << "Cannot load program binaries across different ES context versions.";
4700 return angle::Result::Stop;
4701 }
4702
4703 // Must be before mExecutable->load(), since it uses the value.
4704 mState.mSeparable = stream.readBool();
4705
4706 mState.mExecutable->load(mState.mSeparable, &stream);
4707
4708 mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
4709 mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
4710 mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
4711
4712 mState.mNumViews = stream.readInt<int>();
4713 mState.mEarlyFramentTestsOptimization = stream.readBool();
4714 mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
4715
4716 const size_t uniformIndexCount = stream.readInt<size_t>();
4717 ASSERT(mState.mUniformLocations.empty());
4718 for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex)
4719 {
4720 VariableLocation variable;
4721 stream.readInt(&variable.arrayIndex);
4722 stream.readInt(&variable.index);
4723 stream.readBool(&variable.ignored);
4724
4725 mState.mUniformLocations.push_back(variable);
4726 }
4727
4728 size_t bufferVariableCount = stream.readInt<size_t>();
4729 ASSERT(mState.mBufferVariables.empty());
4730 for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
4731 {
4732 BufferVariable bufferVariable;
4733 LoadBufferVariable(&stream, &bufferVariable);
4734 mState.mBufferVariables.push_back(bufferVariable);
4735 }
4736
4737 size_t outputTypeCount = stream.readInt<size_t>();
4738 for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
4739 {
4740 mState.mOutputVariableTypes.push_back(stream.readInt<GLenum>());
4741 }
4742
4743 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4744 "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
4745 "into 32 bits each");
4746 mState.mDrawBufferTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4747 mState.mActiveOutputVariables =
4748 gl::DrawBufferMask(stream.readInt<gl::DrawBufferMask::value_type>());
4749
4750 stream.readBool(&mState.mYUVOutput);
4751
4752 unsigned int atomicCounterRangeLow = stream.readInt<unsigned int>();
4753 unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
4754 mState.mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
4755
4756 static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
4757 "Too many shader types");
4758
4759 // Reject programs that use transform feedback varyings if the hardware cannot support them.
4760 if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
4761 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4762 {
4763 infoLog << "Current driver does not support transform feedback in binary programs.";
4764 return angle::Result::Stop;
4765 }
4766
4767 if (!mState.mAttachedShaders[ShaderType::Compute])
4768 {
4769 mState.mExecutable->updateTransformFeedbackStrides();
4770 }
4771
4772 postResolveLink(context);
4773 mState.mExecutable->updateCanDrawWith();
4774
4775 return angle::Result::Continue;
4776 }
4777
postResolveLink(const gl::Context * context)4778 void Program::postResolveLink(const gl::Context *context)
4779 {
4780 mState.updateActiveSamplers();
4781 mState.mExecutable->mActiveImageShaderBits.fill({});
4782 mState.mExecutable->updateActiveImages(getExecutable());
4783
4784 setUniformValuesFromBindingQualifiers();
4785
4786 if (context->getExtensions().multiDraw)
4787 {
4788 mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value;
4789 }
4790
4791 if (context->getExtensions().baseVertexBaseInstance)
4792 {
4793 mState.mBaseVertexLocation = getUniformLocation("gl_BaseVertex").value;
4794 mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value;
4795 }
4796 }
4797
4798 // HasAttachedShaders implementation.
getTransformFeedbackStage() const4799 ShaderType HasAttachedShaders::getTransformFeedbackStage() const
4800 {
4801 if (getAttachedShader(ShaderType::Geometry))
4802 {
4803 return ShaderType::Geometry;
4804 }
4805 if (getAttachedShader(ShaderType::TessEvaluation))
4806 {
4807 return ShaderType::TessEvaluation;
4808 }
4809 return ShaderType::Vertex;
4810 }
4811 } // namespace gl
4812