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>
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
1058 // ProgramAliasedBindings implementation.
ProgramAliasedBindings()1059 ProgramAliasedBindings::ProgramAliasedBindings() {}
1060
~ProgramAliasedBindings()1061 ProgramAliasedBindings::~ProgramAliasedBindings() {}
1062
bindLocation(GLuint index,const std::string & name)1063 void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
1064 {
1065 mBindings[name] = ProgramBinding(index);
1066
1067 // EXT_blend_func_extended spec: "If it specifies the base name of an array,
1068 // it identifies the resources associated with the first element of the array."
1069 //
1070 // Normalize array bindings so that "name" and "name[0]" map to the same entry.
1071 // If this binding is of the form "name[0]", then mark the "name" binding as
1072 // aliased but do not update it yet in case "name" is not actually an array.
1073 size_t nameLengthWithoutArrayIndex;
1074 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1075 if (arrayIndex == 0)
1076 {
1077 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1078 auto iter = mBindings.find(baseName);
1079 if (iter != mBindings.end())
1080 {
1081 iter->second.aliased = true;
1082 }
1083 }
1084 }
1085
getBindingByName(const std::string & name) const1086 int ProgramAliasedBindings::getBindingByName(const std::string &name) const
1087 {
1088 auto iter = mBindings.find(name);
1089 return (iter != mBindings.end()) ? iter->second.location : -1;
1090 }
1091
getBindingByLocation(GLuint location) const1092 int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
1093 {
1094 for (const auto &iter : mBindings)
1095 {
1096 if (iter.second.location == location)
1097 {
1098 return iter.second.location;
1099 }
1100 }
1101 return -1;
1102 }
1103
getBinding(const sh::ShaderVariable & variable) const1104 int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const
1105 {
1106 const std::string &name = variable.name;
1107
1108 // Check with the normalized array name if applicable.
1109 if (variable.isArray())
1110 {
1111 size_t nameLengthWithoutArrayIndex;
1112 unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
1113 if (arrayIndex == 0)
1114 {
1115 std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
1116 auto iter = mBindings.find(baseName);
1117 // If "name" exists and is not aliased, that means it was modified more
1118 // recently than its "name[0]" form and should be used instead of that.
1119 if (iter != mBindings.end() && !iter->second.aliased)
1120 {
1121 return iter->second.location;
1122 }
1123 }
1124 else if (arrayIndex == GL_INVALID_INDEX)
1125 {
1126 auto iter = mBindings.find(variable.name);
1127 // If "name" exists and is not aliased, that means it was modified more
1128 // recently than its "name[0]" form and should be used instead of that.
1129 if (iter != mBindings.end() && !iter->second.aliased)
1130 {
1131 return iter->second.location;
1132 }
1133 // The base name was aliased, so use the name with the array notation.
1134 return getBindingByName(name + "[0]");
1135 }
1136 }
1137
1138 return getBindingByName(name);
1139 }
1140
begin() const1141 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
1142 {
1143 return mBindings.begin();
1144 }
1145
end() const1146 ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
1147 {
1148 return mBindings.end();
1149 }
1150
1151 // ImageBinding implementation.
ImageBinding(size_t count,TextureType textureTypeIn)1152 ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn)
1153 : textureType(textureTypeIn), boundImageUnits(count, 0)
1154 {}
ImageBinding(GLuint imageUnit,size_t count,TextureType textureTypeIn)1155 ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
1156 : textureType(textureTypeIn)
1157 {
1158 for (size_t index = 0; index < count; ++index)
1159 {
1160 boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
1161 }
1162 }
1163
1164 ImageBinding::ImageBinding(const ImageBinding &other) = default;
1165
1166 ImageBinding::~ImageBinding() = default;
1167
1168 // ProgramState implementation.
ProgramState()1169 ProgramState::ProgramState()
1170 : mLabel(),
1171 mAttachedShaders{},
1172 mLocationsUsedForXfbExtension(0),
1173 mAtomicCounterUniformRange(0, 0),
1174 mYUVOutput(false),
1175 mBinaryRetrieveableHint(false),
1176 mSeparable(false),
1177 mNumViews(-1),
1178 mDrawIDLocation(-1),
1179 mBaseVertexLocation(-1),
1180 mBaseInstanceLocation(-1),
1181 mCachedBaseVertex(0),
1182 mCachedBaseInstance(0),
1183 mExecutable(new ProgramExecutable())
1184 {
1185 mComputeShaderLocalSize.fill(1);
1186 }
1187
~ProgramState()1188 ProgramState::~ProgramState()
1189 {
1190 ASSERT(!hasAttachedShader());
1191 }
1192
getLabel()1193 const std::string &ProgramState::getLabel()
1194 {
1195 return mLabel;
1196 }
1197
getAttachedShader(ShaderType shaderType) const1198 Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
1199 {
1200 ASSERT(shaderType != ShaderType::InvalidEnum);
1201 return mAttachedShaders[shaderType];
1202 }
1203
getUniformIndexFromName(const std::string & name) const1204 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
1205 {
1206 return GetResourceIndexFromName(mExecutable->mUniforms, name);
1207 }
1208
getBufferVariableIndexFromName(const std::string & name) const1209 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
1210 {
1211 return GetResourceIndexFromName(mBufferVariables, name);
1212 }
1213
getUniformIndexFromLocation(UniformLocation location) const1214 GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const
1215 {
1216 ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
1217 return mUniformLocations[location.value].index;
1218 }
1219
getSamplerIndex(UniformLocation location) const1220 Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
1221 {
1222 GLuint index = getUniformIndexFromLocation(location);
1223 if (!isSamplerUniformIndex(index))
1224 {
1225 return Optional<GLuint>::Invalid();
1226 }
1227
1228 return getSamplerIndexFromUniformIndex(index);
1229 }
1230
isSamplerUniformIndex(GLuint index) const1231 bool ProgramState::isSamplerUniformIndex(GLuint index) const
1232 {
1233 return mExecutable->mSamplerUniformRange.contains(index);
1234 }
1235
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const1236 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
1237 {
1238 ASSERT(isSamplerUniformIndex(uniformIndex));
1239 return uniformIndex - mExecutable->mSamplerUniformRange.low();
1240 }
1241
getUniformIndexFromSamplerIndex(GLuint samplerIndex) const1242 GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
1243 {
1244 ASSERT(samplerIndex < mExecutable->mSamplerUniformRange.length());
1245 return samplerIndex + mExecutable->mSamplerUniformRange.low();
1246 }
1247
isImageUniformIndex(GLuint index) const1248 bool ProgramState::isImageUniformIndex(GLuint index) const
1249 {
1250 return mExecutable->mImageUniformRange.contains(index);
1251 }
1252
getImageIndexFromUniformIndex(GLuint uniformIndex) const1253 GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
1254 {
1255 ASSERT(isImageUniformIndex(uniformIndex));
1256 return uniformIndex - mExecutable->mImageUniformRange.low();
1257 }
1258
getAttributeLocation(const std::string & name) const1259 GLuint ProgramState::getAttributeLocation(const std::string &name) const
1260 {
1261 for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
1262 {
1263 if (attribute.name == name)
1264 {
1265 return attribute.location;
1266 }
1267 }
1268
1269 return static_cast<GLuint>(-1);
1270 }
1271
hasAttachedShader() const1272 bool ProgramState::hasAttachedShader() const
1273 {
1274 for (const Shader *shader : mAttachedShaders)
1275 {
1276 if (shader)
1277 {
1278 return true;
1279 }
1280 }
1281 return false;
1282 }
1283
getFirstAttachedShaderStageType() const1284 ShaderType ProgramState::getFirstAttachedShaderStageType() const
1285 {
1286 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1287 if (linkedStages.none())
1288 {
1289 return ShaderType::InvalidEnum;
1290 }
1291
1292 return linkedStages.first();
1293 }
1294
getLastAttachedShaderStageType() const1295 ShaderType ProgramState::getLastAttachedShaderStageType() const
1296 {
1297 const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
1298 if (linkedStages.none())
1299 {
1300 return ShaderType::InvalidEnum;
1301 }
1302
1303 return linkedStages.last();
1304 }
1305
getAttachedTransformFeedbackStage() const1306 ShaderType ProgramState::getAttachedTransformFeedbackStage() const
1307 {
1308 if (mAttachedShaders[ShaderType::Geometry])
1309 {
1310 return ShaderType::Geometry;
1311 }
1312 if (mAttachedShaders[ShaderType::TessEvaluation])
1313 {
1314 return ShaderType::TessEvaluation;
1315 }
1316 return ShaderType::Vertex;
1317 }
1318
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,ShaderProgramID handle)1319 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
1320 : mSerial(factory->generateSerial()),
1321 mProgram(factory->createProgram(mState)),
1322 mValidated(false),
1323 mLinked(false),
1324 mDeleteStatus(false),
1325 mRefCount(0),
1326 mResourceManager(manager),
1327 mHandle(handle)
1328 {
1329 ASSERT(mProgram);
1330
1331 unlink();
1332 }
1333
~Program()1334 Program::~Program()
1335 {
1336 ASSERT(!mProgram);
1337 }
1338
onDestroy(const Context * context)1339 void Program::onDestroy(const Context *context)
1340 {
1341 resolveLink(context);
1342 for (ShaderType shaderType : AllShaderTypes())
1343 {
1344 if (mState.mAttachedShaders[shaderType])
1345 {
1346 mState.mAttachedShaders[shaderType]->release(context);
1347 mState.mAttachedShaders[shaderType] = nullptr;
1348 }
1349 }
1350
1351 mProgram->destroy(context);
1352
1353 ASSERT(!mState.hasAttachedShader());
1354 SafeDelete(mProgram);
1355
1356 delete this;
1357 }
id() const1358 ShaderProgramID Program::id() const
1359 {
1360 ASSERT(!mLinkingState);
1361 return mHandle;
1362 }
1363
setLabel(const Context * context,const std::string & label)1364 void Program::setLabel(const Context *context, const std::string &label)
1365 {
1366 ASSERT(!mLinkingState);
1367 mState.mLabel = label;
1368 }
1369
getLabel() const1370 const std::string &Program::getLabel() const
1371 {
1372 ASSERT(!mLinkingState);
1373 return mState.mLabel;
1374 }
1375
attachShader(Shader * shader)1376 void Program::attachShader(Shader *shader)
1377 {
1378 ShaderType shaderType = shader->getType();
1379 ASSERT(shaderType != ShaderType::InvalidEnum);
1380
1381 mState.mAttachedShaders[shaderType] = shader;
1382 mState.mAttachedShaders[shaderType]->addRef();
1383 }
1384
detachShader(const Context * context,Shader * shader)1385 void Program::detachShader(const Context *context, Shader *shader)
1386 {
1387 resolveLink(context);
1388 ShaderType shaderType = shader->getType();
1389 ASSERT(shaderType != ShaderType::InvalidEnum);
1390
1391 ASSERT(mState.mAttachedShaders[shaderType] == shader);
1392 shader->release(context);
1393 mState.mAttachedShaders[shaderType] = nullptr;
1394 }
1395
getAttachedShadersCount() const1396 int Program::getAttachedShadersCount() const
1397 {
1398 ASSERT(!mLinkingState);
1399 int numAttachedShaders = 0;
1400 for (const Shader *shader : mState.mAttachedShaders)
1401 {
1402 if (shader)
1403 {
1404 ++numAttachedShaders;
1405 }
1406 }
1407
1408 return numAttachedShaders;
1409 }
1410
getAttachedShader(ShaderType shaderType) const1411 Shader *Program::getAttachedShader(ShaderType shaderType) const
1412 {
1413 ASSERT(!mLinkingState);
1414 return mState.getAttachedShader(shaderType);
1415 }
1416
bindAttributeLocation(GLuint index,const char * name)1417 void Program::bindAttributeLocation(GLuint index, const char *name)
1418 {
1419 ASSERT(!mLinkingState);
1420 mAttributeBindings.bindLocation(index, name);
1421 }
1422
bindUniformLocation(UniformLocation location,const char * name)1423 void Program::bindUniformLocation(UniformLocation location, const char *name)
1424 {
1425 ASSERT(!mLinkingState);
1426 mState.mUniformLocationBindings.bindLocation(location.value, name);
1427 }
1428
bindFragmentOutputLocation(GLuint index,const char * name)1429 void Program::bindFragmentOutputLocation(GLuint index, const char *name)
1430 {
1431 mFragmentOutputLocations.bindLocation(index, name);
1432 }
1433
bindFragmentOutputIndex(GLuint index,const char * name)1434 void Program::bindFragmentOutputIndex(GLuint index, const char *name)
1435 {
1436 mFragmentOutputIndexes.bindLocation(index, name);
1437 }
1438
link(const Context * context)1439 angle::Result Program::link(const Context *context)
1440 {
1441 angle::Result result = linkImpl(context);
1442
1443 // Avoid having two ProgramExecutables if the link failed and the Program had successfully
1444 // linked previously.
1445 if (mLinkingState && mLinkingState->linkedExecutable)
1446 {
1447 mState.mExecutable = mLinkingState->linkedExecutable;
1448 }
1449
1450 return result;
1451 }
1452
1453 // The attached shaders are checked for linking errors by matching up their variables.
1454 // Uniform, input and output variables get collected.
1455 // The code gets compiled into binaries.
linkImpl(const Context * context)1456 angle::Result Program::linkImpl(const Context *context)
1457 {
1458 ASSERT(!mLinkingState);
1459 // Don't make any local variables pointing to anything within the ProgramExecutable, since
1460 // unlink() could make a new ProgramExecutable making any references/pointers invalid.
1461 auto *platform = ANGLEPlatformCurrent();
1462 double startTime = platform->currentTime(platform);
1463
1464 // Unlink the program, but do not clear the validation-related caching yet, since we can still
1465 // use the previously linked program if linking the shaders fails.
1466 mLinked = false;
1467
1468 mState.mExecutable->getInfoLog().reset();
1469
1470 // Validate we have properly attached shaders before checking the cache.
1471 if (!linkValidateShaders(mState.mExecutable->getInfoLog()))
1472 {
1473 return angle::Result::Continue;
1474 }
1475
1476 egl::BlobCache::Key programHash = {0};
1477 MemoryProgramCache *cache = context->getMemoryProgramCache();
1478
1479 // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1480 if (cache && !isSeparable())
1481 {
1482 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1483 angle::Result cacheResult = cache->getProgram(context, this, &programHash);
1484 ANGLE_TRY(cacheResult);
1485
1486 // Check explicitly for Continue, Incomplete means a cache miss
1487 if (cacheResult == angle::Result::Continue)
1488 {
1489 // Succeeded in loading the binaries in the front-end, back end may still be loading
1490 // asynchronously
1491 double delta = platform->currentTime(platform) - startTime;
1492 int us = static_cast<int>(delta * 1000000.0);
1493 ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
1494 return angle::Result::Continue;
1495 }
1496 }
1497
1498 // Cache load failed, fall through to normal linking.
1499 unlink();
1500 InfoLog &infoLog = mState.mExecutable->getInfoLog();
1501
1502 // Re-link shaders after the unlink call.
1503 bool result = linkValidateShaders(infoLog);
1504 ASSERT(result);
1505
1506 std::unique_ptr<LinkingState> linkingState(new LinkingState());
1507 ProgramMergedVaryings mergedVaryings;
1508 ProgramLinkedResources &resources = linkingState->resources;
1509
1510 if (mState.mAttachedShaders[ShaderType::Compute])
1511 {
1512 resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1513 &mState.mExecutable->mComputeShaderStorageBlocks, &mState.mBufferVariables,
1514 &mState.mExecutable->mAtomicCounterBuffers);
1515
1516 GLuint combinedImageUniforms = 0u;
1517 if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1518 mState.mUniformLocationBindings, &combinedImageUniforms,
1519 &resources.unusedUniforms))
1520 {
1521 return angle::Result::Continue;
1522 }
1523
1524 GLuint combinedShaderStorageBlocks = 0u;
1525 if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1526 context->getExtensions().webglCompatibility, infoLog,
1527 &combinedShaderStorageBlocks))
1528 {
1529 return angle::Result::Continue;
1530 }
1531
1532 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
1533 // A link error will be generated if the sum of the number of active image uniforms used in
1534 // all shaders, the number of active shader storage blocks, and the number of active
1535 // fragment shader outputs exceeds the implementation-dependent value of
1536 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
1537 if (combinedImageUniforms + combinedShaderStorageBlocks >
1538 static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
1539 {
1540 infoLog
1541 << "The sum of the number of active image uniforms, active shader storage blocks "
1542 "and active fragment shader outputs exceeds "
1543 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
1544 << context->getCaps().maxCombinedShaderOutputResources << ")";
1545 return angle::Result::Continue;
1546 }
1547
1548 InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1549 InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1550 }
1551 else
1552 {
1553 resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
1554 &mState.mExecutable->mGraphicsShaderStorageBlocks, &mState.mBufferVariables,
1555 &mState.mExecutable->mAtomicCounterBuffers);
1556
1557 if (!linkAttributes(context, infoLog))
1558 {
1559 return angle::Result::Continue;
1560 }
1561
1562 if (!linkVaryings(infoLog))
1563 {
1564 return angle::Result::Continue;
1565 }
1566
1567 GLuint combinedImageUniforms = 0u;
1568 if (!linkUniforms(context->getCaps(), context->getClientVersion(), infoLog,
1569 mState.mUniformLocationBindings, &combinedImageUniforms,
1570 &resources.unusedUniforms))
1571 {
1572 return angle::Result::Continue;
1573 }
1574
1575 GLuint combinedShaderStorageBlocks = 0u;
1576 if (!linkInterfaceBlocks(context->getCaps(), context->getClientVersion(),
1577 context->getExtensions().webglCompatibility, infoLog,
1578 &combinedShaderStorageBlocks))
1579 {
1580 return angle::Result::Continue;
1581 }
1582
1583 if (!LinkValidateProgramGlobalNames(infoLog, *this))
1584 {
1585 return angle::Result::Continue;
1586 }
1587
1588 if (!linkOutputVariables(context->getCaps(), context->getExtensions(),
1589 context->getClientVersion(), combinedImageUniforms,
1590 combinedShaderStorageBlocks))
1591 {
1592 return angle::Result::Continue;
1593 }
1594
1595 gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
1596 if (vertexShader)
1597 {
1598 mState.mNumViews = vertexShader->getNumViews();
1599 mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
1600 }
1601
1602 gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
1603 if (fragmentShader)
1604 {
1605 mState.mEarlyFramentTestsOptimization =
1606 fragmentShader->hasEarlyFragmentTestsOptimization();
1607 mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
1608 }
1609
1610 InitUniformBlockLinker(mState, &resources.uniformBlockLinker);
1611 InitShaderStorageBlockLinker(mState, &resources.shaderStorageBlockLinker);
1612
1613 mergedVaryings = GetMergedVaryingsFromShaders(*this, getExecutable());
1614 if (!mState.mExecutable->linkMergedVaryings(context, *this, mergedVaryings,
1615 mState.mTransformFeedbackVaryingNames,
1616 isSeparable(), &resources.varyingPacking))
1617 {
1618 return angle::Result::Continue;
1619 }
1620 }
1621
1622 updateLinkedShaderStages();
1623
1624 mLinkingState = std::move(linkingState);
1625 mLinkingState->linkingFromBinary = false;
1626 mLinkingState->programHash = programHash;
1627 mLinkingState->linkEvent = mProgram->link(context, resources, infoLog, mergedVaryings);
1628
1629 // Must be after mProgram->link() to avoid misleading the linker about output variables.
1630 mState.updateProgramInterfaceInputs();
1631 mState.updateProgramInterfaceOutputs();
1632
1633 // Linking has succeeded, so we need to save some information that may get overwritten by a
1634 // later linkProgram() that could fail.
1635 if (mState.mSeparable)
1636 {
1637 mState.mExecutable->saveLinkedStateInfo(mState);
1638 mLinkingState->linkedExecutable = mState.mExecutable;
1639 }
1640
1641 return angle::Result::Continue;
1642 }
1643
isLinking() const1644 bool Program::isLinking() const
1645 {
1646 return (mLinkingState.get() && mLinkingState->linkEvent &&
1647 mLinkingState->linkEvent->isLinking());
1648 }
1649
resolveLinkImpl(const Context * context)1650 void Program::resolveLinkImpl(const Context *context)
1651 {
1652 ASSERT(mLinkingState.get());
1653
1654 angle::Result result = mLinkingState->linkEvent->wait(context);
1655
1656 mLinked = result == angle::Result::Continue;
1657 std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
1658 if (!mLinked)
1659 {
1660 return;
1661 }
1662
1663 if (linkingState->linkingFromBinary)
1664 {
1665 // All internal Program state is already loaded from the binary.
1666 return;
1667 }
1668
1669 initInterfaceBlockBindings();
1670
1671 // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
1672 // Only successfully linked program can replace the executables.
1673 ASSERT(mLinked);
1674
1675 // Mark implementation-specific unreferenced uniforms as ignored.
1676 std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
1677 mProgram->markUnusedUniformLocations(&mState.mUniformLocations,
1678 &mState.mExecutable->mSamplerBindings, imageBindings);
1679
1680 // Must be called after markUnusedUniformLocations.
1681 postResolveLink(context);
1682
1683 // Save to the program cache.
1684 std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
1685 MemoryProgramCache *cache = context->getMemoryProgramCache();
1686 // TODO: http://anglebug.com/4530: Enable program caching for separable programs
1687 if (cache && !isSeparable() &&
1688 (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
1689 !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
1690 {
1691 if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
1692 {
1693 // Don't fail linking if putting the program binary into the cache fails, the program is
1694 // still usable.
1695 WARN() << "Failed to save linked program to memory program cache.";
1696 }
1697 }
1698 }
1699
updateLinkedShaderStages()1700 void Program::updateLinkedShaderStages()
1701 {
1702 mState.mExecutable->resetLinkedShaderStages();
1703
1704 for (const Shader *shader : mState.mAttachedShaders)
1705 {
1706 if (shader)
1707 {
1708 mState.mExecutable->setLinkedShaderStages(shader->getType());
1709 }
1710 }
1711
1712 if (mState.mExecutable->hasLinkedShaderStage(ShaderType::Compute))
1713 {
1714 mState.mExecutable->setIsCompute(true);
1715 }
1716 else
1717 {
1718 mState.mExecutable->setIsCompute(false);
1719 }
1720 }
1721
updateActiveSamplers()1722 void ProgramState::updateActiveSamplers()
1723 {
1724 mExecutable->mActiveSamplerRefCounts.fill(0);
1725 mExecutable->updateActiveSamplers(*this);
1726 }
1727
updateProgramInterfaceInputs()1728 void ProgramState::updateProgramInterfaceInputs()
1729 {
1730 const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType();
1731
1732 if (firstAttachedShaderType == ShaderType::Vertex)
1733 {
1734 // Vertex attributes are already what we need, so nothing to do
1735 return;
1736 }
1737
1738 Shader *shader = getAttachedShader(firstAttachedShaderType);
1739 ASSERT(shader);
1740
1741 // Copy over each input varying, since the Shader could go away
1742 if (shader->getType() == ShaderType::Compute)
1743 {
1744 for (const sh::ShaderVariable &attribute : shader->getAllAttributes())
1745 {
1746 // Compute Shaders have the following built-in input variables.
1747 //
1748 // in uvec3 gl_NumWorkGroups;
1749 // in uvec3 gl_WorkGroupID;
1750 // in uvec3 gl_LocalInvocationID;
1751 // in uvec3 gl_GlobalInvocationID;
1752 // in uint gl_LocalInvocationIndex;
1753 // They are all vecs or uints, so no special handling is required.
1754 mExecutable->mProgramInputs.emplace_back(attribute);
1755 }
1756 }
1757 else
1758 {
1759 for (const sh::ShaderVariable &varying : shader->getInputVaryings())
1760 {
1761 UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
1762 }
1763 }
1764 }
1765
updateProgramInterfaceOutputs()1766 void ProgramState::updateProgramInterfaceOutputs()
1767 {
1768 const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType();
1769
1770 if (lastAttachedShaderType == ShaderType::Fragment)
1771 {
1772 // Fragment outputs are already what we need, so nothing to do
1773 return;
1774 }
1775 if (lastAttachedShaderType == ShaderType::Compute)
1776 {
1777 // If the program only contains a Compute Shader, then there are no user-defined outputs.
1778 return;
1779 }
1780
1781 Shader *shader = getAttachedShader(lastAttachedShaderType);
1782 ASSERT(shader);
1783
1784 // Copy over each output varying, since the Shader could go away
1785 for (const sh::ShaderVariable &varying : shader->getOutputVaryings())
1786 {
1787 UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
1788 }
1789 }
1790
1791 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1792 void Program::unlink()
1793 {
1794 if (mLinkingState && mLinkingState->linkedExecutable)
1795 {
1796 // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of
1797 // the last successfully linked ProgramExecutable, so we don't lose any state information.
1798 mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable));
1799 }
1800 mState.mExecutable->reset();
1801
1802 mState.mUniformLocations.clear();
1803 mState.mBufferVariables.clear();
1804 mState.mOutputVariableTypes.clear();
1805 mState.mDrawBufferTypeMask.reset();
1806 mState.mYUVOutput = false;
1807 mState.mActiveOutputVariables.reset();
1808 mState.mComputeShaderLocalSize.fill(1);
1809 mState.mNumViews = -1;
1810 mState.mDrawIDLocation = -1;
1811 mState.mBaseVertexLocation = -1;
1812 mState.mBaseInstanceLocation = -1;
1813 mState.mCachedBaseVertex = 0;
1814 mState.mCachedBaseInstance = 0;
1815 mState.mEarlyFramentTestsOptimization = false;
1816 mState.mDrawIDLocation = -1;
1817 mState.mBaseVertexLocation = -1;
1818 mState.mBaseInstanceLocation = -1;
1819 mState.mCachedBaseVertex = 0;
1820 mState.mCachedBaseInstance = 0;
1821 mState.mEarlyFramentTestsOptimization = false;
1822 mState.mSpecConstUsageBits.reset();
1823
1824 mValidated = false;
1825
1826 mLinked = false;
1827 }
1828
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1829 angle::Result Program::loadBinary(const Context *context,
1830 GLenum binaryFormat,
1831 const void *binary,
1832 GLsizei length)
1833 {
1834 ASSERT(!mLinkingState);
1835 unlink();
1836 InfoLog &infoLog = mState.mExecutable->getInfoLog();
1837
1838 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1839 return angle::Result::Continue;
1840 #else
1841 ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1842 if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1843 {
1844 infoLog << "Invalid program binary format.";
1845 return angle::Result::Continue;
1846 }
1847
1848 BinaryInputStream stream(binary, length);
1849 ANGLE_TRY(deserialize(context, stream, infoLog));
1850
1851 // Currently we require the full shader text to compute the program hash.
1852 // We could also store the binary in the internal program cache.
1853
1854 for (size_t uniformBlockIndex = 0;
1855 uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
1856 {
1857 mDirtyBits.set(uniformBlockIndex);
1858 }
1859
1860 // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple
1861 // implementations. In some implementations, a background thread is used to compile the
1862 // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with
1863 // the operation.
1864
1865 // We do not want to call LinkEvent::wait because that will cause the background thread
1866 // to finish its task before returning, thus defeating the purpose of background compilation.
1867 // We need to defer waiting on background compilation until the very last minute when we
1868 // absolutely need the results, such as when the developer binds the program or queries
1869 // for the completion status.
1870
1871 // If load returns nullptr, we know for sure that the binary is not compatible with the backend.
1872 // The loaded binary could have been read from the on-disk shader cache and be corrupted or
1873 // serialized with different revision and subsystem id than the currently loaded backend.
1874 // Returning 'Incomplete' to the caller results in link happening using the original shader
1875 // sources.
1876 angle::Result result;
1877 std::unique_ptr<LinkingState> linkingState;
1878 std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog);
1879 if (linkEvent)
1880 {
1881 linkingState = std::make_unique<LinkingState>();
1882 linkingState->linkingFromBinary = true;
1883 linkingState->linkEvent = std::move(linkEvent);
1884 result = angle::Result::Continue;
1885 }
1886 else
1887 {
1888 result = angle::Result::Incomplete;
1889 }
1890 mLinkingState = std::move(linkingState);
1891
1892 return result;
1893 #endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1894 }
1895
saveBinary(Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1896 angle::Result Program::saveBinary(Context *context,
1897 GLenum *binaryFormat,
1898 void *binary,
1899 GLsizei bufSize,
1900 GLsizei *length) const
1901 {
1902 ASSERT(!mLinkingState);
1903 if (binaryFormat)
1904 {
1905 *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1906 }
1907
1908 angle::MemoryBuffer memoryBuf;
1909 ANGLE_TRY(serialize(context, &memoryBuf));
1910
1911 GLsizei streamLength = static_cast<GLsizei>(memoryBuf.size());
1912 const uint8_t *streamState = memoryBuf.data();
1913
1914 if (streamLength > bufSize)
1915 {
1916 if (length)
1917 {
1918 *length = 0;
1919 }
1920
1921 // TODO: This should be moved to the validation layer but computing the size of the binary
1922 // before saving it causes the save to happen twice. It may be possible to write the binary
1923 // to a separate buffer, validate sizes and then copy it.
1924 ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
1925 }
1926
1927 if (binary)
1928 {
1929 char *ptr = reinterpret_cast<char *>(binary);
1930
1931 memcpy(ptr, streamState, streamLength);
1932 ptr += streamLength;
1933
1934 ASSERT(ptr - streamLength == binary);
1935 }
1936
1937 if (length)
1938 {
1939 *length = streamLength;
1940 }
1941
1942 return angle::Result::Continue;
1943 }
1944
getBinaryLength(Context * context) const1945 GLint Program::getBinaryLength(Context *context) const
1946 {
1947 ASSERT(!mLinkingState);
1948 if (!mLinked)
1949 {
1950 return 0;
1951 }
1952
1953 GLint length;
1954 angle::Result result =
1955 saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1956 if (result != angle::Result::Continue)
1957 {
1958 return 0;
1959 }
1960
1961 return length;
1962 }
1963
setBinaryRetrievableHint(bool retrievable)1964 void Program::setBinaryRetrievableHint(bool retrievable)
1965 {
1966 ASSERT(!mLinkingState);
1967 // TODO(jmadill) : replace with dirty bits
1968 mProgram->setBinaryRetrievableHint(retrievable);
1969 mState.mBinaryRetrieveableHint = retrievable;
1970 }
1971
getBinaryRetrievableHint() const1972 bool Program::getBinaryRetrievableHint() const
1973 {
1974 ASSERT(!mLinkingState);
1975 return mState.mBinaryRetrieveableHint;
1976 }
1977
setSeparable(bool separable)1978 void Program::setSeparable(bool separable)
1979 {
1980 ASSERT(!mLinkingState);
1981 // TODO(yunchao) : replace with dirty bits
1982 if (mState.mSeparable != separable)
1983 {
1984 mProgram->setSeparable(separable);
1985 mState.mSeparable = separable;
1986 }
1987 }
1988
isSeparable() const1989 bool Program::isSeparable() const
1990 {
1991 ASSERT(!mLinkingState);
1992 return mState.mSeparable;
1993 }
1994
deleteSelf(const Context * context)1995 void Program::deleteSelf(const Context *context)
1996 {
1997 ASSERT(mRefCount == 0 && mDeleteStatus);
1998 mResourceManager->deleteProgram(context, mHandle);
1999 }
2000
getRefCount() const2001 unsigned int Program::getRefCount() const
2002 {
2003 return mRefCount;
2004 }
2005
getAttachedShaders(GLsizei maxCount,GLsizei * count,ShaderProgramID * shaders) const2006 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
2007 {
2008 ASSERT(!mLinkingState);
2009 int total = 0;
2010
2011 for (const Shader *shader : mState.mAttachedShaders)
2012 {
2013 if (shader && (total < maxCount))
2014 {
2015 shaders[total] = shader->getHandle();
2016 ++total;
2017 }
2018 }
2019
2020 if (count)
2021 {
2022 *count = total;
2023 }
2024 }
2025
getAttributeLocation(const std::string & name) const2026 GLuint Program::getAttributeLocation(const std::string &name) const
2027 {
2028 ASSERT(!mLinkingState);
2029 return mState.getAttributeLocation(name);
2030 }
2031
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2032 void Program::getActiveAttribute(GLuint index,
2033 GLsizei bufsize,
2034 GLsizei *length,
2035 GLint *size,
2036 GLenum *type,
2037 GLchar *name) const
2038 {
2039 ASSERT(!mLinkingState);
2040 if (!mLinked)
2041 {
2042 if (bufsize > 0)
2043 {
2044 name[0] = '\0';
2045 }
2046
2047 if (length)
2048 {
2049 *length = 0;
2050 }
2051
2052 *type = GL_NONE;
2053 *size = 1;
2054 return;
2055 }
2056
2057 ASSERT(index < mState.mExecutable->getProgramInputs().size());
2058 const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
2059
2060 if (bufsize > 0)
2061 {
2062 CopyStringToBuffer(name, attrib.name, bufsize, length);
2063 }
2064
2065 // Always a single 'type' instance
2066 *size = 1;
2067 *type = attrib.type;
2068 }
2069
getActiveAttributeCount() const2070 GLint Program::getActiveAttributeCount() const
2071 {
2072 ASSERT(!mLinkingState);
2073 if (!mLinked)
2074 {
2075 return 0;
2076 }
2077
2078 return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
2079 }
2080
getActiveAttributeMaxLength() const2081 GLint Program::getActiveAttributeMaxLength() const
2082 {
2083 ASSERT(!mLinkingState);
2084 if (!mLinked)
2085 {
2086 return 0;
2087 }
2088
2089 size_t maxLength = 0;
2090
2091 for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
2092 {
2093 maxLength = std::max(attrib.name.length() + 1, maxLength);
2094 }
2095
2096 return static_cast<GLint>(maxLength);
2097 }
2098
getAttributes() const2099 const std::vector<sh::ShaderVariable> &Program::getAttributes() const
2100 {
2101 ASSERT(!mLinkingState);
2102 return mState.mExecutable->getProgramInputs();
2103 }
2104
getComputeShaderLocalSize() const2105 const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
2106 {
2107 ASSERT(!mLinkingState);
2108 return mState.mComputeShaderLocalSize;
2109 }
2110
getGeometryShaderInputPrimitiveType() const2111 PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
2112 {
2113 ASSERT(!mLinkingState && mState.mExecutable);
2114 return mState.mExecutable->getGeometryShaderInputPrimitiveType();
2115 }
getGeometryShaderOutputPrimitiveType() const2116 PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
2117 {
2118 ASSERT(!mLinkingState && mState.mExecutable);
2119 return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
2120 }
getGeometryShaderInvocations() const2121 GLint Program::getGeometryShaderInvocations() const
2122 {
2123 ASSERT(!mLinkingState && mState.mExecutable);
2124 return mState.mExecutable->getGeometryShaderInvocations();
2125 }
getGeometryShaderMaxVertices() const2126 GLint Program::getGeometryShaderMaxVertices() const
2127 {
2128 ASSERT(!mLinkingState && mState.mExecutable);
2129 return mState.mExecutable->getGeometryShaderMaxVertices();
2130 }
2131
getTessControlShaderVertices() const2132 GLint Program::getTessControlShaderVertices() const
2133 {
2134 ASSERT(!mLinkingState && mState.mExecutable);
2135 return mState.mExecutable->mTessControlShaderVertices;
2136 }
2137
getTessGenMode() const2138 GLenum Program::getTessGenMode() const
2139 {
2140 ASSERT(!mLinkingState && mState.mExecutable);
2141 return mState.mExecutable->mTessGenMode;
2142 }
2143
getTessGenPointMode() const2144 GLenum Program::getTessGenPointMode() const
2145 {
2146 ASSERT(!mLinkingState && mState.mExecutable);
2147 return mState.mExecutable->mTessGenPointMode;
2148 }
2149
getTessGenSpacing() const2150 GLenum Program::getTessGenSpacing() const
2151 {
2152 ASSERT(!mLinkingState && mState.mExecutable);
2153 return mState.mExecutable->mTessGenSpacing;
2154 }
2155
getTessGenVertexOrder() const2156 GLenum Program::getTessGenVertexOrder() const
2157 {
2158 ASSERT(!mLinkingState && mState.mExecutable);
2159 return mState.mExecutable->mTessGenVertexOrder;
2160 }
2161
getInputResource(size_t index) const2162 const sh::ShaderVariable &Program::getInputResource(size_t index) const
2163 {
2164 ASSERT(!mLinkingState);
2165 ASSERT(index < mState.mExecutable->getProgramInputs().size());
2166 return mState.mExecutable->getProgramInputs()[index];
2167 }
2168
getInputResourceIndex(const GLchar * name) const2169 GLuint Program::getInputResourceIndex(const GLchar *name) const
2170 {
2171 ASSERT(!mLinkingState);
2172 const std::string nameString = StripLastArrayIndex(name);
2173
2174 for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
2175 {
2176 sh::ShaderVariable resource = getInputResource(index);
2177 if (resource.name == nameString)
2178 {
2179 return static_cast<GLuint>(index);
2180 }
2181 }
2182
2183 return GL_INVALID_INDEX;
2184 }
2185
getResourceMaxNameSize(const sh::ShaderVariable & resource,GLint max) const2186 GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
2187 {
2188 if (resource.isArray())
2189 {
2190 return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
2191 }
2192 else
2193 {
2194 return std::max(max, clampCast<GLint>((resource.name).size()));
2195 }
2196 }
2197
getInputResourceMaxNameSize() const2198 GLuint Program::getInputResourceMaxNameSize() const
2199 {
2200 GLint max = 0;
2201
2202 for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
2203 {
2204 max = getResourceMaxNameSize(resource, max);
2205 }
2206
2207 return max;
2208 }
2209
getOutputResourceMaxNameSize() const2210 GLuint Program::getOutputResourceMaxNameSize() const
2211 {
2212 GLint max = 0;
2213
2214 for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
2215 {
2216 max = getResourceMaxNameSize(resource, max);
2217 }
2218
2219 return max;
2220 }
2221
getResourceLocation(const GLchar * name,const sh::ShaderVariable & variable) const2222 GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
2223 {
2224 if (variable.isBuiltIn())
2225 {
2226 return GL_INVALID_INDEX;
2227 }
2228
2229 GLint location = variable.location;
2230 if (variable.isArray())
2231 {
2232 size_t nameLengthWithoutArrayIndexOut;
2233 size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
2234 // The 'name' string may not contain the array notation "[0]"
2235 if (arrayIndex != GL_INVALID_INDEX)
2236 {
2237 location += arrayIndex;
2238 }
2239 }
2240
2241 return location;
2242 }
2243
getInputResourceLocation(const GLchar * name) const2244 GLuint Program::getInputResourceLocation(const GLchar *name) const
2245 {
2246 const GLuint index = getInputResourceIndex(name);
2247 if (index == GL_INVALID_INDEX)
2248 {
2249 return index;
2250 }
2251
2252 const sh::ShaderVariable &variable = getInputResource(index);
2253
2254 return getResourceLocation(name, variable);
2255 }
2256
getOutputResourceLocation(const GLchar * name) const2257 GLuint Program::getOutputResourceLocation(const GLchar *name) const
2258 {
2259 const GLuint index = getOutputResourceIndex(name);
2260 if (index == GL_INVALID_INDEX)
2261 {
2262 return index;
2263 }
2264
2265 const sh::ShaderVariable &variable = getOutputResource(index);
2266
2267 return getResourceLocation(name, variable);
2268 }
2269
getOutputResourceIndex(const GLchar * name) const2270 GLuint Program::getOutputResourceIndex(const GLchar *name) const
2271 {
2272 ASSERT(!mLinkingState);
2273 const std::string nameString = StripLastArrayIndex(name);
2274
2275 for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
2276 {
2277 sh::ShaderVariable resource = getOutputResource(index);
2278 if (resource.name == nameString)
2279 {
2280 return static_cast<GLuint>(index);
2281 }
2282 }
2283
2284 return GL_INVALID_INDEX;
2285 }
2286
getOutputResourceCount() const2287 size_t Program::getOutputResourceCount() const
2288 {
2289 ASSERT(!mLinkingState);
2290 return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
2291 }
2292
getOutputVariableTypes() const2293 const std::vector<GLenum> &Program::getOutputVariableTypes() const
2294 {
2295 ASSERT(!mLinkingState);
2296 return mState.mOutputVariableTypes;
2297 }
2298
getResourceName(const std::string name,GLsizei bufSize,GLsizei * length,GLchar * dest) const2299 void Program::getResourceName(const std::string name,
2300 GLsizei bufSize,
2301 GLsizei *length,
2302 GLchar *dest) const
2303 {
2304 if (length)
2305 {
2306 *length = 0;
2307 }
2308
2309 if (!mLinked)
2310 {
2311 if (bufSize > 0)
2312 {
2313 dest[0] = '\0';
2314 }
2315 return;
2316 }
2317
2318 if (bufSize > 0)
2319 {
2320 CopyStringToBuffer(dest, name, bufSize, length);
2321 }
2322 }
2323
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2324 void Program::getInputResourceName(GLuint index,
2325 GLsizei bufSize,
2326 GLsizei *length,
2327 GLchar *name) const
2328 {
2329 ASSERT(!mLinkingState);
2330 getResourceName(getInputResourceName(index), bufSize, length, name);
2331 }
2332
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2333 void Program::getOutputResourceName(GLuint index,
2334 GLsizei bufSize,
2335 GLsizei *length,
2336 GLchar *name) const
2337 {
2338 ASSERT(!mLinkingState);
2339 getResourceName(getOutputResourceName(index), bufSize, length, name);
2340 }
2341
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2342 void Program::getUniformResourceName(GLuint index,
2343 GLsizei bufSize,
2344 GLsizei *length,
2345 GLchar *name) const
2346 {
2347 ASSERT(!mLinkingState);
2348 ASSERT(index < mState.mExecutable->getUniforms().size());
2349 getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
2350 }
2351
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2352 void Program::getBufferVariableResourceName(GLuint index,
2353 GLsizei bufSize,
2354 GLsizei *length,
2355 GLchar *name) const
2356 {
2357 ASSERT(!mLinkingState);
2358 ASSERT(index < mState.mBufferVariables.size());
2359 getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
2360 }
2361
getResourceName(const sh::ShaderVariable & resource) const2362 const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
2363 {
2364 std::string resourceName = resource.name;
2365
2366 if (resource.isArray())
2367 {
2368 resourceName += "[0]";
2369 }
2370
2371 return resourceName;
2372 }
2373
getInputResourceName(GLuint index) const2374 const std::string Program::getInputResourceName(GLuint index) const
2375 {
2376 ASSERT(!mLinkingState);
2377 const sh::ShaderVariable &resource = getInputResource(index);
2378
2379 return getResourceName(resource);
2380 }
2381
getOutputResourceName(GLuint index) const2382 const std::string Program::getOutputResourceName(GLuint index) const
2383 {
2384 ASSERT(!mLinkingState);
2385 const sh::ShaderVariable &resource = getOutputResource(index);
2386
2387 return getResourceName(resource);
2388 }
2389
getOutputResource(size_t index) const2390 const sh::ShaderVariable &Program::getOutputResource(size_t index) const
2391 {
2392 ASSERT(!mLinkingState);
2393 ASSERT(index < mState.mExecutable->getOutputVariables().size());
2394 return mState.mExecutable->getOutputVariables()[index];
2395 }
2396
getAttributeBindings() const2397 const ProgramBindings &Program::getAttributeBindings() const
2398 {
2399 ASSERT(!mLinkingState);
2400 return mAttributeBindings;
2401 }
getUniformLocationBindings() const2402 const ProgramAliasedBindings &Program::getUniformLocationBindings() const
2403 {
2404 ASSERT(!mLinkingState);
2405 return mState.mUniformLocationBindings;
2406 }
2407
getFragmentOutputLocations() const2408 const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
2409 {
2410 ASSERT(!mLinkingState);
2411 return mFragmentOutputLocations;
2412 }
2413
getFragmentOutputIndexes() const2414 const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
2415 {
2416 ASSERT(!mLinkingState);
2417 return mFragmentOutputIndexes;
2418 }
2419
getDrawBufferTypeMask() const2420 ComponentTypeMask Program::getDrawBufferTypeMask() const
2421 {
2422 ASSERT(!mLinkingState);
2423 return mState.mDrawBufferTypeMask;
2424 }
2425
getTransformFeedbackStrides() const2426 const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
2427 {
2428 ASSERT(!mLinkingState);
2429 return mState.mExecutable->getTransformFeedbackStrides();
2430 }
2431
getFragDataLocation(const std::string & name) const2432 GLint Program::getFragDataLocation(const std::string &name) const
2433 {
2434 ASSERT(!mLinkingState);
2435 GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
2436 mState.mExecutable->getOutputLocations(), name);
2437 if (primaryLocation != -1)
2438 {
2439 return primaryLocation;
2440 }
2441 return GetVariableLocation(mState.mExecutable->getOutputVariables(),
2442 mState.mExecutable->getSecondaryOutputLocations(), name);
2443 }
2444
getFragDataIndex(const std::string & name) const2445 GLint Program::getFragDataIndex(const std::string &name) const
2446 {
2447 ASSERT(!mLinkingState);
2448 if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2449 mState.mExecutable->getOutputLocations(), name) != -1)
2450 {
2451 return 0;
2452 }
2453 if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
2454 mState.mExecutable->getSecondaryOutputLocations(), name) != -1)
2455 {
2456 return 1;
2457 }
2458 return -1;
2459 }
2460
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2461 void Program::getActiveUniform(GLuint index,
2462 GLsizei bufsize,
2463 GLsizei *length,
2464 GLint *size,
2465 GLenum *type,
2466 GLchar *name) const
2467 {
2468 ASSERT(!mLinkingState);
2469 if (mLinked)
2470 {
2471 // index must be smaller than getActiveUniformCount()
2472 ASSERT(index < mState.mExecutable->getUniforms().size());
2473 const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
2474
2475 if (bufsize > 0)
2476 {
2477 std::string string = uniform.name;
2478 CopyStringToBuffer(name, string, bufsize, length);
2479 }
2480
2481 *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
2482 *type = uniform.type;
2483 }
2484 else
2485 {
2486 if (bufsize > 0)
2487 {
2488 name[0] = '\0';
2489 }
2490
2491 if (length)
2492 {
2493 *length = 0;
2494 }
2495
2496 *size = 0;
2497 *type = GL_NONE;
2498 }
2499 }
2500
getActiveUniformCount() const2501 GLint Program::getActiveUniformCount() const
2502 {
2503 ASSERT(!mLinkingState);
2504 if (mLinked)
2505 {
2506 return static_cast<GLint>(mState.mExecutable->getUniforms().size());
2507 }
2508 else
2509 {
2510 return 0;
2511 }
2512 }
2513
getActiveBufferVariableCount() const2514 size_t Program::getActiveBufferVariableCount() const
2515 {
2516 ASSERT(!mLinkingState);
2517 return mLinked ? mState.mBufferVariables.size() : 0;
2518 }
2519
getActiveUniformMaxLength() const2520 GLint Program::getActiveUniformMaxLength() const
2521 {
2522 ASSERT(!mLinkingState);
2523 size_t maxLength = 0;
2524
2525 if (mLinked)
2526 {
2527 for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
2528 {
2529 if (!uniform.name.empty())
2530 {
2531 size_t length = uniform.name.length() + 1u;
2532 if (uniform.isArray())
2533 {
2534 length += 3; // Counting in "[0]".
2535 }
2536 maxLength = std::max(length, maxLength);
2537 }
2538 }
2539 }
2540
2541 return static_cast<GLint>(maxLength);
2542 }
2543
isValidUniformLocation(UniformLocation location) const2544 bool Program::isValidUniformLocation(UniformLocation location) const
2545 {
2546 ASSERT(!mLinkingState);
2547 ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
2548 return (location.value >= 0 &&
2549 static_cast<size_t>(location.value) < mState.mUniformLocations.size() &&
2550 mState.mUniformLocations[static_cast<size_t>(location.value)].used());
2551 }
2552
getUniformByLocation(UniformLocation location) const2553 const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const
2554 {
2555 ASSERT(!mLinkingState);
2556 ASSERT(location.value >= 0 &&
2557 static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2558 return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
2559 }
2560
getUniformLocation(UniformLocation location) const2561 const VariableLocation &Program::getUniformLocation(UniformLocation location) const
2562 {
2563 ASSERT(!mLinkingState);
2564 ASSERT(location.value >= 0 &&
2565 static_cast<size_t>(location.value) < mState.mUniformLocations.size());
2566 return mState.mUniformLocations[location.value];
2567 }
2568
getBufferVariableByIndex(GLuint index) const2569 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
2570 {
2571 ASSERT(!mLinkingState);
2572 ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
2573 return mState.mBufferVariables[index];
2574 }
2575
getUniformLocation(const std::string & name) const2576 UniformLocation Program::getUniformLocation(const std::string &name) const
2577 {
2578 ASSERT(!mLinkingState);
2579 return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
2580 }
2581
getUniformIndex(const std::string & name) const2582 GLuint Program::getUniformIndex(const std::string &name) const
2583 {
2584 ASSERT(!mLinkingState);
2585 return mState.getUniformIndexFromName(name);
2586 }
2587
shouldIgnoreUniform(UniformLocation location) const2588 bool Program::shouldIgnoreUniform(UniformLocation location) const
2589 {
2590 if (location.value == -1)
2591 {
2592 return true;
2593 }
2594
2595 if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored)
2596 {
2597 return true;
2598 }
2599
2600 return false;
2601 }
2602
setUniform1fv(UniformLocation location,GLsizei count,const GLfloat * v)2603 void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
2604 {
2605 ASSERT(!mLinkingState);
2606 if (shouldIgnoreUniform(location))
2607 {
2608 return;
2609 }
2610
2611 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2612 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2613 mProgram->setUniform1fv(location.value, clampedCount, v);
2614 }
2615
setUniform2fv(UniformLocation location,GLsizei count,const GLfloat * v)2616 void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
2617 {
2618 ASSERT(!mLinkingState);
2619 if (shouldIgnoreUniform(location))
2620 {
2621 return;
2622 }
2623
2624 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2625 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2626 mProgram->setUniform2fv(location.value, clampedCount, v);
2627 }
2628
setUniform3fv(UniformLocation location,GLsizei count,const GLfloat * v)2629 void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
2630 {
2631 ASSERT(!mLinkingState);
2632 if (shouldIgnoreUniform(location))
2633 {
2634 return;
2635 }
2636
2637 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2638 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2639 mProgram->setUniform3fv(location.value, clampedCount, v);
2640 }
2641
setUniform4fv(UniformLocation location,GLsizei count,const GLfloat * v)2642 void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
2643 {
2644 ASSERT(!mLinkingState);
2645 if (shouldIgnoreUniform(location))
2646 {
2647 return;
2648 }
2649
2650 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2651 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2652 mProgram->setUniform4fv(location.value, clampedCount, v);
2653 }
2654
setUniform1iv(Context * context,UniformLocation location,GLsizei count,const GLint * v)2655 void Program::setUniform1iv(Context *context,
2656 UniformLocation location,
2657 GLsizei count,
2658 const GLint *v)
2659 {
2660 ASSERT(!mLinkingState);
2661 if (shouldIgnoreUniform(location))
2662 {
2663 return;
2664 }
2665
2666 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2667 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2668
2669 mProgram->setUniform1iv(location.value, clampedCount, v);
2670
2671 if (mState.isSamplerUniformIndex(locationInfo.index))
2672 {
2673 updateSamplerUniform(context, locationInfo, clampedCount, v);
2674 }
2675 }
2676
setUniform2iv(UniformLocation location,GLsizei count,const GLint * v)2677 void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
2678 {
2679 ASSERT(!mLinkingState);
2680 if (shouldIgnoreUniform(location))
2681 {
2682 return;
2683 }
2684
2685 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2686 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2687 mProgram->setUniform2iv(location.value, clampedCount, v);
2688 }
2689
setUniform3iv(UniformLocation location,GLsizei count,const GLint * v)2690 void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
2691 {
2692 ASSERT(!mLinkingState);
2693 if (shouldIgnoreUniform(location))
2694 {
2695 return;
2696 }
2697
2698 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2699 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2700 mProgram->setUniform3iv(location.value, clampedCount, v);
2701 }
2702
setUniform4iv(UniformLocation location,GLsizei count,const GLint * v)2703 void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
2704 {
2705 ASSERT(!mLinkingState);
2706 if (shouldIgnoreUniform(location))
2707 {
2708 return;
2709 }
2710
2711 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2712 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2713 mProgram->setUniform4iv(location.value, clampedCount, v);
2714 }
2715
setUniform1uiv(UniformLocation location,GLsizei count,const GLuint * v)2716 void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
2717 {
2718 ASSERT(!mLinkingState);
2719 if (shouldIgnoreUniform(location))
2720 {
2721 return;
2722 }
2723
2724 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2725 GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
2726 mProgram->setUniform1uiv(location.value, clampedCount, v);
2727 }
2728
setUniform2uiv(UniformLocation location,GLsizei count,const GLuint * v)2729 void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
2730 {
2731 ASSERT(!mLinkingState);
2732 if (shouldIgnoreUniform(location))
2733 {
2734 return;
2735 }
2736
2737 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2738 GLsizei clampedCount = clampUniformCount(locationInfo, count, 2, v);
2739 mProgram->setUniform2uiv(location.value, clampedCount, v);
2740 }
2741
setUniform3uiv(UniformLocation location,GLsizei count,const GLuint * v)2742 void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
2743 {
2744 ASSERT(!mLinkingState);
2745 if (shouldIgnoreUniform(location))
2746 {
2747 return;
2748 }
2749
2750 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2751 GLsizei clampedCount = clampUniformCount(locationInfo, count, 3, v);
2752 mProgram->setUniform3uiv(location.value, clampedCount, v);
2753 }
2754
setUniform4uiv(UniformLocation location,GLsizei count,const GLuint * v)2755 void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
2756 {
2757 ASSERT(!mLinkingState);
2758 if (shouldIgnoreUniform(location))
2759 {
2760 return;
2761 }
2762
2763 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
2764 GLsizei clampedCount = clampUniformCount(locationInfo, count, 4, v);
2765 mProgram->setUniform4uiv(location.value, clampedCount, v);
2766 }
2767
setUniformMatrix2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2768 void Program::setUniformMatrix2fv(UniformLocation location,
2769 GLsizei count,
2770 GLboolean transpose,
2771 const GLfloat *v)
2772 {
2773 ASSERT(!mLinkingState);
2774 if (shouldIgnoreUniform(location))
2775 {
2776 return;
2777 }
2778
2779 GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
2780 mProgram->setUniformMatrix2fv(location.value, clampedCount, transpose, v);
2781 }
2782
setUniformMatrix3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2783 void Program::setUniformMatrix3fv(UniformLocation location,
2784 GLsizei count,
2785 GLboolean transpose,
2786 const GLfloat *v)
2787 {
2788 ASSERT(!mLinkingState);
2789 if (shouldIgnoreUniform(location))
2790 {
2791 return;
2792 }
2793
2794 GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
2795 mProgram->setUniformMatrix3fv(location.value, clampedCount, transpose, v);
2796 }
2797
setUniformMatrix4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2798 void Program::setUniformMatrix4fv(UniformLocation location,
2799 GLsizei count,
2800 GLboolean transpose,
2801 const GLfloat *v)
2802 {
2803 ASSERT(!mLinkingState);
2804 if (shouldIgnoreUniform(location))
2805 {
2806 return;
2807 }
2808
2809 GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
2810 mProgram->setUniformMatrix4fv(location.value, clampedCount, transpose, v);
2811 }
2812
setUniformMatrix2x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2813 void Program::setUniformMatrix2x3fv(UniformLocation location,
2814 GLsizei count,
2815 GLboolean transpose,
2816 const GLfloat *v)
2817 {
2818 ASSERT(!mLinkingState);
2819 if (shouldIgnoreUniform(location))
2820 {
2821 return;
2822 }
2823
2824 GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
2825 mProgram->setUniformMatrix2x3fv(location.value, clampedCount, transpose, v);
2826 }
2827
setUniformMatrix2x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2828 void Program::setUniformMatrix2x4fv(UniformLocation location,
2829 GLsizei count,
2830 GLboolean transpose,
2831 const GLfloat *v)
2832 {
2833 ASSERT(!mLinkingState);
2834 if (shouldIgnoreUniform(location))
2835 {
2836 return;
2837 }
2838
2839 GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
2840 mProgram->setUniformMatrix2x4fv(location.value, clampedCount, transpose, v);
2841 }
2842
setUniformMatrix3x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2843 void Program::setUniformMatrix3x2fv(UniformLocation location,
2844 GLsizei count,
2845 GLboolean transpose,
2846 const GLfloat *v)
2847 {
2848 ASSERT(!mLinkingState);
2849 if (shouldIgnoreUniform(location))
2850 {
2851 return;
2852 }
2853
2854 GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
2855 mProgram->setUniformMatrix3x2fv(location.value, clampedCount, transpose, v);
2856 }
2857
setUniformMatrix3x4fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2858 void Program::setUniformMatrix3x4fv(UniformLocation location,
2859 GLsizei count,
2860 GLboolean transpose,
2861 const GLfloat *v)
2862 {
2863 ASSERT(!mLinkingState);
2864 if (shouldIgnoreUniform(location))
2865 {
2866 return;
2867 }
2868
2869 GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
2870 mProgram->setUniformMatrix3x4fv(location.value, clampedCount, transpose, v);
2871 }
2872
setUniformMatrix4x2fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2873 void Program::setUniformMatrix4x2fv(UniformLocation location,
2874 GLsizei count,
2875 GLboolean transpose,
2876 const GLfloat *v)
2877 {
2878 ASSERT(!mLinkingState);
2879 if (shouldIgnoreUniform(location))
2880 {
2881 return;
2882 }
2883
2884 GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
2885 mProgram->setUniformMatrix4x2fv(location.value, clampedCount, transpose, v);
2886 }
2887
setUniformMatrix4x3fv(UniformLocation location,GLsizei count,GLboolean transpose,const GLfloat * v)2888 void Program::setUniformMatrix4x3fv(UniformLocation location,
2889 GLsizei count,
2890 GLboolean transpose,
2891 const GLfloat *v)
2892 {
2893 ASSERT(!mLinkingState);
2894 if (shouldIgnoreUniform(location))
2895 {
2896 return;
2897 }
2898
2899 GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
2900 mProgram->setUniformMatrix4x3fv(location.value, clampedCount, transpose, v);
2901 }
2902
getSamplerUniformBinding(const VariableLocation & uniformLocation) const2903 GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
2904 {
2905 ASSERT(!mLinkingState);
2906 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
2907 const std::vector<GLuint> &boundTextureUnits =
2908 mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
2909 return (uniformLocation.arrayIndex < boundTextureUnits.size())
2910 ? boundTextureUnits[uniformLocation.arrayIndex]
2911 : 0;
2912 }
2913
getImageUniformBinding(const VariableLocation & uniformLocation) const2914 GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
2915 {
2916 ASSERT(!mLinkingState);
2917 GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
2918
2919 const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings();
2920 const std::vector<GLuint> &boundImageUnits = imageBindings[imageIndex].boundImageUnits;
2921 return boundImageUnits[uniformLocation.arrayIndex];
2922 }
2923
getUniformfv(const Context * context,UniformLocation location,GLfloat * v) const2924 void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const
2925 {
2926 ASSERT(!mLinkingState);
2927 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2928 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2929
2930 if (uniform.isSampler())
2931 {
2932 *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
2933 return;
2934 }
2935 else if (uniform.isImage())
2936 {
2937 *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
2938 return;
2939 }
2940
2941 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2942 if (nativeType == GL_FLOAT)
2943 {
2944 mProgram->getUniformfv(context, location.value, v);
2945 }
2946 else
2947 {
2948 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2949 }
2950 }
2951
getUniformiv(const Context * context,UniformLocation location,GLint * v) const2952 void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const
2953 {
2954 ASSERT(!mLinkingState);
2955 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2956 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2957
2958 if (uniform.isSampler())
2959 {
2960 *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
2961 return;
2962 }
2963 else if (uniform.isImage())
2964 {
2965 *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
2966 return;
2967 }
2968
2969 const GLenum nativeType = gl::VariableComponentType(uniform.type);
2970 if (nativeType == GL_INT || nativeType == GL_BOOL)
2971 {
2972 mProgram->getUniformiv(context, location.value, v);
2973 }
2974 else
2975 {
2976 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
2977 }
2978 }
2979
getUniformuiv(const Context * context,UniformLocation location,GLuint * v) const2980 void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const
2981 {
2982 ASSERT(!mLinkingState);
2983 const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
2984 const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
2985
2986 if (uniform.isSampler())
2987 {
2988 *v = getSamplerUniformBinding(uniformLocation);
2989 return;
2990 }
2991 else if (uniform.isImage())
2992 {
2993 *v = getImageUniformBinding(uniformLocation);
2994 return;
2995 }
2996
2997 const GLenum nativeType = VariableComponentType(uniform.type);
2998 if (nativeType == GL_UNSIGNED_INT)
2999 {
3000 mProgram->getUniformuiv(context, location.value, v);
3001 }
3002 else
3003 {
3004 getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
3005 }
3006 }
3007
flagForDeletion()3008 void Program::flagForDeletion()
3009 {
3010 ASSERT(!mLinkingState);
3011 mDeleteStatus = true;
3012 }
3013
isFlaggedForDeletion() const3014 bool Program::isFlaggedForDeletion() const
3015 {
3016 ASSERT(!mLinkingState);
3017 return mDeleteStatus;
3018 }
3019
validate(const Caps & caps)3020 void Program::validate(const Caps &caps)
3021 {
3022 ASSERT(!mLinkingState);
3023 mState.mExecutable->resetInfoLog();
3024 InfoLog &infoLog = mState.mExecutable->getInfoLog();
3025
3026 if (mLinked)
3027 {
3028 mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
3029 }
3030 else
3031 {
3032 infoLog << "Program has not been successfully linked.";
3033 }
3034 }
3035
isValidated() const3036 bool Program::isValidated() const
3037 {
3038 ASSERT(!mLinkingState);
3039 return mValidated;
3040 }
3041
getActiveUniformBlockName(const UniformBlockIndex blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3042 void Program::getActiveUniformBlockName(const UniformBlockIndex blockIndex,
3043 GLsizei bufSize,
3044 GLsizei *length,
3045 GLchar *blockName) const
3046 {
3047 ASSERT(!mLinkingState);
3048 GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
3049 blockName);
3050 }
3051
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const3052 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
3053 GLsizei bufSize,
3054 GLsizei *length,
3055 GLchar *blockName) const
3056 {
3057 ASSERT(!mLinkingState);
3058 GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize,
3059 length, blockName);
3060 }
3061
3062 template <typename T>
getActiveInterfaceBlockMaxNameLength(const std::vector<T> & resources) const3063 GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
3064 {
3065 int maxLength = 0;
3066
3067 if (mLinked)
3068 {
3069 for (const T &resource : resources)
3070 {
3071 if (!resource.name.empty())
3072 {
3073 int length = static_cast<int>(resource.nameWithArrayIndex().length());
3074 maxLength = std::max(length + 1, maxLength);
3075 }
3076 }
3077 }
3078
3079 return maxLength;
3080 }
3081
getActiveUniformBlockMaxNameLength() const3082 GLint Program::getActiveUniformBlockMaxNameLength() const
3083 {
3084 ASSERT(!mLinkingState);
3085 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
3086 }
3087
getActiveShaderStorageBlockMaxNameLength() const3088 GLint Program::getActiveShaderStorageBlockMaxNameLength() const
3089 {
3090 ASSERT(!mLinkingState);
3091 return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
3092 }
3093
getUniformBlockIndex(const std::string & name) const3094 GLuint Program::getUniformBlockIndex(const std::string &name) const
3095 {
3096 ASSERT(!mLinkingState);
3097 return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
3098 }
3099
getShaderStorageBlockIndex(const std::string & name) const3100 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
3101 {
3102 ASSERT(!mLinkingState);
3103 return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
3104 }
3105
getUniformBlockByIndex(GLuint index) const3106 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
3107 {
3108 ASSERT(!mLinkingState);
3109 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
3110 return mState.mExecutable->getUniformBlocks()[index];
3111 }
3112
getShaderStorageBlockByIndex(GLuint index) const3113 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
3114 {
3115 ASSERT(!mLinkingState);
3116 ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
3117 return mState.mExecutable->getShaderStorageBlocks()[index];
3118 }
3119
bindUniformBlock(UniformBlockIndex uniformBlockIndex,GLuint uniformBlockBinding)3120 void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
3121 {
3122 ASSERT(!mLinkingState);
3123 mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding;
3124 mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value,
3125 uniformBlockBinding != 0);
3126 mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value);
3127 }
3128
getUniformBlockBinding(GLuint uniformBlockIndex) const3129 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
3130 {
3131 ASSERT(!mLinkingState);
3132 return mState.getUniformBlockBinding(uniformBlockIndex);
3133 }
3134
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const3135 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
3136 {
3137 ASSERT(!mLinkingState);
3138 return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
3139 }
3140
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)3141 void Program::setTransformFeedbackVaryings(GLsizei count,
3142 const GLchar *const *varyings,
3143 GLenum bufferMode)
3144 {
3145 ASSERT(!mLinkingState);
3146 mState.mTransformFeedbackVaryingNames.resize(count);
3147 for (GLsizei i = 0; i < count; i++)
3148 {
3149 mState.mTransformFeedbackVaryingNames[i] = varyings[i];
3150 }
3151
3152 mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
3153 }
3154
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const3155 void Program::getTransformFeedbackVarying(GLuint index,
3156 GLsizei bufSize,
3157 GLsizei *length,
3158 GLsizei *size,
3159 GLenum *type,
3160 GLchar *name) const
3161 {
3162 ASSERT(!mLinkingState);
3163 if (mLinked)
3164 {
3165 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3166 const auto &var = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3167 std::string varName = var.nameWithArrayIndex();
3168 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
3169 if (length)
3170 {
3171 *length = lastNameIdx;
3172 }
3173 if (size)
3174 {
3175 *size = var.size();
3176 }
3177 if (type)
3178 {
3179 *type = var.type;
3180 }
3181 if (name)
3182 {
3183 memcpy(name, varName.c_str(), lastNameIdx);
3184 name[lastNameIdx] = '\0';
3185 }
3186 }
3187 }
3188
getTransformFeedbackVaryingCount() const3189 GLsizei Program::getTransformFeedbackVaryingCount() const
3190 {
3191 ASSERT(!mLinkingState);
3192 if (mLinked)
3193 {
3194 return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3195 }
3196 else
3197 {
3198 return 0;
3199 }
3200 }
3201
getTransformFeedbackVaryingMaxLength() const3202 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
3203 {
3204 ASSERT(!mLinkingState);
3205 if (mLinked)
3206 {
3207 GLsizei maxSize = 0;
3208 for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
3209 {
3210 maxSize =
3211 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
3212 }
3213
3214 return maxSize;
3215 }
3216 else
3217 {
3218 return 0;
3219 }
3220 }
3221
getTransformFeedbackBufferMode() const3222 GLenum Program::getTransformFeedbackBufferMode() const
3223 {
3224 ASSERT(!mLinkingState);
3225 return mState.mExecutable->getTransformFeedbackBufferMode();
3226 }
3227
linkValidateShaders(InfoLog & infoLog)3228 bool Program::linkValidateShaders(InfoLog &infoLog)
3229 {
3230 const ShaderMap<Shader *> &shaders = mState.mAttachedShaders;
3231
3232 bool isComputeShaderAttached = shaders[ShaderType::Compute] != nullptr;
3233 bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] ||
3234 shaders[ShaderType::TessControl] ||
3235 shaders[ShaderType::TessEvaluation] ||
3236 shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment];
3237 // Check whether we both have a compute and non-compute shaders attached.
3238 // If there are of both types attached, then linking should fail.
3239 // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
3240 if (isComputeShaderAttached && isGraphicsShaderAttached)
3241 {
3242 infoLog << "Both compute and graphics shaders are attached to the same program.";
3243 return false;
3244 }
3245
3246 Optional<int> version;
3247 for (ShaderType shaderType : kAllGraphicsShaderTypes)
3248 {
3249 Shader *shader = shaders[shaderType];
3250 ASSERT(!shader || shader->getType() == shaderType);
3251 if (!shader)
3252 {
3253 continue;
3254 }
3255
3256 if (!shader->isCompiled())
3257 {
3258 infoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
3259 return false;
3260 }
3261
3262 if (!version.valid())
3263 {
3264 version = shader->getShaderVersion();
3265 }
3266 else if (version != shader->getShaderVersion())
3267 {
3268 infoLog << ShaderTypeToString(shaderType)
3269 << " shader version does not match other shader versions.";
3270 return false;
3271 }
3272 }
3273
3274 if (isComputeShaderAttached)
3275 {
3276 ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute);
3277
3278 mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize();
3279
3280 // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
3281 // If the work group size is not specified, a link time error should occur.
3282 if (!mState.mComputeShaderLocalSize.isDeclared())
3283 {
3284 infoLog << "Work group size is not specified.";
3285 return false;
3286 }
3287 }
3288 else
3289 {
3290 if (!isGraphicsShaderAttached)
3291 {
3292 infoLog << "No compiled shaders.";
3293 return false;
3294 }
3295
3296 bool hasVertex = shaders[ShaderType::Vertex] != nullptr;
3297 bool hasFragment = shaders[ShaderType::Fragment] != nullptr;
3298 if (!isSeparable() && (!hasVertex || !hasFragment))
3299 {
3300 infoLog
3301 << "The program must contain objects to form both a vertex and fragment shader.";
3302 return false;
3303 }
3304
3305 bool hasTessControl = shaders[ShaderType::TessControl] != nullptr;
3306 bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr;
3307 if (!isSeparable() && (hasTessControl != hasTessEvaluation))
3308 {
3309 infoLog << "Tessellation control and evaluation shaders must be specified together.";
3310 return false;
3311 }
3312
3313 Shader *geometryShader = shaders[ShaderType::Geometry];
3314 if (shaders[ShaderType::Geometry])
3315 {
3316 // [GL_EXT_geometry_shader] Chapter 7
3317 // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
3318 // Language Specification, as well as any of the following reasons:
3319 // * One or more of the shader objects attached to <program> are not compiled
3320 // successfully.
3321 // * The shaders do not use the same shader language version.
3322 // * <program> contains objects to form a geometry shader, and
3323 // - <program> is not separable and contains no objects to form a vertex shader; or
3324 // - the input primitive type, output primitive type, or maximum output vertex count
3325 // is not specified in the compiled geometry shader object.
3326 ASSERT(geometryShader->getType() == ShaderType::Geometry);
3327
3328 Optional<PrimitiveMode> inputPrimitive =
3329 geometryShader->getGeometryShaderInputPrimitiveType();
3330 if (!inputPrimitive.valid())
3331 {
3332 infoLog << "Input primitive type is not specified in the geometry shader.";
3333 return false;
3334 }
3335
3336 Optional<PrimitiveMode> outputPrimitive =
3337 geometryShader->getGeometryShaderOutputPrimitiveType();
3338 if (!outputPrimitive.valid())
3339 {
3340 infoLog << "Output primitive type is not specified in the geometry shader.";
3341 return false;
3342 }
3343
3344 Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices();
3345 if (!maxVertices.valid())
3346 {
3347 infoLog << "'max_vertices' is not specified in the geometry shader.";
3348 return false;
3349 }
3350
3351 mState.mExecutable->mGeometryShaderInputPrimitiveType = inputPrimitive.value();
3352 mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
3353 mState.mExecutable->mGeometryShaderMaxVertices = maxVertices.value();
3354 mState.mExecutable->mGeometryShaderInvocations =
3355 geometryShader->getGeometryShaderInvocations();
3356 }
3357
3358 Shader *tessControlShader = shaders[ShaderType::TessControl];
3359 if (tessControlShader)
3360 {
3361 int tcsShaderVertices = tessControlShader->getTessControlShaderVertices();
3362 if (tcsShaderVertices == 0)
3363 {
3364 // In tessellation control shader, output vertices should be specified at least
3365 // once.
3366 // > GLSL ES Version 3.20.6 spec:
3367 // > 4.4.2. Output Layout Qualifiers
3368 // > Tessellation Control Outputs
3369 // > ...
3370 // > There must be at least one layout qualifier specifying an output patch vertex
3371 // > count in any program containing a tessellation control shader.
3372 infoLog << "In Tessellation Control Shader, at least one layout qualifier "
3373 "specifying an output patch vertex count must exist.";
3374 return false;
3375 }
3376
3377 mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
3378 }
3379
3380 Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
3381 if (tessEvaluationShader)
3382 {
3383 GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode();
3384 if (tesPrimitiveMode == 0)
3385 {
3386 // In tessellation evaluation shader, a primitive mode should be specified at least
3387 // once.
3388 // > GLSL ES Version 3.20.6 spec:
3389 // > 4.4.1. Input Layout Qualifiers
3390 // > Tessellation Evaluation Inputs
3391 // > ...
3392 // > The tessellation evaluation shader object in a program must declare a primitive
3393 // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
3394 // > identifiers is optional.
3395 infoLog << "The Tessellation Evaluation Shader object in a program must declare a "
3396 "primitive mode in its input layout.";
3397 return false;
3398 }
3399
3400 mState.mExecutable->mTessGenMode = tesPrimitiveMode;
3401 mState.mExecutable->mTessGenSpacing = tessEvaluationShader->getTessGenSpacing();
3402 mState.mExecutable->mTessGenVertexOrder = tessEvaluationShader->getTessGenVertexOrder();
3403 mState.mExecutable->mTessGenPointMode = tessEvaluationShader->getTessGenPointMode();
3404 }
3405 }
3406
3407 return true;
3408 }
3409
getTransformFeedbackVaryingResourceIndex(const GLchar * name) const3410 GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
3411 {
3412 ASSERT(!mLinkingState);
3413 for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
3414 ++tfIndex)
3415 {
3416 const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
3417 if (tf.nameWithArrayIndex() == name)
3418 {
3419 return tfIndex;
3420 }
3421 }
3422 return GL_INVALID_INDEX;
3423 }
3424
getTransformFeedbackVaryingResource(GLuint index) const3425 const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
3426 {
3427 ASSERT(!mLinkingState);
3428 ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
3429 return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
3430 }
3431
hasDrawIDUniform() const3432 bool Program::hasDrawIDUniform() const
3433 {
3434 ASSERT(!mLinkingState);
3435 return mState.mDrawIDLocation >= 0;
3436 }
3437
setDrawIDUniform(GLint drawid)3438 void Program::setDrawIDUniform(GLint drawid)
3439 {
3440 ASSERT(!mLinkingState);
3441 ASSERT(mState.mDrawIDLocation >= 0);
3442 mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
3443 }
3444
hasBaseVertexUniform() const3445 bool Program::hasBaseVertexUniform() const
3446 {
3447 ASSERT(!mLinkingState);
3448 return mState.mBaseVertexLocation >= 0;
3449 }
3450
setBaseVertexUniform(GLint baseVertex)3451 void Program::setBaseVertexUniform(GLint baseVertex)
3452 {
3453 ASSERT(!mLinkingState);
3454 ASSERT(mState.mBaseVertexLocation >= 0);
3455 if (baseVertex == mState.mCachedBaseVertex)
3456 {
3457 return;
3458 }
3459 mState.mCachedBaseVertex = baseVertex;
3460 mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
3461 }
3462
hasBaseInstanceUniform() const3463 bool Program::hasBaseInstanceUniform() const
3464 {
3465 ASSERT(!mLinkingState);
3466 return mState.mBaseInstanceLocation >= 0;
3467 }
3468
setBaseInstanceUniform(GLuint baseInstance)3469 void Program::setBaseInstanceUniform(GLuint baseInstance)
3470 {
3471 ASSERT(!mLinkingState);
3472 ASSERT(mState.mBaseInstanceLocation >= 0);
3473 if (baseInstance == mState.mCachedBaseInstance)
3474 {
3475 return;
3476 }
3477 mState.mCachedBaseInstance = baseInstance;
3478 GLint baseInstanceInt = baseInstance;
3479 mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
3480 }
3481
linkVaryings(InfoLog & infoLog) const3482 bool Program::linkVaryings(InfoLog &infoLog) const
3483 {
3484 ShaderType previousShaderType = ShaderType::InvalidEnum;
3485 for (ShaderType shaderType : kAllGraphicsShaderTypes)
3486 {
3487 Shader *currentShader = mState.mAttachedShaders[shaderType];
3488 if (!currentShader)
3489 {
3490 continue;
3491 }
3492
3493 if (previousShaderType != ShaderType::InvalidEnum)
3494 {
3495 Shader *previousShader = mState.mAttachedShaders[previousShaderType];
3496 const std::vector<sh::ShaderVariable> &outputVaryings =
3497 previousShader->getOutputVaryings();
3498
3499 if (!LinkValidateShaderInterfaceMatching(
3500 outputVaryings, currentShader->getInputVaryings(), previousShaderType,
3501 currentShader->getType(), previousShader->getShaderVersion(),
3502 currentShader->getShaderVersion(), isSeparable(), infoLog))
3503 {
3504 return false;
3505 }
3506 }
3507 previousShaderType = currentShader->getType();
3508 }
3509
3510 // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
3511 // Need to move logic of validating builtin varyings inside the for-loop above.
3512 // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
3513 // can be redeclared in Geometry or Tessellation shaders as well.
3514 Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
3515 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
3516 if (vertexShader && fragmentShader &&
3517 !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(),
3518 fragmentShader->getInputVaryings(), vertexShader->getType(),
3519 fragmentShader->getType(), vertexShader->getShaderVersion(),
3520 fragmentShader->getShaderVersion(), infoLog))
3521 {
3522 return false;
3523 }
3524
3525 return true;
3526 }
3527
linkUniforms(const Caps & caps,const Version & version,InfoLog & infoLog,const ProgramAliasedBindings & uniformLocationBindings,GLuint * combinedImageUniformsCount,std::vector<UnusedUniform> * unusedUniforms)3528 bool Program::linkUniforms(const Caps &caps,
3529 const Version &version,
3530 InfoLog &infoLog,
3531 const ProgramAliasedBindings &uniformLocationBindings,
3532 GLuint *combinedImageUniformsCount,
3533 std::vector<UnusedUniform> *unusedUniforms)
3534 {
3535 UniformLinker linker(mState);
3536 if (!linker.link(caps, infoLog, uniformLocationBindings))
3537 {
3538 return false;
3539 }
3540
3541 linker.getResults(&mState.mExecutable->mUniforms, unusedUniforms, &mState.mUniformLocations);
3542
3543 linkSamplerAndImageBindings(combinedImageUniformsCount);
3544
3545 if (!linkAtomicCounterBuffers())
3546 {
3547 return false;
3548 }
3549
3550 if (version >= Version(3, 1))
3551 {
3552 GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size());
3553
3554 if (locationSize > caps.maxUniformLocations)
3555 {
3556 infoLog << "Exceeded maximum uniform location size";
3557 return false;
3558 }
3559 }
3560
3561 return true;
3562 }
3563
linkSamplerAndImageBindings(GLuint * combinedImageUniforms)3564 void Program::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
3565 {
3566 ASSERT(combinedImageUniforms);
3567
3568 // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
3569 // atomic counters, images and samplers in that order.
3570 auto highIter = mState.mExecutable->getUniforms().rbegin();
3571 auto lowIter = highIter;
3572
3573 unsigned int high = static_cast<unsigned int>(mState.mExecutable->getUniforms().size());
3574 unsigned int low = high;
3575
3576 // Note that uniform block uniforms are not yet appended to this list.
3577 ASSERT(mState.mExecutable->getUniforms().size() == 0 || highIter->isAtomicCounter() ||
3578 highIter->isImage() || highIter->isSampler() || highIter->isInDefaultBlock() ||
3579 highIter->isFragmentInOut);
3580
3581 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isFragmentInOut;
3582 ++lowIter)
3583 {
3584 --low;
3585 }
3586
3587 mState.mExecutable->mFragmentInoutRange = RangeUI(low, high);
3588
3589 highIter = lowIter;
3590 high = low;
3591
3592 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isAtomicCounter();
3593 ++lowIter)
3594 {
3595 --low;
3596 }
3597
3598 mState.mAtomicCounterUniformRange = RangeUI(low, high);
3599
3600 highIter = lowIter;
3601 high = low;
3602
3603 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isImage(); ++lowIter)
3604 {
3605 --low;
3606 }
3607
3608 mState.mExecutable->mImageUniformRange = RangeUI(low, high);
3609 *combinedImageUniforms = 0u;
3610 // The Program is still linking, so getExecutable().isCompute() isn't accurate yet.
3611 bool hasComputeShader = mState.mAttachedShaders[ShaderType::Compute] != nullptr;
3612 std::vector<ImageBinding> &imageBindings = hasComputeShader
3613 ? mState.mExecutable->mComputeImageBindings
3614 : mState.mExecutable->mGraphicsImageBindings;
3615 // If uniform is a image type, insert it into the mImageBindings array.
3616 for (unsigned int imageIndex : mState.mExecutable->getImageUniformRange())
3617 {
3618 // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
3619 // cannot load values into a uniform defined as an image. if declare without a
3620 // binding qualifier, any uniform image variable (include all elements of
3621 // unbound image array) shoud be bound to unit zero.
3622 auto &imageUniform = mState.mExecutable->getUniforms()[imageIndex];
3623 TextureType textureType = ImageTypeToTextureType(imageUniform.type);
3624 const GLuint arraySize = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
3625
3626 if (imageUniform.binding == -1)
3627 {
3628 imageBindings.emplace_back(
3629 ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
3630 }
3631 else
3632 {
3633 // The arrays of arrays are flattened to arrays, it needs to record the array offset for
3634 // the correct binding image unit.
3635 imageBindings.emplace_back(
3636 ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize,
3637 imageUniform.getBasicTypeElementCount(), textureType));
3638 }
3639
3640 *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
3641 }
3642
3643 highIter = lowIter;
3644 high = low;
3645
3646 for (; lowIter != mState.mExecutable->getUniforms().rend() && lowIter->isSampler(); ++lowIter)
3647 {
3648 --low;
3649 }
3650
3651 mState.mExecutable->mSamplerUniformRange = RangeUI(low, high);
3652
3653 // If uniform is a sampler type, insert it into the mSamplerBindings array.
3654 for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
3655 {
3656 const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
3657 TextureType textureType = SamplerTypeToTextureType(samplerUniform.type);
3658 GLenum samplerType = samplerUniform.typeInfo->type;
3659 unsigned int elementCount = samplerUniform.getBasicTypeElementCount();
3660 SamplerFormat format = samplerUniform.typeInfo->samplerFormat;
3661 mState.mExecutable->mSamplerBindings.emplace_back(textureType, samplerType, format,
3662 elementCount);
3663 }
3664
3665 // Whatever is left constitutes the default uniforms.
3666 mState.mExecutable->mDefaultUniformRange = RangeUI(0, low);
3667 }
3668
linkAtomicCounterBuffers()3669 bool Program::linkAtomicCounterBuffers()
3670 {
3671 for (unsigned int index : mState.mAtomicCounterUniformRange)
3672 {
3673 auto &uniform = mState.mExecutable->mUniforms[index];
3674 uniform.blockInfo.offset = uniform.offset;
3675 uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0);
3676 uniform.blockInfo.matrixStride = 0;
3677 uniform.blockInfo.isRowMajorMatrix = false;
3678
3679 bool found = false;
3680 for (unsigned int bufferIndex = 0;
3681 bufferIndex < mState.mExecutable->getActiveAtomicCounterBufferCount(); ++bufferIndex)
3682 {
3683 auto &buffer = mState.mExecutable->mAtomicCounterBuffers[bufferIndex];
3684 if (buffer.binding == uniform.binding)
3685 {
3686 buffer.memberIndexes.push_back(index);
3687 uniform.bufferIndex = bufferIndex;
3688 found = true;
3689 buffer.unionReferencesWith(uniform);
3690 break;
3691 }
3692 }
3693 if (!found)
3694 {
3695 AtomicCounterBuffer atomicCounterBuffer;
3696 atomicCounterBuffer.binding = uniform.binding;
3697 atomicCounterBuffer.memberIndexes.push_back(index);
3698 atomicCounterBuffer.unionReferencesWith(uniform);
3699 mState.mExecutable->mAtomicCounterBuffers.push_back(atomicCounterBuffer);
3700 uniform.bufferIndex =
3701 static_cast<int>(mState.mExecutable->getActiveAtomicCounterBufferCount() - 1);
3702 }
3703 }
3704 // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
3705 // gl_Max[Vertex|Fragment|Compute|Geometry|Combined]AtomicCounterBuffers.
3706
3707 return true;
3708 }
3709
3710 // Assigns locations to all attributes (except built-ins) from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)3711 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
3712 {
3713 const Caps &caps = context->getCaps();
3714 const Limitations &limitations = context->getLimitations();
3715 bool webglCompatibility = context->getExtensions().webglCompatibility;
3716 int shaderVersion = -1;
3717 unsigned int usedLocations = 0;
3718
3719 Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
3720
3721 if (!vertexShader)
3722 {
3723 // No vertex shader, so no attributes, so nothing to do
3724 return true;
3725 }
3726
3727 shaderVersion = vertexShader->getShaderVersion();
3728 if (shaderVersion >= 300)
3729 {
3730 // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
3731 // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
3732 // aliasing checks.
3733 mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes();
3734 }
3735 else
3736 {
3737 // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
3738 mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes();
3739 }
3740
3741 GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
3742 std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
3743
3744 // Assign locations to attributes that have a binding location and check for attribute aliasing.
3745 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3746 {
3747 // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
3748 // structures, so we don't need to worry about adjusting their names or generating entries
3749 // for each member/element (unlike uniforms for example).
3750 ASSERT(!attribute.isArray() && !attribute.isStruct());
3751
3752 int bindingLocation = mAttributeBindings.getBinding(attribute);
3753 if (attribute.location == -1 && bindingLocation != -1)
3754 {
3755 attribute.location = bindingLocation;
3756 }
3757
3758 if (attribute.location != -1)
3759 {
3760 // Location is set by glBindAttribLocation or by location layout qualifier
3761 const int regs = VariableRegisterCount(attribute.type);
3762
3763 if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
3764 {
3765 infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
3766 << " is too big to fit";
3767
3768 return false;
3769 }
3770
3771 for (int reg = 0; reg < regs; reg++)
3772 {
3773 const int regLocation = attribute.location + reg;
3774 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
3775
3776 // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
3777 // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
3778 // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
3779 // In D3D 9 and 11, aliasing is not supported, so check a limitation.
3780 if (linkedAttribute)
3781 {
3782 if (shaderVersion >= 300 || webglCompatibility ||
3783 limitations.noVertexAttributeAliasing)
3784 {
3785 infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
3786 << linkedAttribute->name << "' at location " << regLocation;
3787 return false;
3788 }
3789 }
3790 else
3791 {
3792 usedAttribMap[regLocation] = &attribute;
3793 }
3794
3795 usedLocations |= 1 << regLocation;
3796 }
3797 }
3798 }
3799
3800 // Assign locations to attributes that don't have a binding location.
3801 for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
3802 {
3803 // Not set by glBindAttribLocation or by location layout qualifier
3804 if (attribute.location == -1)
3805 {
3806 int regs = VariableRegisterCount(attribute.type);
3807 int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
3808
3809 if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
3810 {
3811 infoLog << "Too many attributes (" << attribute.name << ")";
3812 return false;
3813 }
3814
3815 attribute.location = availableIndex;
3816 }
3817 }
3818
3819 ASSERT(mState.mExecutable->mAttributesTypeMask.none());
3820 ASSERT(mState.mExecutable->mAttributesMask.none());
3821
3822 // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
3823 // shader versions we're only processing active attributes to begin with.
3824 if (shaderVersion >= 300)
3825 {
3826 for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
3827 attributeIter != mState.mExecutable->getProgramInputs().end();)
3828 {
3829 if (attributeIter->active)
3830 {
3831 ++attributeIter;
3832 }
3833 else
3834 {
3835 attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
3836 }
3837 }
3838 }
3839
3840 for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
3841 {
3842 ASSERT(attribute.active);
3843 ASSERT(attribute.location != -1);
3844 unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
3845
3846 unsigned int location = static_cast<unsigned int>(attribute.location);
3847 for (unsigned int r = 0; r < regs; r++)
3848 {
3849 // Built-in active program inputs don't have a bound attribute.
3850 if (!attribute.isBuiltIn())
3851 {
3852 mState.mExecutable->mActiveAttribLocationsMask.set(location);
3853 mState.mExecutable->mMaxActiveAttribLocation =
3854 std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
3855
3856 ComponentType componentType =
3857 GLenumToComponentType(VariableComponentType(attribute.type));
3858
3859 SetComponentTypeMask(componentType, location,
3860 &mState.mExecutable->mAttributesTypeMask);
3861 mState.mExecutable->mAttributesMask.set(location);
3862
3863 location++;
3864 }
3865 }
3866 }
3867
3868 return true;
3869 }
3870
linkInterfaceBlocks(const Caps & caps,const Version & version,bool webglCompatibility,InfoLog & infoLog,GLuint * combinedShaderStorageBlocksCount)3871 bool Program::linkInterfaceBlocks(const Caps &caps,
3872 const Version &version,
3873 bool webglCompatibility,
3874 InfoLog &infoLog,
3875 GLuint *combinedShaderStorageBlocksCount)
3876 {
3877 ASSERT(combinedShaderStorageBlocksCount);
3878
3879 GLuint combinedUniformBlocksCount = 0u;
3880 GLuint numShadersHasUniformBlocks = 0u;
3881 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
3882 InterfaceBlockMap instancelessInterfaceBlocksFields;
3883
3884 for (ShaderType shaderType : AllShaderTypes())
3885 {
3886 Shader *shader = mState.mAttachedShaders[shaderType];
3887 if (!shader)
3888 {
3889 continue;
3890 }
3891
3892 const auto &uniformBlocks = shader->getUniformBlocks();
3893 if (!uniformBlocks.empty())
3894 {
3895 if (!ValidateInterfaceBlocksCount(
3896 static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks,
3897 shaderType, sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
3898 {
3899 return false;
3900 }
3901
3902 allShaderUniformBlocks[shaderType] = &uniformBlocks;
3903 ++numShadersHasUniformBlocks;
3904 }
3905 }
3906
3907 if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks))
3908 {
3909 infoLog << "The sum of the number of active uniform blocks exceeds "
3910 "MAX_COMBINED_UNIFORM_BLOCKS ("
3911 << caps.maxCombinedUniformBlocks << ").";
3912 return false;
3913 }
3914
3915 if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
3916 webglCompatibility, &instancelessInterfaceBlocksFields))
3917 {
3918 return false;
3919 }
3920
3921 if (version >= Version(3, 1))
3922 {
3923 *combinedShaderStorageBlocksCount = 0u;
3924 GLuint numShadersHasShaderStorageBlocks = 0u;
3925 ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
3926 for (ShaderType shaderType : AllShaderTypes())
3927 {
3928 Shader *shader = mState.mAttachedShaders[shaderType];
3929 if (!shader)
3930 {
3931 continue;
3932 }
3933
3934 const auto &shaderStorageBlocks = shader->getShaderStorageBlocks();
3935 if (!shaderStorageBlocks.empty())
3936 {
3937 if (!ValidateInterfaceBlocksCount(
3938 static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]),
3939 shaderStorageBlocks, shaderType, sh::BlockType::BLOCK_BUFFER,
3940 combinedShaderStorageBlocksCount, infoLog))
3941 {
3942 return false;
3943 }
3944
3945 allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
3946 ++numShadersHasShaderStorageBlocks;
3947 }
3948 }
3949
3950 if (*combinedShaderStorageBlocksCount >
3951 static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks))
3952 {
3953 infoLog << "The sum of the number of active shader storage blocks exceeds "
3954 "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
3955 << caps.maxCombinedShaderStorageBlocks << ").";
3956 return false;
3957 }
3958
3959 if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
3960 infoLog, webglCompatibility,
3961 &instancelessInterfaceBlocksFields))
3962 {
3963 return false;
3964 }
3965 }
3966
3967 return true;
3968 }
3969
getOutputLocationForLink(const sh::ShaderVariable & outputVariable) const3970 int Program::getOutputLocationForLink(const sh::ShaderVariable &outputVariable) const
3971 {
3972 if (outputVariable.location != -1)
3973 {
3974 return outputVariable.location;
3975 }
3976 int apiLocation = mFragmentOutputLocations.getBinding(outputVariable);
3977 if (apiLocation != -1)
3978 {
3979 return apiLocation;
3980 }
3981 return -1;
3982 }
3983
isOutputSecondaryForLink(const sh::ShaderVariable & outputVariable) const3984 bool Program::isOutputSecondaryForLink(const sh::ShaderVariable &outputVariable) const
3985 {
3986 if (outputVariable.index != -1)
3987 {
3988 ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
3989 return (outputVariable.index == 1);
3990 }
3991 int apiIndex = mFragmentOutputIndexes.getBinding(outputVariable);
3992 if (apiIndex != -1)
3993 {
3994 // Index layout qualifier from the shader takes precedence, so the index from the API is
3995 // checked only if the index was not set in the shader. This is not specified in the EXT
3996 // spec, but is specified in desktop OpenGL specs.
3997 return (apiIndex == 1);
3998 }
3999 // EXT_blend_func_extended: Outputs get index 0 by default.
4000 return false;
4001 }
4002
4003 namespace
4004 {
4005
FindUsedOutputLocation(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex)4006 bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
4007 unsigned int baseLocation,
4008 unsigned int elementCount,
4009 const std::vector<VariableLocation> &reservedLocations,
4010 unsigned int variableIndex)
4011 {
4012 if (baseLocation + elementCount > outputLocations.size())
4013 {
4014 elementCount = baseLocation < outputLocations.size()
4015 ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
4016 : 0;
4017 }
4018 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4019 {
4020 const unsigned int location = baseLocation + elementIndex;
4021 if (outputLocations[location].used())
4022 {
4023 VariableLocation locationInfo(elementIndex, variableIndex);
4024 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4025 reservedLocations.end())
4026 {
4027 return true;
4028 }
4029 }
4030 }
4031 return false;
4032 }
4033
AssignOutputLocations(std::vector<VariableLocation> & outputLocations,unsigned int baseLocation,unsigned int elementCount,const std::vector<VariableLocation> & reservedLocations,unsigned int variableIndex,sh::ShaderVariable & outputVariable)4034 void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
4035 unsigned int baseLocation,
4036 unsigned int elementCount,
4037 const std::vector<VariableLocation> &reservedLocations,
4038 unsigned int variableIndex,
4039 sh::ShaderVariable &outputVariable)
4040 {
4041 if (baseLocation + elementCount > outputLocations.size())
4042 {
4043 outputLocations.resize(baseLocation + elementCount);
4044 }
4045 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4046 {
4047 VariableLocation locationInfo(elementIndex, variableIndex);
4048 if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
4049 reservedLocations.end())
4050 {
4051 outputVariable.location = baseLocation;
4052 const unsigned int location = baseLocation + elementIndex;
4053 outputLocations[location] = locationInfo;
4054 }
4055 }
4056 }
4057
4058 } // anonymous namespace
4059
linkOutputVariables(const Caps & caps,const Extensions & extensions,const Version & version,GLuint combinedImageUniformsCount,GLuint combinedShaderStorageBlocksCount)4060 bool Program::linkOutputVariables(const Caps &caps,
4061 const Extensions &extensions,
4062 const Version &version,
4063 GLuint combinedImageUniformsCount,
4064 GLuint combinedShaderStorageBlocksCount)
4065 {
4066 InfoLog &infoLog = mState.mExecutable->getInfoLog();
4067 Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
4068
4069 ASSERT(mState.mOutputVariableTypes.empty());
4070 ASSERT(mState.mActiveOutputVariables.none());
4071 ASSERT(mState.mDrawBufferTypeMask.none());
4072 ASSERT(!mState.mYUVOutput);
4073
4074 if (!fragmentShader)
4075 {
4076 // No fragment shader, so nothing to link
4077 return true;
4078 }
4079
4080 const std::vector<sh::ShaderVariable> &outputVariables =
4081 fragmentShader->getActiveOutputVariables();
4082
4083 // Gather output variable types
4084 for (const sh::ShaderVariable &outputVariable : outputVariables)
4085 {
4086 if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
4087 outputVariable.name != "gl_FragData")
4088 {
4089 continue;
4090 }
4091
4092 unsigned int baseLocation =
4093 (outputVariable.location == -1 ? 0u
4094 : static_cast<unsigned int>(outputVariable.location));
4095
4096 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4097 // structures, so we may use getBasicTypeElementCount().
4098 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4099 for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
4100 {
4101 const unsigned int location = baseLocation + elementIndex;
4102 if (location >= mState.mOutputVariableTypes.size())
4103 {
4104 mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
4105 }
4106 ASSERT(location < mState.mActiveOutputVariables.size());
4107 mState.mActiveOutputVariables.set(location);
4108 mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
4109 ComponentType componentType =
4110 GLenumToComponentType(mState.mOutputVariableTypes[location]);
4111 SetComponentTypeMask(componentType, location, &mState.mDrawBufferTypeMask);
4112 }
4113
4114 if (outputVariable.yuv)
4115 {
4116 ASSERT(outputVariables.size() == 1);
4117 mState.mYUVOutput = true;
4118 }
4119 }
4120
4121 if (version >= ES_3_1)
4122 {
4123 // [OpenGL ES 3.1] Chapter 8.22 Page 203:
4124 // A link error will be generated if the sum of the number of active image uniforms used in
4125 // all shaders, the number of active shader storage blocks, and the number of active
4126 // fragment shader outputs exceeds the implementation-dependent value of
4127 // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
4128 if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
4129 mState.mActiveOutputVariables.count() >
4130 static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
4131 {
4132 infoLog
4133 << "The sum of the number of active image uniforms, active shader storage blocks "
4134 "and active fragment shader outputs exceeds "
4135 "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
4136 << caps.maxCombinedShaderOutputResources << ")";
4137 return false;
4138 }
4139 }
4140
4141 // Skip this step for GLES2 shaders.
4142 if (fragmentShader && fragmentShader->getShaderVersion() == 100)
4143 return true;
4144
4145 mState.mExecutable->mOutputVariables = outputVariables;
4146 mState.mExecutable->mYUVOutput = mState.mYUVOutput;
4147 // TODO(jmadill): any caps validation here?
4148
4149 // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
4150 // output array in explicit terms.
4151 //
4152 // Assuming fragData is an output array, you can defend the position that:
4153 // P1) you must support binding "fragData" because it's specified
4154 // P2) you must support querying "fragData[x]" because it's specified
4155 // P3) you must support binding "fragData[0]" because it's a frequently used pattern
4156 //
4157 // Then you can make the leap of faith:
4158 // P4) you must support binding "fragData[x]" because you support "fragData[0]"
4159 // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
4160 //
4161 // The spec brings in the "world of arrays" when it mentions binding the arrays and the
4162 // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
4163 // must infer the only possible interpretation (?). Note again: this need of interpretation
4164 // might be completely off of what GL spec logic is.
4165 //
4166 // The other complexity is that unless you implement this feature, it's hard to understand what
4167 // should happen when the client invokes the feature. You cannot add an additional error as it
4168 // is not specified. One can ignore it, but obviously it creates the discrepancies...
4169
4170 std::vector<VariableLocation> reservedLocations;
4171
4172 // Process any output API bindings for arrays that don't alias to the first element.
4173 for (const auto &binding : mFragmentOutputLocations)
4174 {
4175 size_t nameLengthWithoutArrayIndex;
4176 unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
4177 if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
4178 {
4179 continue;
4180 }
4181 for (unsigned int outputVariableIndex = 0;
4182 outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4183 outputVariableIndex++)
4184 {
4185 const sh::ShaderVariable &outputVariable =
4186 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4187 // Check that the binding corresponds to an output array and its array index fits.
4188 if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
4189 !angle::BeginsWith(outputVariable.name, binding.first,
4190 nameLengthWithoutArrayIndex) ||
4191 arrayIndex >= outputVariable.getOutermostArraySize())
4192 {
4193 continue;
4194 }
4195
4196 // Get the API index that corresponds to this exact binding.
4197 // This index may differ from the index used for the array's base.
4198 auto &outputLocations = mFragmentOutputIndexes.getBindingByName(binding.first) == 1
4199 ? mState.mExecutable->mSecondaryOutputLocations
4200 : mState.mExecutable->mOutputLocations;
4201 unsigned int location = binding.second.location;
4202 VariableLocation locationInfo(arrayIndex, outputVariableIndex);
4203 if (location >= outputLocations.size())
4204 {
4205 outputLocations.resize(location + 1);
4206 }
4207 if (outputLocations[location].used())
4208 {
4209 infoLog << "Location of variable " << outputVariable.name
4210 << " conflicts with another variable.";
4211 return false;
4212 }
4213 outputLocations[location] = locationInfo;
4214
4215 // Note the array binding location so that it can be skipped later.
4216 reservedLocations.push_back(locationInfo);
4217 }
4218 }
4219
4220 // Reserve locations for output variables whose location is fixed in the shader or through the
4221 // API. Otherwise, the remaining unallocated outputs will be processed later.
4222 for (unsigned int outputVariableIndex = 0;
4223 outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4224 outputVariableIndex++)
4225 {
4226 const sh::ShaderVariable &outputVariable =
4227 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4228
4229 // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4230 if (outputVariable.isBuiltIn())
4231 continue;
4232
4233 int fixedLocation = getOutputLocationForLink(outputVariable);
4234 if (fixedLocation == -1)
4235 {
4236 // Here we're only reserving locations for variables whose location is fixed.
4237 continue;
4238 }
4239 unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
4240
4241 auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4242 ? mState.mExecutable->mSecondaryOutputLocations
4243 : mState.mExecutable->mOutputLocations;
4244
4245 // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
4246 // structures, so we may use getBasicTypeElementCount().
4247 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4248 if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
4249 outputVariableIndex))
4250 {
4251 infoLog << "Location of variable " << outputVariable.name
4252 << " conflicts with another variable.";
4253 return false;
4254 }
4255 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4256 outputVariableIndex,
4257 mState.mExecutable->mOutputVariables[outputVariableIndex]);
4258 }
4259
4260 // Here we assign locations for the output variables that don't yet have them. Note that we're
4261 // not necessarily able to fit the variables optimally, since then we might have to try
4262 // different arrangements of output arrays. Now we just assign the locations in the order that
4263 // we got the output variables. The spec isn't clear on what kind of algorithm is required for
4264 // finding locations for the output variables, so this should be acceptable at least for now.
4265 GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
4266 if (!mState.mExecutable->getSecondaryOutputLocations().empty())
4267 {
4268 // EXT_blend_func_extended: Program outputs will be validated against
4269 // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
4270 maxLocation = extensions.maxDualSourceDrawBuffers;
4271 }
4272
4273 for (unsigned int outputVariableIndex = 0;
4274 outputVariableIndex < mState.mExecutable->getOutputVariables().size();
4275 outputVariableIndex++)
4276 {
4277 const sh::ShaderVariable &outputVariable =
4278 mState.mExecutable->getOutputVariables()[outputVariableIndex];
4279
4280 // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
4281 if (outputVariable.isBuiltIn())
4282 continue;
4283
4284 int fixedLocation = getOutputLocationForLink(outputVariable);
4285 auto &outputLocations = isOutputSecondaryForLink(outputVariable)
4286 ? mState.mExecutable->mSecondaryOutputLocations
4287 : mState.mExecutable->mOutputLocations;
4288 unsigned int baseLocation = 0;
4289 unsigned int elementCount = outputVariable.getBasicTypeElementCount();
4290 if (fixedLocation != -1)
4291 {
4292 // Secondary inputs might have caused the max location to drop below what has already
4293 // been explicitly assigned locations. Check for any fixed locations above the max
4294 // that should cause linking to fail.
4295 baseLocation = static_cast<unsigned int>(fixedLocation);
4296 }
4297 else
4298 {
4299 // No fixed location, so try to fit the output in unassigned locations.
4300 // Try baseLocations starting from 0 one at a time and see if the variable fits.
4301 while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
4302 reservedLocations, outputVariableIndex))
4303 {
4304 baseLocation++;
4305 }
4306 AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
4307 outputVariableIndex,
4308 mState.mExecutable->mOutputVariables[outputVariableIndex]);
4309 }
4310
4311 // Check for any elements assigned above the max location that are actually used.
4312 if (baseLocation + elementCount > maxLocation &&
4313 (baseLocation >= maxLocation ||
4314 FindUsedOutputLocation(outputLocations, maxLocation,
4315 baseLocation + elementCount - maxLocation, reservedLocations,
4316 outputVariableIndex)))
4317 {
4318 // EXT_blend_func_extended: Linking can fail:
4319 // "if the explicit binding assignments do not leave enough space for the linker to
4320 // automatically assign a location for a varying out array, which requires multiple
4321 // contiguous locations."
4322 infoLog << "Could not fit output variable into available locations: "
4323 << outputVariable.name;
4324 return false;
4325 }
4326 }
4327
4328 return true;
4329 }
4330
setUniformValuesFromBindingQualifiers()4331 void Program::setUniformValuesFromBindingQualifiers()
4332 {
4333 for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
4334 {
4335 const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
4336 if (samplerUniform.binding != -1)
4337 {
4338 UniformLocation location = getUniformLocation(samplerUniform.name);
4339 ASSERT(location.value != -1);
4340 std::vector<GLint> boundTextureUnits;
4341 for (unsigned int elementIndex = 0;
4342 elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
4343 {
4344 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
4345 }
4346
4347 // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
4348 // We know it's safe not to notify the Context because this is only called after link.
4349 setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
4350 boundTextureUnits.data());
4351 }
4352 }
4353 }
4354
initInterfaceBlockBindings()4355 void Program::initInterfaceBlockBindings()
4356 {
4357 // Set initial bindings from shader.
4358 for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
4359 blockIndex++)
4360 {
4361 InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
4362 bindUniformBlock({blockIndex}, uniformBlock.binding);
4363 }
4364 }
4365
updateSamplerUniform(Context * context,const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)4366 void Program::updateSamplerUniform(Context *context,
4367 const VariableLocation &locationInfo,
4368 GLsizei clampedCount,
4369 const GLint *v)
4370 {
4371 ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
4372 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
4373 SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
4374 std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
4375
4376 if (locationInfo.arrayIndex >= boundTextureUnits.size())
4377 {
4378 return;
4379 }
4380 GLsizei safeUniformCount = std::min(
4381 clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
4382
4383 // Update the sampler uniforms.
4384 for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
4385 {
4386 GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
4387 GLint newTextureUnit = v[arrayIndex];
4388
4389 if (oldTextureUnit == newTextureUnit)
4390 {
4391 continue;
4392 }
4393
4394 boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
4395
4396 // Update the reference counts.
4397 uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
4398 uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit];
4399 ASSERT(oldRefCount > 0);
4400 ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
4401 oldRefCount--;
4402 newRefCount++;
4403
4404 // Check for binding type change.
4405 TextureType &newSamplerType = mState.mExecutable->mActiveSamplerTypes[newTextureUnit];
4406 TextureType &oldSamplerType = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit];
4407 SamplerFormat &newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit];
4408 SamplerFormat &oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit];
4409
4410 if (newRefCount == 1)
4411 {
4412 newSamplerType = samplerBinding.textureType;
4413 newSamplerFormat = samplerBinding.format;
4414 mState.mExecutable->mActiveSamplersMask.set(newTextureUnit);
4415 mState.mExecutable->mActiveSamplerShaderBits[newTextureUnit] =
4416 mState.mExecutable->getUniforms()[locationInfo.index].activeShaders();
4417 }
4418 else
4419 {
4420 if (newSamplerType != samplerBinding.textureType)
4421 {
4422 // Conflict detected. Ensure we reset it properly.
4423 newSamplerType = TextureType::InvalidEnum;
4424 }
4425 if (newSamplerFormat != samplerBinding.format)
4426 {
4427 newSamplerFormat = SamplerFormat::InvalidEnum;
4428 }
4429 }
4430
4431 // Unset previously active sampler.
4432 if (oldRefCount == 0)
4433 {
4434 oldSamplerType = TextureType::InvalidEnum;
4435 oldSamplerFormat = SamplerFormat::InvalidEnum;
4436 mState.mExecutable->mActiveSamplersMask.reset(oldTextureUnit);
4437 }
4438 else
4439 {
4440 if (oldSamplerType == TextureType::InvalidEnum ||
4441 oldSamplerFormat == SamplerFormat::InvalidEnum)
4442 {
4443 // Previous conflict. Check if this new change fixed the conflict.
4444 mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
4445 }
4446 }
4447
4448 // Update the observing PPO's executable, if any.
4449 // Do this before any of the Context work, since that uses the current ProgramExecutable,
4450 // which will be the PPO's if this Program is bound to it, rather than this Program's.
4451 if (isSeparable())
4452 {
4453 onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
4454 }
4455
4456 // Notify context.
4457 if (context)
4458 {
4459 context->onSamplerUniformChange(newTextureUnit);
4460 context->onSamplerUniformChange(oldTextureUnit);
4461 }
4462 }
4463
4464 // Invalidate the validation cache.
4465 getExecutable().resetCachedValidateSamplersResult();
4466 // Inform any PPOs this Program may be bound to.
4467 onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
4468 }
4469
setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)4470 void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
4471 {
4472 mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
4473 mExecutable->mSamplerBindings);
4474 }
4475
4476 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)4477 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
4478 GLsizei count,
4479 int vectorSize,
4480 const T *v)
4481 {
4482 if (count == 1)
4483 return 1;
4484
4485 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4486
4487 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4488 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4489 unsigned int remainingElements =
4490 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4491 GLsizei maxElementCount =
4492 static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
4493
4494 if (count * vectorSize > maxElementCount)
4495 {
4496 return maxElementCount / vectorSize;
4497 }
4498
4499 return count;
4500 }
4501
4502 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(UniformLocation location,GLsizei count,GLboolean transpose,const T * v)4503 GLsizei Program::clampMatrixUniformCount(UniformLocation location,
4504 GLsizei count,
4505 GLboolean transpose,
4506 const T *v)
4507 {
4508 const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
4509
4510 if (!transpose)
4511 {
4512 return clampUniformCount(locationInfo, count, cols * rows, v);
4513 }
4514
4515 const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
4516
4517 // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
4518 // element index used, as reported by GetActiveUniform, will be ignored by the GL."
4519 unsigned int remainingElements =
4520 linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
4521 return std::min(count, static_cast<GLsizei>(remainingElements));
4522 }
4523
4524 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
4525 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
4526 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,UniformLocation location,GLenum nativeType,int components) const4527 void Program::getUniformInternal(const Context *context,
4528 DestT *dataOut,
4529 UniformLocation location,
4530 GLenum nativeType,
4531 int components) const
4532 {
4533 switch (nativeType)
4534 {
4535 case GL_BOOL:
4536 {
4537 GLint tempValue[16] = {0};
4538 mProgram->getUniformiv(context, location.value, tempValue);
4539 UniformStateQueryCastLoop<GLboolean>(
4540 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4541 break;
4542 }
4543 case GL_INT:
4544 {
4545 GLint tempValue[16] = {0};
4546 mProgram->getUniformiv(context, location.value, tempValue);
4547 UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4548 components);
4549 break;
4550 }
4551 case GL_UNSIGNED_INT:
4552 {
4553 GLuint tempValue[16] = {0};
4554 mProgram->getUniformuiv(context, location.value, tempValue);
4555 UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
4556 components);
4557 break;
4558 }
4559 case GL_FLOAT:
4560 {
4561 GLfloat tempValue[16] = {0};
4562 mProgram->getUniformfv(context, location.value, tempValue);
4563 UniformStateQueryCastLoop<GLfloat>(
4564 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
4565 break;
4566 }
4567 default:
4568 UNREACHABLE();
4569 break;
4570 }
4571 }
4572
syncState(const Context * context)4573 angle::Result Program::syncState(const Context *context)
4574 {
4575 if (mDirtyBits.any())
4576 {
4577 ASSERT(!mLinkingState);
4578 ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
4579 mDirtyBits.reset();
4580 }
4581
4582 return angle::Result::Continue;
4583 }
4584
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const4585 angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
4586 {
4587 BinaryOutputStream stream;
4588
4589 stream.writeBytes(reinterpret_cast<const unsigned char *>(ANGLE_COMMIT_HASH),
4590 ANGLE_COMMIT_HASH_SIZE);
4591
4592 // nullptr context is supported when computing binary length.
4593 if (context)
4594 {
4595 stream.writeInt(context->getClientVersion().major);
4596 stream.writeInt(context->getClientVersion().minor);
4597 }
4598 else
4599 {
4600 stream.writeInt(2);
4601 stream.writeInt(0);
4602 }
4603
4604 // Must be before mExecutable->save(), since it uses the value.
4605 stream.writeBool(mState.mSeparable);
4606
4607 mState.mExecutable->save(mState.mSeparable, &stream);
4608
4609 const auto &computeLocalSize = mState.getComputeShaderLocalSize();
4610
4611 stream.writeInt(computeLocalSize[0]);
4612 stream.writeInt(computeLocalSize[1]);
4613 stream.writeInt(computeLocalSize[2]);
4614
4615 stream.writeInt(mState.mNumViews);
4616 stream.writeBool(mState.mEarlyFramentTestsOptimization);
4617 stream.writeInt(mState.mSpecConstUsageBits.bits());
4618
4619 stream.writeInt(mState.getUniformLocations().size());
4620 for (const auto &variable : mState.getUniformLocations())
4621 {
4622 stream.writeInt(variable.arrayIndex);
4623 stream.writeIntOrNegOne(variable.index);
4624 stream.writeBool(variable.ignored);
4625 }
4626
4627 stream.writeInt(mState.getBufferVariables().size());
4628 for (const BufferVariable &bufferVariable : mState.getBufferVariables())
4629 {
4630 WriteBufferVariable(&stream, bufferVariable);
4631 }
4632
4633 // Warn the app layer if saving a binary with unsupported transform feedback.
4634 if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
4635 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4636 {
4637 WARN() << "Saving program binary with transform feedback, which is not supported on this "
4638 "driver.";
4639 }
4640
4641 stream.writeInt(mState.mOutputVariableTypes.size());
4642 for (const auto &outputVariableType : mState.mOutputVariableTypes)
4643 {
4644 stream.writeInt(outputVariableType);
4645 }
4646
4647 static_assert(
4648 IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4649 "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
4650 stream.writeInt(static_cast<int>(mState.mDrawBufferTypeMask.to_ulong()));
4651 stream.writeInt(static_cast<int>(mState.mActiveOutputVariables.to_ulong()));
4652
4653 stream.writeBool(mState.isYUVOutput());
4654
4655 stream.writeInt(mState.getAtomicCounterUniformRange().low());
4656 stream.writeInt(mState.getAtomicCounterUniformRange().high());
4657
4658 mProgram->save(context, &stream);
4659
4660 ASSERT(binaryOut);
4661 if (!binaryOut->resize(stream.length()))
4662 {
4663 WARN() << "Failed to allocate enough memory to serialize a program. (" << stream.length()
4664 << " bytes )";
4665 return angle::Result::Incomplete;
4666 }
4667 memcpy(binaryOut->data(), stream.data(), stream.length());
4668 return angle::Result::Continue;
4669 }
4670
deserialize(const Context * context,BinaryInputStream & stream,InfoLog & infoLog)4671 angle::Result Program::deserialize(const Context *context,
4672 BinaryInputStream &stream,
4673 InfoLog &infoLog)
4674 {
4675 unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
4676 stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
4677 if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) !=
4678 0)
4679 {
4680 infoLog << "Invalid program binary version.";
4681 return angle::Result::Stop;
4682 }
4683
4684 int majorVersion = stream.readInt<int>();
4685 int minorVersion = stream.readInt<int>();
4686 if (majorVersion != context->getClientMajorVersion() ||
4687 minorVersion != context->getClientMinorVersion())
4688 {
4689 infoLog << "Cannot load program binaries across different ES context versions.";
4690 return angle::Result::Stop;
4691 }
4692
4693 // Must be before mExecutable->load(), since it uses the value.
4694 mState.mSeparable = stream.readBool();
4695
4696 mState.mExecutable->load(mState.mSeparable, &stream);
4697
4698 mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
4699 mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
4700 mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
4701
4702 mState.mNumViews = stream.readInt<int>();
4703 mState.mEarlyFramentTestsOptimization = stream.readBool();
4704 mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
4705
4706 const size_t uniformIndexCount = stream.readInt<size_t>();
4707 ASSERT(mState.mUniformLocations.empty());
4708 for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex)
4709 {
4710 VariableLocation variable;
4711 stream.readInt(&variable.arrayIndex);
4712 stream.readInt(&variable.index);
4713 stream.readBool(&variable.ignored);
4714
4715 mState.mUniformLocations.push_back(variable);
4716 }
4717
4718 size_t bufferVariableCount = stream.readInt<size_t>();
4719 ASSERT(mState.mBufferVariables.empty());
4720 for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
4721 {
4722 BufferVariable bufferVariable;
4723 LoadBufferVariable(&stream, &bufferVariable);
4724 mState.mBufferVariables.push_back(bufferVariable);
4725 }
4726
4727 size_t outputTypeCount = stream.readInt<size_t>();
4728 for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
4729 {
4730 mState.mOutputVariableTypes.push_back(stream.readInt<GLenum>());
4731 }
4732
4733 static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
4734 "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
4735 "into 32 bits each");
4736 mState.mDrawBufferTypeMask = gl::ComponentTypeMask(stream.readInt<uint32_t>());
4737 mState.mActiveOutputVariables =
4738 gl::DrawBufferMask(stream.readInt<gl::DrawBufferMask::value_type>());
4739
4740 stream.readBool(&mState.mYUVOutput);
4741
4742 unsigned int atomicCounterRangeLow = stream.readInt<unsigned int>();
4743 unsigned int atomicCounterRangeHigh = stream.readInt<unsigned int>();
4744 mState.mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
4745
4746 static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
4747 "Too many shader types");
4748
4749 // Reject programs that use transform feedback varyings if the hardware cannot support them.
4750 if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
4751 context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
4752 {
4753 infoLog << "Current driver does not support transform feedback in binary programs.";
4754 return angle::Result::Stop;
4755 }
4756
4757 if (!mState.mAttachedShaders[ShaderType::Compute])
4758 {
4759 mState.mExecutable->updateTransformFeedbackStrides();
4760 }
4761
4762 postResolveLink(context);
4763 mState.mExecutable->updateCanDrawWith();
4764
4765 return angle::Result::Continue;
4766 }
4767
postResolveLink(const gl::Context * context)4768 void Program::postResolveLink(const gl::Context *context)
4769 {
4770 mState.updateActiveSamplers();
4771 mState.mExecutable->mActiveImageShaderBits.fill({});
4772 mState.mExecutable->updateActiveImages(getExecutable());
4773
4774 setUniformValuesFromBindingQualifiers();
4775
4776 if (context->getExtensions().multiDraw)
4777 {
4778 mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value;
4779 }
4780
4781 if (context->getExtensions().baseVertexBaseInstance)
4782 {
4783 mState.mBaseVertexLocation = getUniformLocation("gl_BaseVertex").value;
4784 mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value;
4785 }
4786 }
4787
4788 // HasAttachedShaders implementation.
getTransformFeedbackStage() const4789 ShaderType HasAttachedShaders::getTransformFeedbackStage() const
4790 {
4791 if (getAttachedShader(ShaderType::Geometry))
4792 {
4793 return ShaderType::Geometry;
4794 }
4795 if (getAttachedShader(ShaderType::TessEvaluation))
4796 {
4797 return ShaderType::TessEvaluation;
4798 }
4799 return ShaderType::Vertex;
4800 }
4801 } // namespace gl
4802