1 //
2 // Copyright (c) 2002-2014 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 
14 #include "common/bitset_utils.h"
15 #include "common/debug.h"
16 #include "common/platform.h"
17 #include "common/string_utils.h"
18 #include "common/utilities.h"
19 #include "compiler/translator/blocklayout.h"
20 #include "libANGLE/Context.h"
21 #include "libANGLE/MemoryProgramCache.h"
22 #include "libANGLE/ProgramLinkedResources.h"
23 #include "libANGLE/ResourceManager.h"
24 #include "libANGLE/Uniform.h"
25 #include "libANGLE/VaryingPacking.h"
26 #include "libANGLE/features.h"
27 #include "libANGLE/histogram_macros.h"
28 #include "libANGLE/queryconversions.h"
29 #include "libANGLE/renderer/GLImplFactory.h"
30 #include "libANGLE/renderer/ProgramImpl.h"
31 #include "platform/Platform.h"
32 
33 namespace gl
34 {
35 
36 namespace
37 {
38 
39 // This simplified cast function doesn't need to worry about advanced concepts like
40 // depth range values, or casting to bool.
41 template <typename DestT, typename SrcT>
42 DestT UniformStateQueryCast(SrcT value);
43 
44 // From-Float-To-Integer Casts
45 template <>
UniformStateQueryCast(GLfloat value)46 GLint UniformStateQueryCast(GLfloat value)
47 {
48     return clampCast<GLint>(roundf(value));
49 }
50 
51 template <>
UniformStateQueryCast(GLfloat value)52 GLuint UniformStateQueryCast(GLfloat value)
53 {
54     return clampCast<GLuint>(roundf(value));
55 }
56 
57 // From-Integer-to-Integer Casts
58 template <>
UniformStateQueryCast(GLuint value)59 GLint UniformStateQueryCast(GLuint value)
60 {
61     return clampCast<GLint>(value);
62 }
63 
64 template <>
UniformStateQueryCast(GLint value)65 GLuint UniformStateQueryCast(GLint value)
66 {
67     return clampCast<GLuint>(value);
68 }
69 
70 // From-Boolean-to-Anything Casts
71 template <>
UniformStateQueryCast(GLboolean value)72 GLfloat UniformStateQueryCast(GLboolean value)
73 {
74     return (ConvertToBool(value) ? 1.0f : 0.0f);
75 }
76 
77 template <>
UniformStateQueryCast(GLboolean value)78 GLint UniformStateQueryCast(GLboolean value)
79 {
80     return (ConvertToBool(value) ? 1 : 0);
81 }
82 
83 template <>
UniformStateQueryCast(GLboolean value)84 GLuint UniformStateQueryCast(GLboolean value)
85 {
86     return (ConvertToBool(value) ? 1u : 0u);
87 }
88 
89 // Default to static_cast
90 template <typename DestT, typename SrcT>
91 DestT UniformStateQueryCast(SrcT value)
92 {
93     return static_cast<DestT>(value);
94 }
95 
96 template <typename SrcT, typename DestT>
UniformStateQueryCastLoop(DestT * dataOut,const uint8_t * srcPointer,int components)97 void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
98 {
99     for (int comp = 0; comp < components; ++comp)
100     {
101         // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
102         // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
103         size_t offset               = comp * 4;
104         const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
105         dataOut[comp]               = UniformStateQueryCast<DestT>(*typedSrcPointer);
106     }
107 }
108 
109 template <typename VarT>
GetResourceIndexFromName(const std::vector<VarT> & list,const std::string & name)110 GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
111 {
112     std::string nameAsArrayName = name + "[0]";
113     for (size_t index = 0; index < list.size(); index++)
114     {
115         const VarT &resource = list[index];
116         if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
117         {
118             return static_cast<GLuint>(index);
119         }
120     }
121 
122     return GL_INVALID_INDEX;
123 }
124 
125 template <typename VarT>
GetVariableLocation(const std::vector<VarT> & list,const std::vector<VariableLocation> & locationList,const std::string & name)126 GLint GetVariableLocation(const std::vector<VarT> &list,
127                           const std::vector<VariableLocation> &locationList,
128                           const std::string &name)
129 {
130     size_t nameLengthWithoutArrayIndex;
131     unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
132 
133     for (size_t location = 0u; location < locationList.size(); ++location)
134     {
135         const VariableLocation &variableLocation = locationList[location];
136         if (!variableLocation.used())
137         {
138             continue;
139         }
140 
141         const VarT &variable = list[variableLocation.index];
142 
143         if (angle::BeginsWith(variable.name, name))
144         {
145             if (name.length() == variable.name.length())
146             {
147                 ASSERT(name == variable.name);
148                 // GLES 3.1 November 2016 page 87.
149                 // The string exactly matches the name of the active variable.
150                 return static_cast<GLint>(location);
151             }
152             if (name.length() + 3u == variable.name.length() && variable.isArray())
153             {
154                 ASSERT(name + "[0]" == variable.name);
155                 // The string identifies the base name of an active array, where the string would
156                 // exactly match the name of the variable if the suffix "[0]" were appended to the
157                 // string.
158                 return static_cast<GLint>(location);
159             }
160         }
161         if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
162             nameLengthWithoutArrayIndex + 3u == variable.name.length() &&
163             angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
164         {
165             ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name);
166             // The string identifies an active element of the array, where the string ends with the
167             // concatenation of the "[" character, an integer (with no "+" sign, extra leading
168             // zeroes, or whitespace) identifying an array element, and the "]" character, the
169             // integer is less than the number of active elements of the array variable, and where
170             // the string would exactly match the enumerated name of the array if the decimal
171             // integer were replaced with zero.
172             return static_cast<GLint>(location);
173         }
174     }
175 
176     return -1;
177 }
178 
CopyStringToBuffer(GLchar * buffer,const std::string & string,GLsizei bufSize,GLsizei * length)179 void CopyStringToBuffer(GLchar *buffer, const std::string &string, GLsizei bufSize, GLsizei *length)
180 {
181     ASSERT(bufSize > 0);
182     strncpy(buffer, string.c_str(), bufSize);
183     buffer[bufSize - 1] = '\0';
184 
185     if (length)
186     {
187         *length = static_cast<GLsizei>(strlen(buffer));
188     }
189 }
190 
IncludeSameArrayElement(const std::set<std::string> & nameSet,const std::string & name)191 bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
192 {
193     std::vector<unsigned int> subscripts;
194     std::string baseName = ParseResourceName(name, &subscripts);
195     for (auto nameInSet : nameSet)
196     {
197         std::vector<unsigned int> arrayIndices;
198         std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
199         if (baseName == arrayName &&
200             (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
201         {
202             return true;
203         }
204     }
205     return false;
206 }
207 
validateInterfaceBlocksCount(GLuint maxInterfaceBlocks,const std::vector<sh::InterfaceBlock> & interfaceBlocks,const std::string & errorMessage,InfoLog & infoLog)208 bool validateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
209                                   const std::vector<sh::InterfaceBlock> &interfaceBlocks,
210                                   const std::string &errorMessage,
211                                   InfoLog &infoLog)
212 {
213     GLuint blockCount = 0;
214     for (const sh::InterfaceBlock &block : interfaceBlocks)
215     {
216         if (block.staticUse || block.layout != sh::BLOCKLAYOUT_PACKED)
217         {
218             blockCount += (block.arraySize ? block.arraySize : 1);
219             if (blockCount > maxInterfaceBlocks)
220             {
221                 infoLog << errorMessage << maxInterfaceBlocks << ")";
222                 return false;
223             }
224         }
225     }
226     return true;
227 }
228 
GetInterfaceBlockIndex(const std::vector<InterfaceBlock> & list,const std::string & name)229 GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
230 {
231     std::vector<unsigned int> subscripts;
232     std::string baseName = ParseResourceName(name, &subscripts);
233 
234     unsigned int numBlocks = static_cast<unsigned int>(list.size());
235     for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
236     {
237         const auto &block = list[blockIndex];
238         if (block.name == baseName)
239         {
240             const bool arrayElementZero =
241                 (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
242             const bool arrayElementMatches =
243                 (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
244             if (arrayElementMatches || arrayElementZero)
245             {
246                 return blockIndex;
247             }
248         }
249     }
250 
251     return GL_INVALID_INDEX;
252 }
253 
GetInterfaceBlockName(const GLuint index,const std::vector<InterfaceBlock> & list,GLsizei bufSize,GLsizei * length,GLchar * name)254 void GetInterfaceBlockName(const GLuint index,
255                            const std::vector<InterfaceBlock> &list,
256                            GLsizei bufSize,
257                            GLsizei *length,
258                            GLchar *name)
259 {
260     ASSERT(index < list.size());
261 
262     const auto &block = list[index];
263 
264     if (bufSize > 0)
265     {
266         std::string blockName = block.name;
267 
268         if (block.isArray)
269         {
270             blockName += ArrayString(block.arrayElement);
271         }
272         CopyStringToBuffer(name, blockName, bufSize, length);
273     }
274 }
275 
InitUniformBlockLinker(const gl::Context * context,const ProgramState & state,UniformBlockLinker * blockLinker)276 void InitUniformBlockLinker(const gl::Context *context,
277                             const ProgramState &state,
278                             UniformBlockLinker *blockLinker)
279 {
280     if (state.getAttachedVertexShader())
281     {
282         blockLinker->addShaderBlocks(GL_VERTEX_SHADER,
283                                      &state.getAttachedVertexShader()->getUniformBlocks(context));
284     }
285 
286     if (state.getAttachedFragmentShader())
287     {
288         blockLinker->addShaderBlocks(GL_FRAGMENT_SHADER,
289                                      &state.getAttachedFragmentShader()->getUniformBlocks(context));
290     }
291 
292     if (state.getAttachedComputeShader())
293     {
294         blockLinker->addShaderBlocks(GL_COMPUTE_SHADER,
295                                      &state.getAttachedComputeShader()->getUniformBlocks(context));
296     }
297 }
298 
InitShaderStorageBlockLinker(const gl::Context * context,const ProgramState & state,ShaderStorageBlockLinker * blockLinker)299 void InitShaderStorageBlockLinker(const gl::Context *context,
300                                   const ProgramState &state,
301                                   ShaderStorageBlockLinker *blockLinker)
302 {
303     if (state.getAttachedVertexShader())
304     {
305         blockLinker->addShaderBlocks(
306             GL_VERTEX_SHADER, &state.getAttachedVertexShader()->getShaderStorageBlocks(context));
307     }
308 
309     if (state.getAttachedFragmentShader())
310     {
311         blockLinker->addShaderBlocks(
312             GL_FRAGMENT_SHADER,
313             &state.getAttachedFragmentShader()->getShaderStorageBlocks(context));
314     }
315 
316     if (state.getAttachedComputeShader())
317     {
318         blockLinker->addShaderBlocks(
319             GL_COMPUTE_SHADER, &state.getAttachedComputeShader()->getShaderStorageBlocks(context));
320     }
321 }
322 
323 }  // anonymous namespace
324 
325 const char *const g_fakepath = "C:\\fakepath";
326 
InfoLog()327 InfoLog::InfoLog()
328 {
329 }
330 
~InfoLog()331 InfoLog::~InfoLog()
332 {
333 }
334 
getLength() const335 size_t InfoLog::getLength() const
336 {
337     if (!mLazyStream)
338     {
339         return 0;
340     }
341 
342     const std::string &logString = mLazyStream->str();
343     return logString.empty() ? 0 : logString.length() + 1;
344 }
345 
getLog(GLsizei bufSize,GLsizei * length,char * infoLog) const346 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
347 {
348     size_t index = 0;
349 
350     if (bufSize > 0)
351     {
352         const std::string logString(str());
353 
354         if (!logString.empty())
355         {
356             index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
357             memcpy(infoLog, logString.c_str(), index);
358         }
359 
360         infoLog[index] = '\0';
361     }
362 
363     if (length)
364     {
365         *length = static_cast<GLsizei>(index);
366     }
367 }
368 
369 // append a santized message to the program info log.
370 // The D3D compiler includes a fake file path in some of the warning or error
371 // messages, so lets remove all occurrences of this fake file path from the log.
appendSanitized(const char * message)372 void InfoLog::appendSanitized(const char *message)
373 {
374     ensureInitialized();
375 
376     std::string msg(message);
377 
378     size_t found;
379     do
380     {
381         found = msg.find(g_fakepath);
382         if (found != std::string::npos)
383         {
384             msg.erase(found, strlen(g_fakepath));
385         }
386     }
387     while (found != std::string::npos);
388 
389     *mLazyStream << message << std::endl;
390 }
391 
reset()392 void InfoLog::reset()
393 {
394 }
395 
VariableLocation()396 VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false)
397 {
398 }
399 
VariableLocation(unsigned int arrayIndex,unsigned int index)400 VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
401     : arrayIndex(arrayIndex), index(index), ignored(false)
402 {
403     ASSERT(arrayIndex != GL_INVALID_INDEX);
404 }
405 
SamplerBinding(GLenum textureTypeIn,size_t elementCount,bool unreferenced)406 SamplerBinding::SamplerBinding(GLenum textureTypeIn, size_t elementCount, bool unreferenced)
407     : textureType(textureTypeIn), boundTextureUnits(elementCount, 0), unreferenced(unreferenced)
408 {
409 }
410 
411 SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
412 
413 SamplerBinding::~SamplerBinding() = default;
414 
Bindings()415 Program::Bindings::Bindings()
416 {
417 }
418 
~Bindings()419 Program::Bindings::~Bindings()
420 {
421 }
422 
bindLocation(GLuint index,const std::string & name)423 void Program::Bindings::bindLocation(GLuint index, const std::string &name)
424 {
425     mBindings[name] = index;
426 }
427 
getBinding(const std::string & name) const428 int Program::Bindings::getBinding(const std::string &name) const
429 {
430     auto iter = mBindings.find(name);
431     return (iter != mBindings.end()) ? iter->second : -1;
432 }
433 
begin() const434 Program::Bindings::const_iterator Program::Bindings::begin() const
435 {
436     return mBindings.begin();
437 }
438 
end() const439 Program::Bindings::const_iterator Program::Bindings::end() const
440 {
441     return mBindings.end();
442 }
443 
ImageBinding(size_t count)444 ImageBinding::ImageBinding(size_t count) : boundImageUnits(count, 0)
445 {
446 }
ImageBinding(GLuint imageUnit,size_t count)447 ImageBinding::ImageBinding(GLuint imageUnit, size_t count)
448 {
449     for (size_t index = 0; index < count; ++index)
450     {
451         boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
452     }
453 }
454 
455 ImageBinding::ImageBinding(const ImageBinding &other) = default;
456 
457 ImageBinding::~ImageBinding() = default;
458 
ProgramState()459 ProgramState::ProgramState()
460     : mLabel(),
461       mAttachedFragmentShader(nullptr),
462       mAttachedVertexShader(nullptr),
463       mAttachedComputeShader(nullptr),
464       mAttachedGeometryShader(nullptr),
465       mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
466       mMaxActiveAttribLocation(0),
467       mSamplerUniformRange(0, 0),
468       mImageUniformRange(0, 0),
469       mAtomicCounterUniformRange(0, 0),
470       mBinaryRetrieveableHint(false),
471       mNumViews(-1)
472 {
473     mComputeShaderLocalSize.fill(1);
474 }
475 
~ProgramState()476 ProgramState::~ProgramState()
477 {
478     ASSERT(!mAttachedVertexShader && !mAttachedFragmentShader && !mAttachedComputeShader &&
479            !mAttachedGeometryShader);
480 }
481 
getLabel()482 const std::string &ProgramState::getLabel()
483 {
484     return mLabel;
485 }
486 
getUniformIndexFromName(const std::string & name) const487 GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
488 {
489     return GetResourceIndexFromName(mUniforms, name);
490 }
491 
getBufferVariableIndexFromName(const std::string & name) const492 GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
493 {
494     return GetResourceIndexFromName(mBufferVariables, name);
495 }
496 
getUniformIndexFromLocation(GLint location) const497 GLuint ProgramState::getUniformIndexFromLocation(GLint location) const
498 {
499     ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformLocations.size());
500     return mUniformLocations[location].index;
501 }
502 
getSamplerIndex(GLint location) const503 Optional<GLuint> ProgramState::getSamplerIndex(GLint location) const
504 {
505     GLuint index = getUniformIndexFromLocation(location);
506     if (!isSamplerUniformIndex(index))
507     {
508         return Optional<GLuint>::Invalid();
509     }
510 
511     return getSamplerIndexFromUniformIndex(index);
512 }
513 
isSamplerUniformIndex(GLuint index) const514 bool ProgramState::isSamplerUniformIndex(GLuint index) const
515 {
516     return mSamplerUniformRange.contains(index);
517 }
518 
getSamplerIndexFromUniformIndex(GLuint uniformIndex) const519 GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
520 {
521     ASSERT(isSamplerUniformIndex(uniformIndex));
522     return uniformIndex - mSamplerUniformRange.low();
523 }
524 
getAttributeLocation(const std::string & name) const525 GLuint ProgramState::getAttributeLocation(const std::string &name) const
526 {
527     for (const sh::Attribute &attribute : mAttributes)
528     {
529         if (attribute.name == name)
530         {
531             return attribute.location;
532         }
533     }
534 
535     return static_cast<GLuint>(-1);
536 }
537 
Program(rx::GLImplFactory * factory,ShaderProgramManager * manager,GLuint handle)538 Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, GLuint handle)
539     : mProgram(factory->createProgram(mState)),
540       mValidated(false),
541       mLinked(false),
542       mDeleteStatus(false),
543       mRefCount(0),
544       mResourceManager(manager),
545       mHandle(handle)
546 {
547     ASSERT(mProgram);
548 
549     unlink();
550 }
551 
~Program()552 Program::~Program()
553 {
554     ASSERT(!mProgram);
555 }
556 
onDestroy(const Context * context)557 void Program::onDestroy(const Context *context)
558 {
559     if (mState.mAttachedVertexShader != nullptr)
560     {
561         mState.mAttachedVertexShader->release(context);
562         mState.mAttachedVertexShader = nullptr;
563     }
564 
565     if (mState.mAttachedFragmentShader != nullptr)
566     {
567         mState.mAttachedFragmentShader->release(context);
568         mState.mAttachedFragmentShader = nullptr;
569     }
570 
571     if (mState.mAttachedComputeShader != nullptr)
572     {
573         mState.mAttachedComputeShader->release(context);
574         mState.mAttachedComputeShader = nullptr;
575     }
576 
577     if (mState.mAttachedGeometryShader != nullptr)
578     {
579         mState.mAttachedGeometryShader->release(context);
580         mState.mAttachedGeometryShader = nullptr;
581     }
582 
583     mProgram->destroy(context);
584 
585     ASSERT(!mState.mAttachedVertexShader && !mState.mAttachedFragmentShader &&
586            !mState.mAttachedComputeShader && !mState.mAttachedGeometryShader);
587     SafeDelete(mProgram);
588 
589     delete this;
590 }
591 
setLabel(const std::string & label)592 void Program::setLabel(const std::string &label)
593 {
594     mState.mLabel = label;
595 }
596 
getLabel() const597 const std::string &Program::getLabel() const
598 {
599     return mState.mLabel;
600 }
601 
attachShader(Shader * shader)602 void Program::attachShader(Shader *shader)
603 {
604     switch (shader->getType())
605     {
606         case GL_VERTEX_SHADER:
607         {
608             ASSERT(!mState.mAttachedVertexShader);
609             mState.mAttachedVertexShader = shader;
610             mState.mAttachedVertexShader->addRef();
611             break;
612         }
613         case GL_FRAGMENT_SHADER:
614         {
615             ASSERT(!mState.mAttachedFragmentShader);
616             mState.mAttachedFragmentShader = shader;
617             mState.mAttachedFragmentShader->addRef();
618             break;
619         }
620         case GL_COMPUTE_SHADER:
621         {
622             ASSERT(!mState.mAttachedComputeShader);
623             mState.mAttachedComputeShader = shader;
624             mState.mAttachedComputeShader->addRef();
625             break;
626         }
627         case GL_GEOMETRY_SHADER_EXT:
628         {
629             ASSERT(!mState.mAttachedGeometryShader);
630             mState.mAttachedGeometryShader = shader;
631             mState.mAttachedGeometryShader->addRef();
632             break;
633         }
634         default:
635             UNREACHABLE();
636     }
637 }
638 
detachShader(const Context * context,Shader * shader)639 void Program::detachShader(const Context *context, Shader *shader)
640 {
641     switch (shader->getType())
642     {
643         case GL_VERTEX_SHADER:
644         {
645             ASSERT(mState.mAttachedVertexShader == shader);
646             shader->release(context);
647             mState.mAttachedVertexShader = nullptr;
648             break;
649         }
650         case GL_FRAGMENT_SHADER:
651         {
652             ASSERT(mState.mAttachedFragmentShader == shader);
653             shader->release(context);
654             mState.mAttachedFragmentShader = nullptr;
655             break;
656         }
657         case GL_COMPUTE_SHADER:
658         {
659             ASSERT(mState.mAttachedComputeShader == shader);
660             shader->release(context);
661             mState.mAttachedComputeShader = nullptr;
662             break;
663         }
664         case GL_GEOMETRY_SHADER_EXT:
665         {
666             ASSERT(mState.mAttachedGeometryShader == shader);
667             shader->release(context);
668             mState.mAttachedGeometryShader = nullptr;
669             break;
670         }
671         default:
672             UNREACHABLE();
673     }
674 }
675 
getAttachedShadersCount() const676 int Program::getAttachedShadersCount() const
677 {
678     return (mState.mAttachedVertexShader ? 1 : 0) + (mState.mAttachedFragmentShader ? 1 : 0) +
679            (mState.mAttachedComputeShader ? 1 : 0) + (mState.mAttachedGeometryShader ? 1 : 0);
680 }
681 
bindAttributeLocation(GLuint index,const char * name)682 void Program::bindAttributeLocation(GLuint index, const char *name)
683 {
684     mAttributeBindings.bindLocation(index, name);
685 }
686 
bindUniformLocation(GLuint index,const char * name)687 void Program::bindUniformLocation(GLuint index, const char *name)
688 {
689     mUniformLocationBindings.bindLocation(index, name);
690 }
691 
bindFragmentInputLocation(GLint index,const char * name)692 void Program::bindFragmentInputLocation(GLint index, const char *name)
693 {
694     mFragmentInputBindings.bindLocation(index, name);
695 }
696 
getFragmentInputBindingInfo(const Context * context,GLint index) const697 BindingInfo Program::getFragmentInputBindingInfo(const Context *context, GLint index) const
698 {
699     BindingInfo ret;
700     ret.type  = GL_NONE;
701     ret.valid = false;
702 
703     Shader *fragmentShader = mState.getAttachedFragmentShader();
704     ASSERT(fragmentShader);
705 
706     // Find the actual fragment shader varying we're interested in
707     const std::vector<sh::Varying> &inputs = fragmentShader->getInputVaryings(context);
708 
709     for (const auto &binding : mFragmentInputBindings)
710     {
711         if (binding.second != static_cast<GLuint>(index))
712             continue;
713 
714         ret.valid = true;
715 
716         size_t nameLengthWithoutArrayIndex;
717         unsigned int arrayIndex = ParseArrayIndex(binding.first, &nameLengthWithoutArrayIndex);
718 
719         for (const auto &in : inputs)
720         {
721             if (in.name.length() == nameLengthWithoutArrayIndex &&
722                 angle::BeginsWith(in.name, binding.first, nameLengthWithoutArrayIndex))
723             {
724                 if (in.isArray())
725                 {
726                     // The client wants to bind either "name" or "name[0]".
727                     // GL ES 3.1 spec refers to active array names with language such as:
728                     // "if the string identifies the base name of an active array, where the
729                     // string would exactly match the name of the variable if the suffix "[0]"
730                     // were appended to the string".
731                     if (arrayIndex == GL_INVALID_INDEX)
732                         arrayIndex = 0;
733 
734                     ret.name = in.mappedName + "[" + ToString(arrayIndex) + "]";
735                 }
736                 else
737                 {
738                     ret.name = in.mappedName;
739                 }
740                 ret.type = in.type;
741                 return ret;
742             }
743         }
744     }
745 
746     return ret;
747 }
748 
pathFragmentInputGen(const Context * context,GLint index,GLenum genMode,GLint components,const GLfloat * coeffs)749 void Program::pathFragmentInputGen(const Context *context,
750                                    GLint index,
751                                    GLenum genMode,
752                                    GLint components,
753                                    const GLfloat *coeffs)
754 {
755     // If the location is -1 then the command is silently ignored
756     if (index == -1)
757         return;
758 
759     const auto &binding = getFragmentInputBindingInfo(context, index);
760 
761     // If the input doesn't exist then then the command is silently ignored
762     // This could happen through optimization for example, the shader translator
763     // decides that a variable is not actually being used and optimizes it away.
764     if (binding.name.empty())
765         return;
766 
767     mProgram->setPathFragmentInputGen(binding.name, genMode, components, coeffs);
768 }
769 
770 // The attached shaders are checked for linking errors by matching up their variables.
771 // Uniform, input and output variables get collected.
772 // The code gets compiled into binaries.
link(const gl::Context * context)773 Error Program::link(const gl::Context *context)
774 {
775     const auto &data = context->getContextState();
776 
777     auto *platform   = ANGLEPlatformCurrent();
778     double startTime = platform->currentTime(platform);
779 
780     unlink();
781 
782     ProgramHash programHash;
783     auto *cache = context->getMemoryProgramCache();
784     if (cache)
785     {
786         ANGLE_TRY_RESULT(cache->getProgram(context, this, &mState, &programHash), mLinked);
787         ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.ProgramCache.LoadBinarySuccess", mLinked);
788     }
789 
790     if (mLinked)
791     {
792         double delta = platform->currentTime(platform) - startTime;
793         int us       = static_cast<int>(delta * 1000000.0);
794         ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
795         return NoError();
796     }
797 
798     // Cache load failed, fall through to normal linking.
799     unlink();
800     mInfoLog.reset();
801 
802     const Caps &caps = data.getCaps();
803 
804     Shader *vertexShader   = mState.mAttachedVertexShader;
805     Shader *fragmentShader = mState.mAttachedFragmentShader;
806     Shader *computeShader  = mState.mAttachedComputeShader;
807 
808     bool isComputeShaderAttached   = (computeShader != nullptr);
809     bool nonComputeShadersAttached = (vertexShader != nullptr || fragmentShader != nullptr);
810     // Check whether we both have a compute and non-compute shaders attached.
811     // If there are of both types attached, then linking should fail.
812     // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
813     if (isComputeShaderAttached == true && nonComputeShadersAttached == true)
814     {
815         mInfoLog << "Both a compute and non-compute shaders are attached to the same program.";
816         return NoError();
817     }
818 
819     if (computeShader)
820     {
821         if (!computeShader->isCompiled(context))
822         {
823             mInfoLog << "Attached compute shader is not compiled.";
824             return NoError();
825         }
826         ASSERT(computeShader->getType() == GL_COMPUTE_SHADER);
827 
828         mState.mComputeShaderLocalSize = computeShader->getWorkGroupSize(context);
829 
830         // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
831         // If the work group size is not specified, a link time error should occur.
832         if (!mState.mComputeShaderLocalSize.isDeclared())
833         {
834             mInfoLog << "Work group size is not specified.";
835             return NoError();
836         }
837 
838         if (!linkUniforms(context, mInfoLog, mUniformLocationBindings))
839         {
840             return NoError();
841         }
842 
843         if (!linkInterfaceBlocks(context, mInfoLog))
844         {
845             return NoError();
846         }
847 
848         ProgramLinkedResources resources = {
849             {0, PackMode::ANGLE_RELAXED},
850             {&mState.mUniformBlocks, &mState.mUniforms},
851             {&mState.mShaderStorageBlocks, &mState.mBufferVariables}};
852 
853         InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker);
854         InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker);
855 
856         ANGLE_TRY_RESULT(mProgram->link(context, resources, mInfoLog), mLinked);
857         if (!mLinked)
858         {
859             return NoError();
860         }
861     }
862     else
863     {
864         if (!fragmentShader || !fragmentShader->isCompiled(context))
865         {
866             return NoError();
867         }
868         ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
869 
870         if (!vertexShader || !vertexShader->isCompiled(context))
871         {
872             return NoError();
873         }
874         ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
875 
876         if (fragmentShader->getShaderVersion(context) != vertexShader->getShaderVersion(context))
877         {
878             mInfoLog << "Fragment shader version does not match vertex shader version.";
879             return NoError();
880         }
881 
882         if (!linkAttributes(context, mInfoLog))
883         {
884             return NoError();
885         }
886 
887         if (!linkVaryings(context, mInfoLog))
888         {
889             return NoError();
890         }
891 
892         if (!linkUniforms(context, mInfoLog, mUniformLocationBindings))
893         {
894             return NoError();
895         }
896 
897         if (!linkInterfaceBlocks(context, mInfoLog))
898         {
899             return NoError();
900         }
901 
902         if (!linkValidateGlobalNames(context, mInfoLog))
903         {
904             return NoError();
905         }
906 
907         const auto &mergedVaryings = getMergedVaryings(context);
908 
909         mState.mNumViews = vertexShader->getNumViews(context);
910 
911         linkOutputVariables(context);
912 
913         // Map the varyings to the register file
914         // In WebGL, we use a slightly different handling for packing variables.
915         auto packMode = data.getExtensions().webglCompatibility ? PackMode::WEBGL_STRICT
916                                                                 : PackMode::ANGLE_RELAXED;
917 
918         ProgramLinkedResources resources = {
919             {data.getCaps().maxVaryingVectors, packMode},
920             {&mState.mUniformBlocks, &mState.mUniforms},
921             {&mState.mShaderStorageBlocks, &mState.mBufferVariables}};
922 
923         InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker);
924         InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker);
925 
926         if (!linkValidateTransformFeedback(context, mInfoLog, mergedVaryings, caps))
927         {
928             return NoError();
929         }
930 
931         if (!resources.varyingPacking.collectAndPackUserVaryings(
932                 mInfoLog, mergedVaryings, mState.getTransformFeedbackVaryingNames()))
933         {
934             return NoError();
935         }
936 
937         ANGLE_TRY_RESULT(mProgram->link(context, resources, mInfoLog), mLinked);
938         if (!mLinked)
939         {
940             return NoError();
941         }
942 
943         gatherTransformFeedbackVaryings(mergedVaryings);
944     }
945 
946     gatherAtomicCounterBuffers();
947     initInterfaceBlockBindings();
948 
949     setUniformValuesFromBindingQualifiers();
950 
951     ASSERT(mLinked);
952     updateLinkedShaderStages();
953 
954     // Mark implementation-specific unreferenced uniforms as ignored.
955     mProgram->markUnusedUniformLocations(&mState.mUniformLocations, &mState.mSamplerBindings);
956 
957     // Save to the program cache.
958     if (cache && (mState.mLinkedTransformFeedbackVaryings.empty() ||
959                   !context->getWorkarounds().disableProgramCachingForTransformFeedback))
960     {
961         cache->putProgram(programHash, context, this);
962     }
963 
964     double delta = platform->currentTime(platform) - startTime;
965     int us       = static_cast<int>(delta * 1000000.0);
966     ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheMissTimeUS", us);
967 
968     return NoError();
969 }
970 
updateLinkedShaderStages()971 void Program::updateLinkedShaderStages()
972 {
973     if (mState.mAttachedVertexShader)
974     {
975         mState.mLinkedShaderStages.set(SHADER_VERTEX);
976     }
977 
978     if (mState.mAttachedFragmentShader)
979     {
980         mState.mLinkedShaderStages.set(SHADER_FRAGMENT);
981     }
982 
983     if (mState.mAttachedComputeShader)
984     {
985         mState.mLinkedShaderStages.set(SHADER_COMPUTE);
986     }
987 }
988 
989 // Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()990 void Program::unlink()
991 {
992     mState.mAttributes.clear();
993     mState.mActiveAttribLocationsMask.reset();
994     mState.mMaxActiveAttribLocation = 0;
995     mState.mLinkedTransformFeedbackVaryings.clear();
996     mState.mUniforms.clear();
997     mState.mUniformLocations.clear();
998     mState.mUniformBlocks.clear();
999     mState.mActiveUniformBlockBindings.reset();
1000     mState.mAtomicCounterBuffers.clear();
1001     mState.mOutputVariables.clear();
1002     mState.mOutputLocations.clear();
1003     mState.mOutputVariableTypes.clear();
1004     mState.mActiveOutputVariables.reset();
1005     mState.mComputeShaderLocalSize.fill(1);
1006     mState.mSamplerBindings.clear();
1007     mState.mImageBindings.clear();
1008     mState.mNumViews = -1;
1009     mState.mLinkedShaderStages.reset();
1010 
1011     mValidated = false;
1012 
1013     mLinked = false;
1014 }
1015 
isLinked() const1016 bool Program::isLinked() const
1017 {
1018     return mLinked;
1019 }
1020 
loadBinary(const Context * context,GLenum binaryFormat,const void * binary,GLsizei length)1021 Error Program::loadBinary(const Context *context,
1022                           GLenum binaryFormat,
1023                           const void *binary,
1024                           GLsizei length)
1025 {
1026     unlink();
1027 
1028 #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
1029     return NoError();
1030 #else
1031     ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
1032     if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
1033     {
1034         mInfoLog << "Invalid program binary format.";
1035         return NoError();
1036     }
1037 
1038     const uint8_t *bytes = reinterpret_cast<const uint8_t *>(binary);
1039     ANGLE_TRY_RESULT(
1040         MemoryProgramCache::Deserialize(context, this, &mState, bytes, length, mInfoLog), mLinked);
1041 
1042     // Currently we require the full shader text to compute the program hash.
1043     // TODO(jmadill): Store the binary in the internal program cache.
1044 
1045     return NoError();
1046 #endif  // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
1047 }
1048 
saveBinary(const Context * context,GLenum * binaryFormat,void * binary,GLsizei bufSize,GLsizei * length) const1049 Error Program::saveBinary(const Context *context,
1050                           GLenum *binaryFormat,
1051                           void *binary,
1052                           GLsizei bufSize,
1053                           GLsizei *length) const
1054 {
1055     if (binaryFormat)
1056     {
1057         *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
1058     }
1059 
1060     angle::MemoryBuffer memoryBuf;
1061     MemoryProgramCache::Serialize(context, this, &memoryBuf);
1062 
1063     GLsizei streamLength       = static_cast<GLsizei>(memoryBuf.size());
1064     const uint8_t *streamState = memoryBuf.data();
1065 
1066     if (streamLength > bufSize)
1067     {
1068         if (length)
1069         {
1070             *length = 0;
1071         }
1072 
1073         // TODO: This should be moved to the validation layer but computing the size of the binary before saving
1074         // it causes the save to happen twice.  It may be possible to write the binary to a separate buffer, validate
1075         // sizes and then copy it.
1076         return InternalError();
1077     }
1078 
1079     if (binary)
1080     {
1081         char *ptr = reinterpret_cast<char*>(binary);
1082 
1083         memcpy(ptr, streamState, streamLength);
1084         ptr += streamLength;
1085 
1086         ASSERT(ptr - streamLength == binary);
1087     }
1088 
1089     if (length)
1090     {
1091         *length = streamLength;
1092     }
1093 
1094     return NoError();
1095 }
1096 
getBinaryLength(const Context * context) const1097 GLint Program::getBinaryLength(const Context *context) const
1098 {
1099     GLint length;
1100     Error error = saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
1101     if (error.isError())
1102     {
1103         return 0;
1104     }
1105 
1106     return length;
1107 }
1108 
setBinaryRetrievableHint(bool retrievable)1109 void Program::setBinaryRetrievableHint(bool retrievable)
1110 {
1111     // TODO(jmadill) : replace with dirty bits
1112     mProgram->setBinaryRetrievableHint(retrievable);
1113     mState.mBinaryRetrieveableHint = retrievable;
1114 }
1115 
getBinaryRetrievableHint() const1116 bool Program::getBinaryRetrievableHint() const
1117 {
1118     return mState.mBinaryRetrieveableHint;
1119 }
1120 
setSeparable(bool separable)1121 void Program::setSeparable(bool separable)
1122 {
1123     // TODO(yunchao) : replace with dirty bits
1124     if (mState.mSeparable != separable)
1125     {
1126         mProgram->setSeparable(separable);
1127         mState.mSeparable = separable;
1128     }
1129 }
1130 
isSeparable() const1131 bool Program::isSeparable() const
1132 {
1133     return mState.mSeparable;
1134 }
1135 
release(const Context * context)1136 void Program::release(const Context *context)
1137 {
1138     mRefCount--;
1139 
1140     if (mRefCount == 0 && mDeleteStatus)
1141     {
1142         mResourceManager->deleteProgram(context, mHandle);
1143     }
1144 }
1145 
addRef()1146 void Program::addRef()
1147 {
1148     mRefCount++;
1149 }
1150 
getRefCount() const1151 unsigned int Program::getRefCount() const
1152 {
1153     return mRefCount;
1154 }
1155 
getInfoLogLength() const1156 int Program::getInfoLogLength() const
1157 {
1158     return static_cast<int>(mInfoLog.getLength());
1159 }
1160 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog) const1161 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
1162 {
1163     return mInfoLog.getLog(bufSize, length, infoLog);
1164 }
1165 
getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders) const1166 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const
1167 {
1168     int total = 0;
1169 
1170     if (mState.mAttachedComputeShader)
1171     {
1172         if (total < maxCount)
1173         {
1174             shaders[total] = mState.mAttachedComputeShader->getHandle();
1175             total++;
1176         }
1177     }
1178 
1179     if (mState.mAttachedVertexShader)
1180     {
1181         if (total < maxCount)
1182         {
1183             shaders[total] = mState.mAttachedVertexShader->getHandle();
1184             total++;
1185         }
1186     }
1187 
1188     if (mState.mAttachedFragmentShader)
1189     {
1190         if (total < maxCount)
1191         {
1192             shaders[total] = mState.mAttachedFragmentShader->getHandle();
1193             total++;
1194         }
1195     }
1196 
1197     if (mState.mAttachedGeometryShader)
1198     {
1199         if (total < maxCount)
1200         {
1201             shaders[total] = mState.mAttachedGeometryShader->getHandle();
1202             total++;
1203         }
1204     }
1205 
1206     if (count)
1207     {
1208         *count = total;
1209     }
1210 }
1211 
getAttributeLocation(const std::string & name) const1212 GLuint Program::getAttributeLocation(const std::string &name) const
1213 {
1214     return mState.getAttributeLocation(name);
1215 }
1216 
isAttribLocationActive(size_t attribLocation) const1217 bool Program::isAttribLocationActive(size_t attribLocation) const
1218 {
1219     ASSERT(attribLocation < mState.mActiveAttribLocationsMask.size());
1220     return mState.mActiveAttribLocationsMask[attribLocation];
1221 }
1222 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const1223 void Program::getActiveAttribute(GLuint index,
1224                                  GLsizei bufsize,
1225                                  GLsizei *length,
1226                                  GLint *size,
1227                                  GLenum *type,
1228                                  GLchar *name) const
1229 {
1230     if (!mLinked)
1231     {
1232         if (bufsize > 0)
1233         {
1234             name[0] = '\0';
1235         }
1236 
1237         if (length)
1238         {
1239             *length = 0;
1240         }
1241 
1242         *type = GL_NONE;
1243         *size = 1;
1244         return;
1245     }
1246 
1247     ASSERT(index < mState.mAttributes.size());
1248     const sh::Attribute &attrib = mState.mAttributes[index];
1249 
1250     if (bufsize > 0)
1251     {
1252         CopyStringToBuffer(name, attrib.name, bufsize, length);
1253     }
1254 
1255     // Always a single 'type' instance
1256     *size = 1;
1257     *type = attrib.type;
1258 }
1259 
getActiveAttributeCount() const1260 GLint Program::getActiveAttributeCount() const
1261 {
1262     if (!mLinked)
1263     {
1264         return 0;
1265     }
1266 
1267     return static_cast<GLint>(mState.mAttributes.size());
1268 }
1269 
getActiveAttributeMaxLength() const1270 GLint Program::getActiveAttributeMaxLength() const
1271 {
1272     if (!mLinked)
1273     {
1274         return 0;
1275     }
1276 
1277     size_t maxLength = 0;
1278 
1279     for (const sh::Attribute &attrib : mState.mAttributes)
1280     {
1281         maxLength = std::max(attrib.name.length() + 1, maxLength);
1282     }
1283 
1284     return static_cast<GLint>(maxLength);
1285 }
1286 
getInputResourceIndex(const GLchar * name) const1287 GLuint Program::getInputResourceIndex(const GLchar *name) const
1288 {
1289     return GetResourceIndexFromName(mState.mAttributes, std::string(name));
1290 }
1291 
getOutputResourceIndex(const GLchar * name) const1292 GLuint Program::getOutputResourceIndex(const GLchar *name) const
1293 {
1294     return GetResourceIndexFromName(mState.mOutputVariables, std::string(name));
1295 }
1296 
getOutputResourceCount() const1297 size_t Program::getOutputResourceCount() const
1298 {
1299     return (mLinked ? mState.mOutputVariables.size() : 0);
1300 }
1301 
1302 template <typename T>
getResourceName(GLuint index,const std::vector<T> & resources,GLsizei bufSize,GLsizei * length,GLchar * name) const1303 void Program::getResourceName(GLuint index,
1304                               const std::vector<T> &resources,
1305                               GLsizei bufSize,
1306                               GLsizei *length,
1307                               GLchar *name) const
1308 {
1309     if (length)
1310     {
1311         *length = 0;
1312     }
1313 
1314     if (!mLinked)
1315     {
1316         if (bufSize > 0)
1317         {
1318             name[0] = '\0';
1319         }
1320         return;
1321     }
1322     ASSERT(index < resources.size());
1323     const auto &resource = resources[index];
1324 
1325     if (bufSize > 0)
1326     {
1327         CopyStringToBuffer(name, resource.name, bufSize, length);
1328     }
1329 }
1330 
getInputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const1331 void Program::getInputResourceName(GLuint index,
1332                                    GLsizei bufSize,
1333                                    GLsizei *length,
1334                                    GLchar *name) const
1335 {
1336     getResourceName(index, mState.mAttributes, bufSize, length, name);
1337 }
1338 
getOutputResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const1339 void Program::getOutputResourceName(GLuint index,
1340                                     GLsizei bufSize,
1341                                     GLsizei *length,
1342                                     GLchar *name) const
1343 {
1344     getResourceName(index, mState.mOutputVariables, bufSize, length, name);
1345 }
1346 
getUniformResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const1347 void Program::getUniformResourceName(GLuint index,
1348                                      GLsizei bufSize,
1349                                      GLsizei *length,
1350                                      GLchar *name) const
1351 {
1352     getResourceName(index, mState.mUniforms, bufSize, length, name);
1353 }
1354 
getBufferVariableResourceName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const1355 void Program::getBufferVariableResourceName(GLuint index,
1356                                             GLsizei bufSize,
1357                                             GLsizei *length,
1358                                             GLchar *name) const
1359 {
1360     getResourceName(index, mState.mBufferVariables, bufSize, length, name);
1361 }
1362 
getInputResource(GLuint index) const1363 const sh::Attribute &Program::getInputResource(GLuint index) const
1364 {
1365     ASSERT(index < mState.mAttributes.size());
1366     return mState.mAttributes[index];
1367 }
1368 
getOutputResource(GLuint index) const1369 const sh::OutputVariable &Program::getOutputResource(GLuint index) const
1370 {
1371     ASSERT(index < mState.mOutputVariables.size());
1372     return mState.mOutputVariables[index];
1373 }
1374 
getFragDataLocation(const std::string & name) const1375 GLint Program::getFragDataLocation(const std::string &name) const
1376 {
1377     return GetVariableLocation(mState.mOutputVariables, mState.mOutputLocations, name);
1378 }
1379 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const1380 void Program::getActiveUniform(GLuint index,
1381                                GLsizei bufsize,
1382                                GLsizei *length,
1383                                GLint *size,
1384                                GLenum *type,
1385                                GLchar *name) const
1386 {
1387     if (mLinked)
1388     {
1389         // index must be smaller than getActiveUniformCount()
1390         ASSERT(index < mState.mUniforms.size());
1391         const LinkedUniform &uniform = mState.mUniforms[index];
1392 
1393         if (bufsize > 0)
1394         {
1395             std::string string = uniform.name;
1396             CopyStringToBuffer(name, string, bufsize, length);
1397         }
1398 
1399         *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
1400         *type = uniform.type;
1401     }
1402     else
1403     {
1404         if (bufsize > 0)
1405         {
1406             name[0] = '\0';
1407         }
1408 
1409         if (length)
1410         {
1411             *length = 0;
1412         }
1413 
1414         *size = 0;
1415         *type = GL_NONE;
1416     }
1417 }
1418 
getActiveUniformCount() const1419 GLint Program::getActiveUniformCount() const
1420 {
1421     if (mLinked)
1422     {
1423         return static_cast<GLint>(mState.mUniforms.size());
1424     }
1425     else
1426     {
1427         return 0;
1428     }
1429 }
1430 
getActiveBufferVariableCount() const1431 size_t Program::getActiveBufferVariableCount() const
1432 {
1433     return mLinked ? mState.mBufferVariables.size() : 0;
1434 }
1435 
getActiveUniformMaxLength() const1436 GLint Program::getActiveUniformMaxLength() const
1437 {
1438     size_t maxLength = 0;
1439 
1440     if (mLinked)
1441     {
1442         for (const LinkedUniform &uniform : mState.mUniforms)
1443         {
1444             if (!uniform.name.empty())
1445             {
1446                 size_t length = uniform.name.length() + 1u;
1447                 if (uniform.isArray())
1448                 {
1449                     length += 3;  // Counting in "[0]".
1450                 }
1451                 maxLength = std::max(length, maxLength);
1452             }
1453         }
1454     }
1455 
1456     return static_cast<GLint>(maxLength);
1457 }
1458 
isValidUniformLocation(GLint location) const1459 bool Program::isValidUniformLocation(GLint location) const
1460 {
1461     ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
1462     return (location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size() &&
1463             mState.mUniformLocations[static_cast<size_t>(location)].used());
1464 }
1465 
getUniformByLocation(GLint location) const1466 const LinkedUniform &Program::getUniformByLocation(GLint location) const
1467 {
1468     ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
1469     return mState.mUniforms[mState.getUniformIndexFromLocation(location)];
1470 }
1471 
getUniformLocation(GLint location) const1472 const VariableLocation &Program::getUniformLocation(GLint location) const
1473 {
1474     ASSERT(location >= 0 && static_cast<size_t>(location) < mState.mUniformLocations.size());
1475     return mState.mUniformLocations[location];
1476 }
1477 
getUniformLocations() const1478 const std::vector<VariableLocation> &Program::getUniformLocations() const
1479 {
1480     return mState.mUniformLocations;
1481 }
1482 
getUniformByIndex(GLuint index) const1483 const LinkedUniform &Program::getUniformByIndex(GLuint index) const
1484 {
1485     ASSERT(index < static_cast<size_t>(mState.mUniforms.size()));
1486     return mState.mUniforms[index];
1487 }
1488 
getBufferVariableByIndex(GLuint index) const1489 const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
1490 {
1491     ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
1492     return mState.mBufferVariables[index];
1493 }
1494 
getUniformLocation(const std::string & name) const1495 GLint Program::getUniformLocation(const std::string &name) const
1496 {
1497     return GetVariableLocation(mState.mUniforms, mState.mUniformLocations, name);
1498 }
1499 
getUniformIndex(const std::string & name) const1500 GLuint Program::getUniformIndex(const std::string &name) const
1501 {
1502     return mState.getUniformIndexFromName(name);
1503 }
1504 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)1505 void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
1506 {
1507     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1508     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
1509     mProgram->setUniform1fv(location, clampedCount, v);
1510 }
1511 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)1512 void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1513 {
1514     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1515     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
1516     mProgram->setUniform2fv(location, clampedCount, v);
1517 }
1518 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)1519 void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1520 {
1521     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1522     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
1523     mProgram->setUniform3fv(location, clampedCount, v);
1524 }
1525 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)1526 void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1527 {
1528     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1529     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
1530     mProgram->setUniform4fv(location, clampedCount, v);
1531 }
1532 
setUniform1iv(GLint location,GLsizei count,const GLint * v)1533 Program::SetUniformResult Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
1534 {
1535     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1536     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
1537 
1538     mProgram->setUniform1iv(location, clampedCount, v);
1539 
1540     if (mState.isSamplerUniformIndex(locationInfo.index))
1541     {
1542         updateSamplerUniform(locationInfo, clampedCount, v);
1543         return SetUniformResult::SamplerChanged;
1544     }
1545 
1546     return SetUniformResult::NoSamplerChange;
1547 }
1548 
setUniform2iv(GLint location,GLsizei count,const GLint * v)1549 void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
1550 {
1551     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1552     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
1553     mProgram->setUniform2iv(location, clampedCount, v);
1554 }
1555 
setUniform3iv(GLint location,GLsizei count,const GLint * v)1556 void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
1557 {
1558     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1559     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
1560     mProgram->setUniform3iv(location, clampedCount, v);
1561 }
1562 
setUniform4iv(GLint location,GLsizei count,const GLint * v)1563 void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
1564 {
1565     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1566     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
1567     mProgram->setUniform4iv(location, clampedCount, v);
1568 }
1569 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)1570 void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
1571 {
1572     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1573     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 1, v);
1574     mProgram->setUniform1uiv(location, clampedCount, v);
1575 }
1576 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)1577 void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
1578 {
1579     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1580     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 2, v);
1581     mProgram->setUniform2uiv(location, clampedCount, v);
1582 }
1583 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)1584 void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
1585 {
1586     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1587     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 3, v);
1588     mProgram->setUniform3uiv(location, clampedCount, v);
1589 }
1590 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)1591 void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
1592 {
1593     const VariableLocation &locationInfo = mState.mUniformLocations[location];
1594     GLsizei clampedCount                 = clampUniformCount(locationInfo, count, 4, v);
1595     mProgram->setUniform4uiv(location, clampedCount, v);
1596 }
1597 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1598 void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1599 {
1600     GLsizei clampedCount = clampMatrixUniformCount<2, 2>(location, count, transpose, v);
1601     mProgram->setUniformMatrix2fv(location, clampedCount, transpose, v);
1602 }
1603 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1604 void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1605 {
1606     GLsizei clampedCount = clampMatrixUniformCount<3, 3>(location, count, transpose, v);
1607     mProgram->setUniformMatrix3fv(location, clampedCount, transpose, v);
1608 }
1609 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1610 void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1611 {
1612     GLsizei clampedCount = clampMatrixUniformCount<4, 4>(location, count, transpose, v);
1613     mProgram->setUniformMatrix4fv(location, clampedCount, transpose, v);
1614 }
1615 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1616 void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1617 {
1618     GLsizei clampedCount = clampMatrixUniformCount<2, 3>(location, count, transpose, v);
1619     mProgram->setUniformMatrix2x3fv(location, clampedCount, transpose, v);
1620 }
1621 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1622 void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1623 {
1624     GLsizei clampedCount = clampMatrixUniformCount<2, 4>(location, count, transpose, v);
1625     mProgram->setUniformMatrix2x4fv(location, clampedCount, transpose, v);
1626 }
1627 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1628 void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1629 {
1630     GLsizei clampedCount = clampMatrixUniformCount<3, 2>(location, count, transpose, v);
1631     mProgram->setUniformMatrix3x2fv(location, clampedCount, transpose, v);
1632 }
1633 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1634 void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1635 {
1636     GLsizei clampedCount = clampMatrixUniformCount<3, 4>(location, count, transpose, v);
1637     mProgram->setUniformMatrix3x4fv(location, clampedCount, transpose, v);
1638 }
1639 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1640 void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1641 {
1642     GLsizei clampedCount = clampMatrixUniformCount<4, 2>(location, count, transpose, v);
1643     mProgram->setUniformMatrix4x2fv(location, clampedCount, transpose, v);
1644 }
1645 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * v)1646 void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
1647 {
1648     GLsizei clampedCount = clampMatrixUniformCount<4, 3>(location, count, transpose, v);
1649     mProgram->setUniformMatrix4x3fv(location, clampedCount, transpose, v);
1650 }
1651 
getUniformfv(const Context * context,GLint location,GLfloat * v) const1652 void Program::getUniformfv(const Context *context, GLint location, GLfloat *v) const
1653 {
1654     const auto &uniformLocation = mState.getUniformLocations()[location];
1655     const auto &uniform         = mState.getUniforms()[uniformLocation.index];
1656 
1657     GLenum nativeType = gl::VariableComponentType(uniform.type);
1658     if (nativeType == GL_FLOAT)
1659     {
1660         mProgram->getUniformfv(context, location, v);
1661     }
1662     else
1663     {
1664         getUniformInternal(context, v, location, nativeType,
1665                            gl::VariableComponentCount(uniform.type));
1666     }
1667 }
1668 
getUniformiv(const Context * context,GLint location,GLint * v) const1669 void Program::getUniformiv(const Context *context, GLint location, GLint *v) const
1670 {
1671     const auto &uniformLocation = mState.getUniformLocations()[location];
1672     const auto &uniform         = mState.getUniforms()[uniformLocation.index];
1673 
1674     GLenum nativeType = gl::VariableComponentType(uniform.type);
1675     if (nativeType == GL_INT || nativeType == GL_BOOL)
1676     {
1677         mProgram->getUniformiv(context, location, v);
1678     }
1679     else
1680     {
1681         getUniformInternal(context, v, location, nativeType,
1682                            gl::VariableComponentCount(uniform.type));
1683     }
1684 }
1685 
getUniformuiv(const Context * context,GLint location,GLuint * v) const1686 void Program::getUniformuiv(const Context *context, GLint location, GLuint *v) const
1687 {
1688     const auto &uniformLocation = mState.getUniformLocations()[location];
1689     const auto &uniform         = mState.getUniforms()[uniformLocation.index];
1690 
1691     GLenum nativeType = gl::VariableComponentType(uniform.type);
1692     if (nativeType == GL_UNSIGNED_INT)
1693     {
1694         mProgram->getUniformuiv(context, location, v);
1695     }
1696     else
1697     {
1698         getUniformInternal(context, v, location, nativeType,
1699                            gl::VariableComponentCount(uniform.type));
1700     }
1701 }
1702 
flagForDeletion()1703 void Program::flagForDeletion()
1704 {
1705     mDeleteStatus = true;
1706 }
1707 
isFlaggedForDeletion() const1708 bool Program::isFlaggedForDeletion() const
1709 {
1710     return mDeleteStatus;
1711 }
1712 
validate(const Caps & caps)1713 void Program::validate(const Caps &caps)
1714 {
1715     mInfoLog.reset();
1716 
1717     if (mLinked)
1718     {
1719         mValidated = ConvertToBool(mProgram->validate(caps, &mInfoLog));
1720     }
1721     else
1722     {
1723         mInfoLog << "Program has not been successfully linked.";
1724     }
1725 }
1726 
validateSamplers(InfoLog * infoLog,const Caps & caps)1727 bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps)
1728 {
1729     // Skip cache if we're using an infolog, so we get the full error.
1730     // Also skip the cache if the sample mapping has changed, or if we haven't ever validated.
1731     if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
1732     {
1733         return mCachedValidateSamplersResult.value();
1734     }
1735 
1736     if (mTextureUnitTypesCache.empty())
1737     {
1738         mTextureUnitTypesCache.resize(caps.maxCombinedTextureImageUnits, GL_NONE);
1739     }
1740     else
1741     {
1742         std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
1743     }
1744 
1745     // if any two active samplers in a program are of different types, but refer to the same
1746     // texture image unit, and this is the current program, then ValidateProgram will fail, and
1747     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
1748     for (const auto &samplerBinding : mState.mSamplerBindings)
1749     {
1750         if (samplerBinding.unreferenced)
1751             continue;
1752 
1753         GLenum textureType = samplerBinding.textureType;
1754 
1755         for (GLuint textureUnit : samplerBinding.boundTextureUnits)
1756         {
1757             if (textureUnit >= caps.maxCombinedTextureImageUnits)
1758             {
1759                 if (infoLog)
1760                 {
1761                     (*infoLog) << "Sampler uniform (" << textureUnit
1762                                << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS ("
1763                                << caps.maxCombinedTextureImageUnits << ")";
1764                 }
1765 
1766                 mCachedValidateSamplersResult = false;
1767                 return false;
1768             }
1769 
1770             if (mTextureUnitTypesCache[textureUnit] != GL_NONE)
1771             {
1772                 if (textureType != mTextureUnitTypesCache[textureUnit])
1773                 {
1774                     if (infoLog)
1775                     {
1776                         (*infoLog) << "Samplers of conflicting types refer to the same texture "
1777                                       "image unit ("
1778                                    << textureUnit << ").";
1779                     }
1780 
1781                     mCachedValidateSamplersResult = false;
1782                     return false;
1783                 }
1784             }
1785             else
1786             {
1787                 mTextureUnitTypesCache[textureUnit] = textureType;
1788             }
1789         }
1790     }
1791 
1792     mCachedValidateSamplersResult = true;
1793     return true;
1794 }
1795 
isValidated() const1796 bool Program::isValidated() const
1797 {
1798     return mValidated;
1799 }
1800 
getActiveUniformBlockCount() const1801 GLuint Program::getActiveUniformBlockCount() const
1802 {
1803     return static_cast<GLuint>(mState.mUniformBlocks.size());
1804 }
1805 
getActiveAtomicCounterBufferCount() const1806 GLuint Program::getActiveAtomicCounterBufferCount() const
1807 {
1808     return static_cast<GLuint>(mState.mAtomicCounterBuffers.size());
1809 }
1810 
getActiveShaderStorageBlockCount() const1811 GLuint Program::getActiveShaderStorageBlockCount() const
1812 {
1813     return static_cast<GLuint>(mState.mShaderStorageBlocks.size());
1814 }
1815 
getActiveUniformBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const1816 void Program::getActiveUniformBlockName(const GLuint blockIndex,
1817                                         GLsizei bufSize,
1818                                         GLsizei *length,
1819                                         GLchar *blockName) const
1820 {
1821     GetInterfaceBlockName(blockIndex, mState.mUniformBlocks, bufSize, length, blockName);
1822 }
1823 
getActiveShaderStorageBlockName(const GLuint blockIndex,GLsizei bufSize,GLsizei * length,GLchar * blockName) const1824 void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
1825                                               GLsizei bufSize,
1826                                               GLsizei *length,
1827                                               GLchar *blockName) const
1828 {
1829 
1830     GetInterfaceBlockName(blockIndex, mState.mShaderStorageBlocks, bufSize, length, blockName);
1831 }
1832 
getActiveUniformBlockMaxLength() const1833 GLint Program::getActiveUniformBlockMaxLength() const
1834 {
1835     int maxLength = 0;
1836 
1837     if (mLinked)
1838     {
1839         unsigned int numUniformBlocks = static_cast<unsigned int>(mState.mUniformBlocks.size());
1840         for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
1841         {
1842             const InterfaceBlock &uniformBlock = mState.mUniformBlocks[uniformBlockIndex];
1843             if (!uniformBlock.name.empty())
1844             {
1845                 int length = static_cast<int>(uniformBlock.nameWithArrayIndex().length());
1846                 maxLength  = std::max(length + 1, maxLength);
1847             }
1848         }
1849     }
1850 
1851     return maxLength;
1852 }
1853 
getUniformBlockIndex(const std::string & name) const1854 GLuint Program::getUniformBlockIndex(const std::string &name) const
1855 {
1856     return GetInterfaceBlockIndex(mState.mUniformBlocks, name);
1857 }
1858 
getShaderStorageBlockIndex(const std::string & name) const1859 GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
1860 {
1861     return GetInterfaceBlockIndex(mState.mShaderStorageBlocks, name);
1862 }
1863 
getUniformBlockByIndex(GLuint index) const1864 const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
1865 {
1866     ASSERT(index < static_cast<GLuint>(mState.mUniformBlocks.size()));
1867     return mState.mUniformBlocks[index];
1868 }
1869 
getShaderStorageBlockByIndex(GLuint index) const1870 const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
1871 {
1872     ASSERT(index < static_cast<GLuint>(mState.mShaderStorageBlocks.size()));
1873     return mState.mShaderStorageBlocks[index];
1874 }
1875 
bindUniformBlock(GLuint uniformBlockIndex,GLuint uniformBlockBinding)1876 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
1877 {
1878     mState.mUniformBlocks[uniformBlockIndex].binding = uniformBlockBinding;
1879     mState.mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlockBinding != 0);
1880     mProgram->setUniformBlockBinding(uniformBlockIndex, uniformBlockBinding);
1881 }
1882 
getUniformBlockBinding(GLuint uniformBlockIndex) const1883 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
1884 {
1885     return mState.getUniformBlockBinding(uniformBlockIndex);
1886 }
1887 
getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const1888 GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
1889 {
1890     return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
1891 }
1892 
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)1893 void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
1894 {
1895     mState.mTransformFeedbackVaryingNames.resize(count);
1896     for (GLsizei i = 0; i < count; i++)
1897     {
1898         mState.mTransformFeedbackVaryingNames[i] = varyings[i];
1899     }
1900 
1901     mState.mTransformFeedbackBufferMode = bufferMode;
1902 }
1903 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const1904 void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
1905 {
1906     if (mLinked)
1907     {
1908         ASSERT(index < mState.mLinkedTransformFeedbackVaryings.size());
1909         const auto &var     = mState.mLinkedTransformFeedbackVaryings[index];
1910         std::string varName = var.nameWithArrayIndex();
1911         GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
1912         if (length)
1913         {
1914             *length = lastNameIdx;
1915         }
1916         if (size)
1917         {
1918             *size = var.size();
1919         }
1920         if (type)
1921         {
1922             *type = var.type;
1923         }
1924         if (name)
1925         {
1926             memcpy(name, varName.c_str(), lastNameIdx);
1927             name[lastNameIdx] = '\0';
1928         }
1929     }
1930 }
1931 
getTransformFeedbackVaryingCount() const1932 GLsizei Program::getTransformFeedbackVaryingCount() const
1933 {
1934     if (mLinked)
1935     {
1936         return static_cast<GLsizei>(mState.mLinkedTransformFeedbackVaryings.size());
1937     }
1938     else
1939     {
1940         return 0;
1941     }
1942 }
1943 
getTransformFeedbackVaryingMaxLength() const1944 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
1945 {
1946     if (mLinked)
1947     {
1948         GLsizei maxSize = 0;
1949         for (const auto &var : mState.mLinkedTransformFeedbackVaryings)
1950         {
1951             maxSize =
1952                 std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
1953         }
1954 
1955         return maxSize;
1956     }
1957     else
1958     {
1959         return 0;
1960     }
1961 }
1962 
getTransformFeedbackBufferMode() const1963 GLenum Program::getTransformFeedbackBufferMode() const
1964 {
1965     return mState.mTransformFeedbackBufferMode;
1966 }
1967 
linkVaryings(const Context * context,InfoLog & infoLog) const1968 bool Program::linkVaryings(const Context *context, InfoLog &infoLog) const
1969 {
1970     Shader *vertexShader   = mState.mAttachedVertexShader;
1971     Shader *fragmentShader = mState.mAttachedFragmentShader;
1972 
1973     ASSERT(vertexShader->getShaderVersion(context) == fragmentShader->getShaderVersion(context));
1974 
1975     const std::vector<sh::Varying> &vertexVaryings   = vertexShader->getOutputVaryings(context);
1976     const std::vector<sh::Varying> &fragmentVaryings = fragmentShader->getInputVaryings(context);
1977 
1978     std::map<GLuint, std::string> staticFragmentInputLocations;
1979 
1980     for (const sh::Varying &output : fragmentVaryings)
1981     {
1982         bool matched = false;
1983 
1984         // Built-in varyings obey special rules
1985         if (output.isBuiltIn())
1986         {
1987             continue;
1988         }
1989 
1990         for (const sh::Varying &input : vertexVaryings)
1991         {
1992             if (output.name == input.name)
1993             {
1994                 ASSERT(!input.isBuiltIn());
1995                 if (!linkValidateVaryings(infoLog, output.name, input, output,
1996                                           vertexShader->getShaderVersion(context)))
1997                 {
1998                     return false;
1999                 }
2000 
2001                 matched = true;
2002                 break;
2003             }
2004         }
2005 
2006         // We permit unmatched, unreferenced varyings
2007         if (!matched && output.staticUse)
2008         {
2009             infoLog << "Fragment varying " << output.name << " does not match any vertex varying";
2010             return false;
2011         }
2012 
2013         // Check for aliased path rendering input bindings (if any).
2014         // If more than one binding refer statically to the same
2015         // location the link must fail.
2016 
2017         if (!output.staticUse)
2018             continue;
2019 
2020         const auto inputBinding = mFragmentInputBindings.getBinding(output.name);
2021         if (inputBinding == -1)
2022             continue;
2023 
2024         const auto it = staticFragmentInputLocations.find(inputBinding);
2025         if (it == std::end(staticFragmentInputLocations))
2026         {
2027             staticFragmentInputLocations.insert(std::make_pair(inputBinding, output.name));
2028         }
2029         else
2030         {
2031             infoLog << "Binding for fragment input " << output.name << " conflicts with "
2032                     << it->second;
2033             return false;
2034         }
2035     }
2036 
2037     if (!linkValidateBuiltInVaryings(context, infoLog))
2038     {
2039         return false;
2040     }
2041 
2042     // TODO(jmadill): verify no unmatched vertex varyings?
2043 
2044     return true;
2045 }
2046 
linkUniforms(const Context * context,InfoLog & infoLog,const Bindings & uniformLocationBindings)2047 bool Program::linkUniforms(const Context *context,
2048                            InfoLog &infoLog,
2049                            const Bindings &uniformLocationBindings)
2050 {
2051     UniformLinker linker(mState);
2052     if (!linker.link(context, infoLog, uniformLocationBindings))
2053     {
2054         return false;
2055     }
2056 
2057     linker.getResults(&mState.mUniforms, &mState.mUniformLocations);
2058 
2059     linkSamplerAndImageBindings();
2060 
2061     if (!linkAtomicCounterBuffers())
2062     {
2063         return false;
2064     }
2065 
2066     return true;
2067 }
2068 
linkSamplerAndImageBindings()2069 void Program::linkSamplerAndImageBindings()
2070 {
2071     unsigned int high = static_cast<unsigned int>(mState.mUniforms.size());
2072     unsigned int low  = high;
2073 
2074     for (auto counterIter = mState.mUniforms.rbegin();
2075          counterIter != mState.mUniforms.rend() && counterIter->isAtomicCounter(); ++counterIter)
2076     {
2077         --low;
2078     }
2079 
2080     mState.mAtomicCounterUniformRange = RangeUI(low, high);
2081 
2082     high = low;
2083 
2084     for (auto imageIter = mState.mUniforms.rbegin();
2085          imageIter != mState.mUniforms.rend() && imageIter->isImage(); ++imageIter)
2086     {
2087         --low;
2088     }
2089 
2090     mState.mImageUniformRange = RangeUI(low, high);
2091 
2092     // If uniform is a image type, insert it into the mImageBindings array.
2093     for (unsigned int imageIndex : mState.mImageUniformRange)
2094     {
2095         // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
2096         // cannot load values into a uniform defined as an image. if declare without a
2097         // binding qualifier, any uniform image variable (include all elements of
2098         // unbound image array) shoud be bound to unit zero.
2099         auto &imageUniform = mState.mUniforms[imageIndex];
2100         if (imageUniform.binding == -1)
2101         {
2102             mState.mImageBindings.emplace_back(
2103                 ImageBinding(imageUniform.getBasicTypeElementCount()));
2104         }
2105         else
2106         {
2107             mState.mImageBindings.emplace_back(
2108                 ImageBinding(imageUniform.binding, imageUniform.getBasicTypeElementCount()));
2109         }
2110     }
2111 
2112     high = low;
2113 
2114     for (auto samplerIter = mState.mUniforms.rbegin() + mState.mImageUniformRange.length();
2115          samplerIter != mState.mUniforms.rend() && samplerIter->isSampler(); ++samplerIter)
2116     {
2117         --low;
2118     }
2119 
2120     mState.mSamplerUniformRange = RangeUI(low, high);
2121 
2122     // If uniform is a sampler type, insert it into the mSamplerBindings array.
2123     for (unsigned int samplerIndex : mState.mSamplerUniformRange)
2124     {
2125         const auto &samplerUniform = mState.mUniforms[samplerIndex];
2126         GLenum textureType         = SamplerTypeToTextureType(samplerUniform.type);
2127         mState.mSamplerBindings.emplace_back(
2128             SamplerBinding(textureType, samplerUniform.getBasicTypeElementCount(), false));
2129     }
2130 }
2131 
linkAtomicCounterBuffers()2132 bool Program::linkAtomicCounterBuffers()
2133 {
2134     for (unsigned int index : mState.mAtomicCounterUniformRange)
2135     {
2136         auto &uniform = mState.mUniforms[index];
2137         bool found    = false;
2138         for (unsigned int bufferIndex = 0; bufferIndex < mState.mAtomicCounterBuffers.size();
2139              ++bufferIndex)
2140         {
2141             auto &buffer = mState.mAtomicCounterBuffers[bufferIndex];
2142             if (buffer.binding == uniform.binding)
2143             {
2144                 buffer.memberIndexes.push_back(index);
2145                 uniform.bufferIndex = bufferIndex;
2146                 found               = true;
2147                 buffer.unionReferencesWith(uniform);
2148                 break;
2149             }
2150         }
2151         if (!found)
2152         {
2153             AtomicCounterBuffer atomicCounterBuffer;
2154             atomicCounterBuffer.binding = uniform.binding;
2155             atomicCounterBuffer.memberIndexes.push_back(index);
2156             atomicCounterBuffer.unionReferencesWith(uniform);
2157             mState.mAtomicCounterBuffers.push_back(atomicCounterBuffer);
2158             uniform.bufferIndex = static_cast<int>(mState.mAtomicCounterBuffers.size() - 1);
2159         }
2160     }
2161     // TODO(jie.a.chen@intel.com): Count each atomic counter buffer to validate against
2162     // gl_Max[Vertex|Fragment|Compute|Combined]AtomicCounterBuffers.
2163 
2164     return true;
2165 }
2166 
linkValidateInterfaceBlockFields(InfoLog & infoLog,const std::string & uniformName,const sh::InterfaceBlockField & vertexUniform,const sh::InterfaceBlockField & fragmentUniform,bool webglCompatibility)2167 bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog,
2168                                                const std::string &uniformName,
2169                                                const sh::InterfaceBlockField &vertexUniform,
2170                                                const sh::InterfaceBlockField &fragmentUniform,
2171                                                bool webglCompatibility)
2172 {
2173     // If webgl, validate precision of UBO fields, otherwise don't.  See Khronos bug 10287.
2174     if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform,
2175                                    webglCompatibility))
2176     {
2177         return false;
2178     }
2179 
2180     if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
2181     {
2182         infoLog << "Matrix packings for " << uniformName << " differ between vertex and fragment shaders";
2183         return false;
2184     }
2185 
2186     return true;
2187 }
2188 
2189 // Assigns locations to all attributes from the bindings and program locations.
linkAttributes(const Context * context,InfoLog & infoLog)2190 bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
2191 {
2192     const ContextState &data = context->getContextState();
2193     auto *vertexShader       = mState.getAttachedVertexShader();
2194 
2195     unsigned int usedLocations = 0;
2196     mState.mAttributes         = vertexShader->getActiveAttributes(context);
2197     GLuint maxAttribs          = data.getCaps().maxVertexAttributes;
2198 
2199     // TODO(jmadill): handle aliasing robustly
2200     if (mState.mAttributes.size() > maxAttribs)
2201     {
2202         infoLog << "Too many vertex attributes.";
2203         return false;
2204     }
2205 
2206     std::vector<sh::Attribute *> usedAttribMap(maxAttribs, nullptr);
2207 
2208     // Link attributes that have a binding location
2209     for (sh::Attribute &attribute : mState.mAttributes)
2210     {
2211         // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
2212         // structures, so we don't need to worry about adjusting their names or generating entries
2213         // for each member/element (unlike uniforms for example).
2214         ASSERT(!attribute.isArray() && !attribute.isStruct());
2215 
2216         int bindingLocation = mAttributeBindings.getBinding(attribute.name);
2217         if (attribute.location == -1 && bindingLocation != -1)
2218         {
2219             attribute.location = bindingLocation;
2220         }
2221 
2222         if (attribute.location != -1)
2223         {
2224             // Location is set by glBindAttribLocation or by location layout qualifier
2225             const int regs = VariableRegisterCount(attribute.type);
2226 
2227             if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
2228             {
2229                 infoLog << "Active attribute (" << attribute.name << ") at location "
2230                         << attribute.location << " is too big to fit";
2231 
2232                 return false;
2233             }
2234 
2235             for (int reg = 0; reg < regs; reg++)
2236             {
2237                 const int regLocation               = attribute.location + reg;
2238                 sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
2239 
2240                 // In GLSL 3.00, attribute aliasing produces a link error
2241                 // In GLSL 1.00, attribute aliasing is allowed, but ANGLE currently has a bug
2242                 if (linkedAttribute)
2243                 {
2244                     // TODO(jmadill): fix aliasing on ES2
2245                     // if (mProgram->getShaderVersion() >= 300)
2246                     {
2247                         infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
2248                                 << linkedAttribute->name << "' at location " << regLocation;
2249                         return false;
2250                     }
2251                 }
2252                 else
2253                 {
2254                     usedAttribMap[regLocation] = &attribute;
2255                 }
2256 
2257                 usedLocations |= 1 << regLocation;
2258             }
2259         }
2260     }
2261 
2262     // Link attributes that don't have a binding location
2263     for (sh::Attribute &attribute : mState.mAttributes)
2264     {
2265         // Not set by glBindAttribLocation or by location layout qualifier
2266         if (attribute.location == -1)
2267         {
2268             int regs           = VariableRegisterCount(attribute.type);
2269             int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
2270 
2271             if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
2272             {
2273                 infoLog << "Too many active attributes (" << attribute.name << ")";
2274                 return false;
2275             }
2276 
2277             attribute.location = availableIndex;
2278         }
2279     }
2280 
2281     for (const sh::Attribute &attribute : mState.mAttributes)
2282     {
2283         ASSERT(attribute.location != -1);
2284         unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
2285 
2286         for (unsigned int r = 0; r < regs; r++)
2287         {
2288             unsigned int location = static_cast<unsigned int>(attribute.location) + r;
2289             mState.mActiveAttribLocationsMask.set(location);
2290             mState.mMaxActiveAttribLocation =
2291                 std::max(mState.mMaxActiveAttribLocation, location + 1);
2292         }
2293     }
2294 
2295     return true;
2296 }
2297 
validateVertexAndFragmentInterfaceBlocks(const std::vector<sh::InterfaceBlock> & vertexInterfaceBlocks,const std::vector<sh::InterfaceBlock> & fragmentInterfaceBlocks,InfoLog & infoLog,bool webglCompatibility) const2298 bool Program::validateVertexAndFragmentInterfaceBlocks(
2299     const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks,
2300     const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks,
2301     InfoLog &infoLog,
2302     bool webglCompatibility) const
2303 {
2304     // Check that interface blocks defined in the vertex and fragment shaders are identical
2305     typedef std::map<std::string, const sh::InterfaceBlock *> InterfaceBlockMap;
2306     InterfaceBlockMap linkedInterfaceBlocks;
2307 
2308     for (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks)
2309     {
2310         linkedInterfaceBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
2311     }
2312 
2313     for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks)
2314     {
2315         auto entry = linkedInterfaceBlocks.find(fragmentInterfaceBlock.name);
2316         if (entry != linkedInterfaceBlocks.end())
2317         {
2318             const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
2319             if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock,
2320                                             webglCompatibility))
2321             {
2322                 return false;
2323             }
2324         }
2325         // TODO(jiajia.qin@intel.com): Add
2326         // MAX_COMBINED_UNIFORM_BLOCKS/MAX_COMBINED_SHADER_STORAGE_BLOCKS validation.
2327     }
2328     return true;
2329 }
2330 
linkInterfaceBlocks(const Context * context,InfoLog & infoLog)2331 bool Program::linkInterfaceBlocks(const Context *context, InfoLog &infoLog)
2332 {
2333     const auto &caps = context->getCaps();
2334 
2335     if (mState.mAttachedComputeShader)
2336     {
2337         Shader &computeShader              = *mState.mAttachedComputeShader;
2338         const auto &computeUniformBlocks   = computeShader.getUniformBlocks(context);
2339 
2340         if (!validateInterfaceBlocksCount(
2341                 caps.maxComputeUniformBlocks, computeUniformBlocks,
2342                 "Compute shader uniform block count exceeds GL_MAX_COMPUTE_UNIFORM_BLOCKS (",
2343                 infoLog))
2344         {
2345             return false;
2346         }
2347 
2348         const auto &computeShaderStorageBlocks = computeShader.getShaderStorageBlocks(context);
2349         if (!validateInterfaceBlocksCount(caps.maxComputeShaderStorageBlocks,
2350                                           computeShaderStorageBlocks,
2351                                           "Compute shader shader storage block count exceeds "
2352                                           "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS (",
2353                                           infoLog))
2354         {
2355             return false;
2356         }
2357         return true;
2358     }
2359 
2360     Shader &vertexShader   = *mState.mAttachedVertexShader;
2361     Shader &fragmentShader = *mState.mAttachedFragmentShader;
2362 
2363     const auto &vertexUniformBlocks   = vertexShader.getUniformBlocks(context);
2364     const auto &fragmentUniformBlocks = fragmentShader.getUniformBlocks(context);
2365 
2366     if (!validateInterfaceBlocksCount(
2367             caps.maxVertexUniformBlocks, vertexUniformBlocks,
2368             "Vertex shader uniform block count exceeds GL_MAX_VERTEX_UNIFORM_BLOCKS (", infoLog))
2369     {
2370         return false;
2371     }
2372     if (!validateInterfaceBlocksCount(
2373             caps.maxFragmentUniformBlocks, fragmentUniformBlocks,
2374             "Fragment shader uniform block count exceeds GL_MAX_FRAGMENT_UNIFORM_BLOCKS (",
2375             infoLog))
2376     {
2377 
2378         return false;
2379     }
2380 
2381     bool webglCompatibility = context->getExtensions().webglCompatibility;
2382     if (!validateVertexAndFragmentInterfaceBlocks(vertexUniformBlocks, fragmentUniformBlocks,
2383                                                   infoLog, webglCompatibility))
2384     {
2385         return false;
2386     }
2387 
2388     if (context->getClientVersion() >= Version(3, 1))
2389     {
2390         const auto &vertexShaderStorageBlocks   = vertexShader.getShaderStorageBlocks(context);
2391         const auto &fragmentShaderStorageBlocks = fragmentShader.getShaderStorageBlocks(context);
2392 
2393         if (!validateInterfaceBlocksCount(caps.maxVertexShaderStorageBlocks,
2394                                           vertexShaderStorageBlocks,
2395                                           "Vertex shader shader storage block count exceeds "
2396                                           "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS (",
2397                                           infoLog))
2398         {
2399             return false;
2400         }
2401         if (!validateInterfaceBlocksCount(caps.maxFragmentShaderStorageBlocks,
2402                                           fragmentShaderStorageBlocks,
2403                                           "Fragment shader shader storage block count exceeds "
2404                                           "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS (",
2405                                           infoLog))
2406         {
2407 
2408             return false;
2409         }
2410 
2411         if (!validateVertexAndFragmentInterfaceBlocks(vertexShaderStorageBlocks,
2412                                                       fragmentShaderStorageBlocks, infoLog,
2413                                                       webglCompatibility))
2414         {
2415             return false;
2416         }
2417     }
2418     return true;
2419 }
2420 
areMatchingInterfaceBlocks(InfoLog & infoLog,const sh::InterfaceBlock & vertexInterfaceBlock,const sh::InterfaceBlock & fragmentInterfaceBlock,bool webglCompatibility) const2421 bool Program::areMatchingInterfaceBlocks(InfoLog &infoLog,
2422                                          const sh::InterfaceBlock &vertexInterfaceBlock,
2423                                          const sh::InterfaceBlock &fragmentInterfaceBlock,
2424                                          bool webglCompatibility) const
2425 {
2426     const char* blockName = vertexInterfaceBlock.name.c_str();
2427     // validate blocks for the same member types
2428     if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
2429     {
2430         infoLog << "Types for interface block '" << blockName
2431                 << "' differ between vertex and fragment shaders";
2432         return false;
2433     }
2434     if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
2435     {
2436         infoLog << "Array sizes differ for interface block '" << blockName
2437                 << "' between vertex and fragment shaders";
2438         return false;
2439     }
2440     if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout ||
2441         vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout ||
2442         vertexInterfaceBlock.binding != fragmentInterfaceBlock.binding)
2443     {
2444         infoLog << "Layout qualifiers differ for interface block '" << blockName
2445                 << "' between vertex and fragment shaders";
2446         return false;
2447     }
2448     const unsigned int numBlockMembers =
2449         static_cast<unsigned int>(vertexInterfaceBlock.fields.size());
2450     for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
2451     {
2452         const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
2453         const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
2454         if (vertexMember.name != fragmentMember.name)
2455         {
2456             infoLog << "Name mismatch for field " << blockMemberIndex
2457                     << " of interface block '" << blockName
2458                     << "': (in vertex: '" << vertexMember.name
2459                     << "', in fragment: '" << fragmentMember.name << "')";
2460             return false;
2461         }
2462         std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
2463         if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember,
2464                                               webglCompatibility))
2465         {
2466             return false;
2467         }
2468     }
2469     return true;
2470 }
2471 
linkValidateVariablesBase(InfoLog & infoLog,const std::string & variableName,const sh::ShaderVariable & vertexVariable,const sh::ShaderVariable & fragmentVariable,bool validatePrecision)2472 bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
2473                                               const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
2474 {
2475     if (vertexVariable.type != fragmentVariable.type)
2476     {
2477         infoLog << "Types for " << variableName << " differ between vertex and fragment shaders";
2478         return false;
2479     }
2480     if (vertexVariable.arraySizes != fragmentVariable.arraySizes)
2481     {
2482         infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders";
2483         return false;
2484     }
2485     if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
2486     {
2487         infoLog << "Precisions for " << variableName << " differ between vertex and fragment shaders";
2488         return false;
2489     }
2490     if (vertexVariable.structName != fragmentVariable.structName)
2491     {
2492         infoLog << "Structure names for " << variableName
2493                 << " differ between vertex and fragment shaders";
2494         return false;
2495     }
2496 
2497     if (vertexVariable.fields.size() != fragmentVariable.fields.size())
2498     {
2499         infoLog << "Structure lengths for " << variableName << " differ between vertex and fragment shaders";
2500         return false;
2501     }
2502     const unsigned int numMembers = static_cast<unsigned int>(vertexVariable.fields.size());
2503     for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
2504     {
2505         const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex];
2506         const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex];
2507 
2508         if (vertexMember.name != fragmentMember.name)
2509         {
2510             infoLog << "Name mismatch for field '" << memberIndex
2511                     << "' of " << variableName
2512                     << ": (in vertex: '" << vertexMember.name
2513                     << "', in fragment: '" << fragmentMember.name << "')";
2514             return false;
2515         }
2516 
2517         const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
2518                                        vertexMember.name + "'";
2519 
2520         if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
2521         {
2522             return false;
2523         }
2524     }
2525 
2526     return true;
2527 }
2528 
linkValidateVaryings(InfoLog & infoLog,const std::string & varyingName,const sh::Varying & vertexVarying,const sh::Varying & fragmentVarying,int shaderVersion)2529 bool Program::linkValidateVaryings(InfoLog &infoLog,
2530                                    const std::string &varyingName,
2531                                    const sh::Varying &vertexVarying,
2532                                    const sh::Varying &fragmentVarying,
2533                                    int shaderVersion)
2534 {
2535     if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
2536     {
2537         return false;
2538     }
2539 
2540     if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation))
2541     {
2542         infoLog << "Interpolation types for " << varyingName
2543                 << " differ between vertex and fragment shaders.";
2544         return false;
2545     }
2546 
2547     if (shaderVersion == 100 && vertexVarying.isInvariant != fragmentVarying.isInvariant)
2548     {
2549         infoLog << "Invariance for " << varyingName
2550                 << " differs between vertex and fragment shaders.";
2551         return false;
2552     }
2553 
2554     return true;
2555 }
2556 
linkValidateBuiltInVaryings(const Context * context,InfoLog & infoLog) const2557 bool Program::linkValidateBuiltInVaryings(const Context *context, InfoLog &infoLog) const
2558 {
2559     Shader *vertexShader         = mState.mAttachedVertexShader;
2560     Shader *fragmentShader       = mState.mAttachedFragmentShader;
2561     const auto &vertexVaryings   = vertexShader->getOutputVaryings(context);
2562     const auto &fragmentVaryings = fragmentShader->getInputVaryings(context);
2563     int shaderVersion            = vertexShader->getShaderVersion(context);
2564 
2565     if (shaderVersion != 100)
2566     {
2567         // Only ESSL 1.0 has restrictions on matching input and output invariance
2568         return true;
2569     }
2570 
2571     bool glPositionIsInvariant   = false;
2572     bool glPointSizeIsInvariant  = false;
2573     bool glFragCoordIsInvariant  = false;
2574     bool glPointCoordIsInvariant = false;
2575 
2576     for (const sh::Varying &varying : vertexVaryings)
2577     {
2578         if (!varying.isBuiltIn())
2579         {
2580             continue;
2581         }
2582         if (varying.name.compare("gl_Position") == 0)
2583         {
2584             glPositionIsInvariant = varying.isInvariant;
2585         }
2586         else if (varying.name.compare("gl_PointSize") == 0)
2587         {
2588             glPointSizeIsInvariant = varying.isInvariant;
2589         }
2590     }
2591 
2592     for (const sh::Varying &varying : fragmentVaryings)
2593     {
2594         if (!varying.isBuiltIn())
2595         {
2596             continue;
2597         }
2598         if (varying.name.compare("gl_FragCoord") == 0)
2599         {
2600             glFragCoordIsInvariant = varying.isInvariant;
2601         }
2602         else if (varying.name.compare("gl_PointCoord") == 0)
2603         {
2604             glPointCoordIsInvariant = varying.isInvariant;
2605         }
2606     }
2607 
2608     // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
2609     // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
2610     // Not requiring invariance to match is supported by:
2611     // dEQP, WebGL CTS, Nexus 5X GLES
2612     if (glFragCoordIsInvariant && !glPositionIsInvariant)
2613     {
2614         infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
2615                    "declared invariant.";
2616         return false;
2617     }
2618     if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
2619     {
2620         infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
2621                    "declared invariant.";
2622         return false;
2623     }
2624 
2625     return true;
2626 }
2627 
linkValidateTransformFeedback(const gl::Context * context,InfoLog & infoLog,const Program::MergedVaryings & varyings,const Caps & caps) const2628 bool Program::linkValidateTransformFeedback(const gl::Context *context,
2629                                             InfoLog &infoLog,
2630                                             const Program::MergedVaryings &varyings,
2631                                             const Caps &caps) const
2632 {
2633     size_t totalComponents = 0;
2634 
2635     std::set<std::string> uniqueNames;
2636 
2637     for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
2638     {
2639         bool found = false;
2640         std::vector<unsigned int> subscripts;
2641         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
2642 
2643         for (const auto &ref : varyings)
2644         {
2645             const sh::Varying *varying = ref.second.get();
2646 
2647             if (baseName == varying->name)
2648             {
2649                 if (uniqueNames.count(tfVaryingName) > 0)
2650                 {
2651                     infoLog << "Two transform feedback varyings specify the same output variable ("
2652                             << tfVaryingName << ").";
2653                     return false;
2654                 }
2655                 if (context->getClientVersion() >= Version(3, 1))
2656                 {
2657                     if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
2658                     {
2659                         infoLog
2660                             << "Two transform feedback varyings include the same array element ("
2661                             << tfVaryingName << ").";
2662                         return false;
2663                     }
2664                 }
2665                 else if (varying->isArray())
2666                 {
2667                     infoLog << "Capture of arrays is undefined and not supported.";
2668                     return false;
2669                 }
2670 
2671                 uniqueNames.insert(tfVaryingName);
2672 
2673                 // TODO(jmadill): Investigate implementation limits on D3D11
2674 
2675                 // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
2676                 ASSERT(!varying->isArrayOfArrays());
2677                 size_t elementCount =
2678                     ((varying->isArray() && subscripts.empty()) ? varying->getOutermostArraySize()
2679                                                                 : 1);
2680                 size_t componentCount = VariableComponentCount(varying->type) * elementCount;
2681                 if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
2682                     componentCount > caps.maxTransformFeedbackSeparateComponents)
2683                 {
2684                     infoLog << "Transform feedback varying's " << varying->name << " components ("
2685                             << componentCount << ") exceed the maximum separate components ("
2686                             << caps.maxTransformFeedbackSeparateComponents << ").";
2687                     return false;
2688                 }
2689 
2690                 totalComponents += componentCount;
2691                 found = true;
2692                 break;
2693             }
2694         }
2695         if (context->getClientVersion() < Version(3, 1) &&
2696             tfVaryingName.find('[') != std::string::npos)
2697         {
2698             infoLog << "Capture of array elements is undefined and not supported.";
2699             return false;
2700         }
2701         if (!found)
2702         {
2703             infoLog << "Transform feedback varying " << tfVaryingName
2704                     << " does not exist in the vertex shader.";
2705             return false;
2706         }
2707     }
2708 
2709     if (mState.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
2710         totalComponents > caps.maxTransformFeedbackInterleavedComponents)
2711     {
2712         infoLog << "Transform feedback varying total components (" << totalComponents
2713                 << ") exceed the maximum interleaved components ("
2714                 << caps.maxTransformFeedbackInterleavedComponents << ").";
2715         return false;
2716     }
2717 
2718     return true;
2719 }
2720 
linkValidateGlobalNames(const Context * context,InfoLog & infoLog) const2721 bool Program::linkValidateGlobalNames(const Context *context, InfoLog &infoLog) const
2722 {
2723     const std::vector<sh::Uniform> &vertexUniforms =
2724         mState.mAttachedVertexShader->getUniforms(context);
2725     const std::vector<sh::Uniform> &fragmentUniforms =
2726         mState.mAttachedFragmentShader->getUniforms(context);
2727     const std::vector<sh::Attribute> &attributes =
2728         mState.mAttachedVertexShader->getActiveAttributes(context);
2729     for (const auto &attrib : attributes)
2730     {
2731         for (const auto &uniform : vertexUniforms)
2732         {
2733             if (uniform.name == attrib.name)
2734             {
2735                 infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
2736                 return false;
2737             }
2738         }
2739         for (const auto &uniform : fragmentUniforms)
2740         {
2741             if (uniform.name == attrib.name)
2742             {
2743                 infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
2744                 return false;
2745             }
2746         }
2747     }
2748     return true;
2749 }
2750 
gatherTransformFeedbackVaryings(const Program::MergedVaryings & varyings)2751 void Program::gatherTransformFeedbackVaryings(const Program::MergedVaryings &varyings)
2752 {
2753     // Gather the linked varyings that are used for transform feedback, they should all exist.
2754     mState.mLinkedTransformFeedbackVaryings.clear();
2755     for (const std::string &tfVaryingName : mState.mTransformFeedbackVaryingNames)
2756     {
2757         std::vector<unsigned int> subscripts;
2758         std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
2759         size_t subscript     = GL_INVALID_INDEX;
2760         if (!subscripts.empty())
2761         {
2762             subscript = subscripts.back();
2763         }
2764         for (const auto &ref : varyings)
2765         {
2766             const sh::Varying *varying = ref.second.get();
2767             if (baseName == varying->name)
2768             {
2769                 mState.mLinkedTransformFeedbackVaryings.emplace_back(
2770                     *varying, static_cast<GLuint>(subscript));
2771                 break;
2772             }
2773         }
2774     }
2775 }
2776 
getMergedVaryings(const Context * context) const2777 Program::MergedVaryings Program::getMergedVaryings(const Context *context) const
2778 {
2779     MergedVaryings merged;
2780 
2781     for (const sh::Varying &varying : mState.mAttachedVertexShader->getOutputVaryings(context))
2782     {
2783         merged[varying.name].vertex = &varying;
2784     }
2785 
2786     for (const sh::Varying &varying : mState.mAttachedFragmentShader->getInputVaryings(context))
2787     {
2788         merged[varying.name].fragment = &varying;
2789     }
2790 
2791     return merged;
2792 }
2793 
2794 
linkOutputVariables(const Context * context)2795 void Program::linkOutputVariables(const Context *context)
2796 {
2797     Shader *fragmentShader = mState.mAttachedFragmentShader;
2798     ASSERT(fragmentShader != nullptr);
2799 
2800     ASSERT(mState.mOutputVariableTypes.empty());
2801     ASSERT(mState.mActiveOutputVariables.none());
2802 
2803     // Gather output variable types
2804     for (const auto &outputVariable : fragmentShader->getActiveOutputVariables(context))
2805     {
2806         if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
2807             outputVariable.name != "gl_FragData")
2808         {
2809             continue;
2810         }
2811 
2812         unsigned int baseLocation =
2813             (outputVariable.location == -1 ? 0u
2814                                            : static_cast<unsigned int>(outputVariable.location));
2815 
2816         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
2817         // structures, so we may use getBasicTypeElementCount().
2818         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
2819         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
2820         {
2821             const unsigned int location = baseLocation + elementIndex;
2822             if (location >= mState.mOutputVariableTypes.size())
2823             {
2824                 mState.mOutputVariableTypes.resize(location + 1, GL_NONE);
2825             }
2826             ASSERT(location < mState.mActiveOutputVariables.size());
2827             mState.mActiveOutputVariables.set(location);
2828             mState.mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
2829         }
2830     }
2831 
2832     // Skip this step for GLES2 shaders.
2833     if (fragmentShader->getShaderVersion(context) == 100)
2834         return;
2835 
2836     mState.mOutputVariables = fragmentShader->getActiveOutputVariables(context);
2837     // TODO(jmadill): any caps validation here?
2838 
2839     for (unsigned int outputVariableIndex = 0; outputVariableIndex < mState.mOutputVariables.size();
2840          outputVariableIndex++)
2841     {
2842         const sh::OutputVariable &outputVariable = mState.mOutputVariables[outputVariableIndex];
2843 
2844         if (outputVariable.isArray())
2845         {
2846             // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active
2847             // Resources and including [0] at the end of array variable names.
2848             mState.mOutputVariables[outputVariableIndex].name += "[0]";
2849             mState.mOutputVariables[outputVariableIndex].mappedName += "[0]";
2850         }
2851 
2852         // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
2853         if (outputVariable.isBuiltIn())
2854             continue;
2855 
2856         // Since multiple output locations must be specified, use 0 for non-specified locations.
2857         unsigned int baseLocation =
2858             (outputVariable.location == -1 ? 0u
2859                                            : static_cast<unsigned int>(outputVariable.location));
2860 
2861         // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
2862         // structures, so we may use getBasicTypeElementCount().
2863         unsigned int elementCount = outputVariable.getBasicTypeElementCount();
2864         for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
2865         {
2866             const unsigned int location = baseLocation + elementIndex;
2867             if (location >= mState.mOutputLocations.size())
2868             {
2869                 mState.mOutputLocations.resize(location + 1);
2870             }
2871             ASSERT(!mState.mOutputLocations.at(location).used());
2872             if (outputVariable.isArray())
2873             {
2874                 mState.mOutputLocations[location] =
2875                     VariableLocation(elementIndex, outputVariableIndex);
2876             }
2877             else
2878             {
2879                 VariableLocation locationInfo;
2880                 locationInfo.index                = outputVariableIndex;
2881                 mState.mOutputLocations[location] = locationInfo;
2882             }
2883         }
2884     }
2885 }
2886 
setUniformValuesFromBindingQualifiers()2887 void Program::setUniformValuesFromBindingQualifiers()
2888 {
2889     for (unsigned int samplerIndex : mState.mSamplerUniformRange)
2890     {
2891         const auto &samplerUniform = mState.mUniforms[samplerIndex];
2892         if (samplerUniform.binding != -1)
2893         {
2894             GLint location = getUniformLocation(samplerUniform.name);
2895             ASSERT(location != -1);
2896             std::vector<GLint> boundTextureUnits;
2897             for (unsigned int elementIndex = 0;
2898                  elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
2899             {
2900                 boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
2901             }
2902             setUniform1iv(location, static_cast<GLsizei>(boundTextureUnits.size()),
2903                           boundTextureUnits.data());
2904         }
2905     }
2906 }
2907 
gatherAtomicCounterBuffers()2908 void Program::gatherAtomicCounterBuffers()
2909 {
2910     for (unsigned int index : mState.mAtomicCounterUniformRange)
2911     {
2912         auto &uniform                      = mState.mUniforms[index];
2913         uniform.blockInfo.offset           = uniform.offset;
2914         uniform.blockInfo.arrayStride      = (uniform.isArray() ? 4 : 0);
2915         uniform.blockInfo.matrixStride     = 0;
2916         uniform.blockInfo.isRowMajorMatrix = false;
2917     }
2918 
2919     // TODO(jie.a.chen@intel.com): Get the actual BUFFER_DATA_SIZE from backend for each buffer.
2920 }
2921 
initInterfaceBlockBindings()2922 void Program::initInterfaceBlockBindings()
2923 {
2924     // Set initial bindings from shader.
2925     for (unsigned int blockIndex = 0; blockIndex < mState.mUniformBlocks.size(); blockIndex++)
2926     {
2927         InterfaceBlock &uniformBlock = mState.mUniformBlocks[blockIndex];
2928         bindUniformBlock(blockIndex, uniformBlock.binding);
2929     }
2930 }
2931 
updateSamplerUniform(const VariableLocation & locationInfo,GLsizei clampedCount,const GLint * v)2932 void Program::updateSamplerUniform(const VariableLocation &locationInfo,
2933                                    GLsizei clampedCount,
2934                                    const GLint *v)
2935 {
2936     ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
2937     GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
2938     std::vector<GLuint> *boundTextureUnits =
2939         &mState.mSamplerBindings[samplerIndex].boundTextureUnits;
2940 
2941     std::copy(v, v + clampedCount, boundTextureUnits->begin() + locationInfo.arrayIndex);
2942 
2943     // Invalidate the validation cache.
2944     mCachedValidateSamplersResult.reset();
2945 }
2946 
2947 template <typename T>
clampUniformCount(const VariableLocation & locationInfo,GLsizei count,int vectorSize,const T * v)2948 GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
2949                                    GLsizei count,
2950                                    int vectorSize,
2951                                    const T *v)
2952 {
2953     if (count == 1)
2954         return 1;
2955 
2956     const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
2957 
2958     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
2959     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
2960     unsigned int remainingElements =
2961         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
2962     GLsizei maxElementCount =
2963         static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
2964 
2965     if (count * vectorSize > maxElementCount)
2966     {
2967         return maxElementCount / vectorSize;
2968     }
2969 
2970     return count;
2971 }
2972 
2973 template <size_t cols, size_t rows, typename T>
clampMatrixUniformCount(GLint location,GLsizei count,GLboolean transpose,const T * v)2974 GLsizei Program::clampMatrixUniformCount(GLint location,
2975                                          GLsizei count,
2976                                          GLboolean transpose,
2977                                          const T *v)
2978 {
2979     const VariableLocation &locationInfo = mState.mUniformLocations[location];
2980 
2981     if (!transpose)
2982     {
2983         return clampUniformCount(locationInfo, count, cols * rows, v);
2984     }
2985 
2986     const LinkedUniform &linkedUniform = mState.mUniforms[locationInfo.index];
2987 
2988     // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
2989     // element index used, as reported by GetActiveUniform, will be ignored by the GL."
2990     unsigned int remainingElements =
2991         linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
2992     return std::min(count, static_cast<GLsizei>(remainingElements));
2993 }
2994 
2995 // Driver differences mean that doing the uniform value cast ourselves gives consistent results.
2996 // EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
2997 template <typename DestT>
getUniformInternal(const Context * context,DestT * dataOut,GLint location,GLenum nativeType,int components) const2998 void Program::getUniformInternal(const Context *context,
2999                                  DestT *dataOut,
3000                                  GLint location,
3001                                  GLenum nativeType,
3002                                  int components) const
3003 {
3004     switch (nativeType)
3005     {
3006         case GL_BOOL:
3007         {
3008             GLint tempValue[16] = {0};
3009             mProgram->getUniformiv(context, location, tempValue);
3010             UniformStateQueryCastLoop<GLboolean>(
3011                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3012             break;
3013         }
3014         case GL_INT:
3015         {
3016             GLint tempValue[16] = {0};
3017             mProgram->getUniformiv(context, location, tempValue);
3018             UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3019                                              components);
3020             break;
3021         }
3022         case GL_UNSIGNED_INT:
3023         {
3024             GLuint tempValue[16] = {0};
3025             mProgram->getUniformuiv(context, location, tempValue);
3026             UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
3027                                               components);
3028             break;
3029         }
3030         case GL_FLOAT:
3031         {
3032             GLfloat tempValue[16] = {0};
3033             mProgram->getUniformfv(context, location, tempValue);
3034             UniformStateQueryCastLoop<GLfloat>(
3035                 dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
3036             break;
3037         }
3038         default:
3039             UNREACHABLE();
3040             break;
3041     }
3042 }
3043 
samplesFromTexture(const gl::State & state,GLuint textureID) const3044 bool Program::samplesFromTexture(const gl::State &state, GLuint textureID) const
3045 {
3046     // Must be called after samplers are validated.
3047     ASSERT(mCachedValidateSamplersResult.valid() && mCachedValidateSamplersResult.value());
3048 
3049     for (const auto &binding : mState.mSamplerBindings)
3050     {
3051         GLenum textureType = binding.textureType;
3052         for (const auto &unit : binding.boundTextureUnits)
3053         {
3054             GLenum programTextureID = state.getSamplerTextureId(unit, textureType);
3055             if (programTextureID == textureID)
3056             {
3057                 // TODO(jmadill): Check for appropriate overlap.
3058                 return true;
3059             }
3060         }
3061     }
3062 
3063     return false;
3064 }
3065 
3066 }  // namespace gl
3067