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