• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "precompiled.h"
2 //
3 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7 
8 // Program.cpp: Implements the gl::Program class. Implements GL program objects
9 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
10 
11 #include "libGLESv2/BinaryStream.h"
12 #include "libGLESv2/ProgramBinary.h"
13 #include "libGLESv2/renderer/ShaderExecutable.h"
14 
15 #include "common/debug.h"
16 #include "common/version.h"
17 #include "common/utilities.h"
18 
19 #include "libGLESv2/main.h"
20 #include "libGLESv2/Shader.h"
21 #include "libGLESv2/Program.h"
22 #include "libGLESv2/renderer/Renderer.h"
23 #include "libGLESv2/renderer/VertexDataManager.h"
24 #include "libGLESv2/Context.h"
25 #include "libGLESv2/Buffer.h"
26 #include "libGLESv2/DynamicHLSL.h"
27 #include "common/blocklayout.h"
28 
29 #undef near
30 #undef far
31 
32 namespace gl
33 {
34 
35 namespace
36 {
37 
ParseAndStripArrayIndex(std::string * name)38 unsigned int ParseAndStripArrayIndex(std::string* name)
39 {
40     unsigned int subscript = GL_INVALID_INDEX;
41 
42     // Strip any trailing array operator and retrieve the subscript
43     size_t open = name->find_last_of('[');
44     size_t close = name->find_last_of(']');
45     if (open != std::string::npos && close == name->length() - 1)
46     {
47         subscript = atoi(name->substr(open + 1).c_str());
48         name->erase(open);
49     }
50 
51     return subscript;
52 }
53 
GetInputLayoutFromShader(const std::vector<gl::Attribute> & shaderAttributes,VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])54 void GetInputLayoutFromShader(const std::vector<gl::Attribute> &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
55 {
56     size_t layoutIndex = 0;
57     for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
58     {
59         ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS);
60 
61         const gl::Attribute &shaderAttr = shaderAttributes[attributeIndex];
62 
63         if (shaderAttr.type != GL_NONE)
64         {
65             GLenum transposedType = TransposeMatrixType(shaderAttr.type);
66 
67             for (size_t rowIndex = 0; static_cast<int>(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++)
68             {
69                 VertexFormat *defaultFormat = &inputLayout[layoutIndex];
70 
71                 defaultFormat->mType = UniformComponentType(transposedType);
72                 defaultFormat->mNormalized = false;
73                 defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool
74                 defaultFormat->mComponents = VariableColumnCount(transposedType);
75             }
76         }
77     }
78 }
79 
80 }
81 
VariableLocation(const std::string & name,unsigned int element,unsigned int index)82 VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
83     : name(name), element(element), index(index)
84 {
85 }
86 
VertexExecutable(rx::Renderer * const renderer,const VertexFormat inputLayout[],const GLenum signature[],rx::ShaderExecutable * shaderExecutable)87 ProgramBinary::VertexExecutable::VertexExecutable(rx::Renderer *const renderer,
88                                                   const VertexFormat inputLayout[],
89                                                   const GLenum signature[],
90                                                   rx::ShaderExecutable *shaderExecutable)
91     : mShaderExecutable(shaderExecutable)
92 {
93     for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
94     {
95         mInputs[attributeIndex] = inputLayout[attributeIndex];
96         mSignature[attributeIndex] = signature[attributeIndex];
97     }
98 }
99 
~VertexExecutable()100 ProgramBinary::VertexExecutable::~VertexExecutable()
101 {
102     delete mShaderExecutable;
103 }
104 
matchesSignature(const GLenum signature[]) const105 bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const
106 {
107     for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
108     {
109         if (mSignature[attributeIndex] != signature[attributeIndex])
110         {
111             return false;
112         }
113     }
114 
115     return true;
116 }
117 
LinkedVarying()118 LinkedVarying::LinkedVarying()
119 {
120 }
121 
LinkedVarying(const std::string & name,GLenum type,GLsizei size,const std::string & semanticName,unsigned int semanticIndex,unsigned int semanticIndexCount)122 LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
123                              unsigned int semanticIndex, unsigned int semanticIndexCount)
124     : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount)
125 {
126 }
127 
128 unsigned int ProgramBinary::mCurrentSerial = 1;
129 
ProgramBinary(rx::Renderer * renderer)130 ProgramBinary::ProgramBinary(rx::Renderer *renderer)
131     : RefCountObject(0),
132       mRenderer(renderer),
133       mDynamicHLSL(NULL),
134       mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE),
135       mPixelExecutable(NULL),
136       mGeometryExecutable(NULL),
137       mUsedVertexSamplerRange(0),
138       mUsedPixelSamplerRange(0),
139       mUsesPointSize(false),
140       mShaderVersion(100),
141       mVertexUniformStorage(NULL),
142       mFragmentUniformStorage(NULL),
143       mValidated(false),
144       mSerial(issueSerial())
145 {
146     for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
147     {
148         mSemanticIndex[index] = -1;
149     }
150 
151     for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
152     {
153         mSamplersPS[index].active = false;
154     }
155 
156     for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
157     {
158         mSamplersVS[index].active = false;
159     }
160 
161     mDynamicHLSL = new DynamicHLSL(renderer);
162 }
163 
~ProgramBinary()164 ProgramBinary::~ProgramBinary()
165 {
166     while (!mVertexExecutables.empty())
167     {
168         delete mVertexExecutables.back();
169         mVertexExecutables.pop_back();
170     }
171 
172     SafeDelete(mGeometryExecutable);
173     SafeDelete(mPixelExecutable);
174 
175     while (!mUniforms.empty())
176     {
177         delete mUniforms.back();
178         mUniforms.pop_back();
179     }
180 
181     while (!mUniformBlocks.empty())
182     {
183         delete mUniformBlocks.back();
184         mUniformBlocks.pop_back();
185     }
186 
187     SafeDelete(mVertexUniformStorage);
188     SafeDelete(mFragmentUniformStorage);
189     SafeDelete(mDynamicHLSL);
190 }
191 
getSerial() const192 unsigned int ProgramBinary::getSerial() const
193 {
194     return mSerial;
195 }
196 
getShaderVersion() const197 int ProgramBinary::getShaderVersion() const
198 {
199     return mShaderVersion;
200 }
201 
issueSerial()202 unsigned int ProgramBinary::issueSerial()
203 {
204     return mCurrentSerial++;
205 }
206 
getPixelExecutable() const207 rx::ShaderExecutable *ProgramBinary::getPixelExecutable() const
208 {
209     return mPixelExecutable;
210 }
211 
getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])212 rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS])
213 {
214     GLenum signature[MAX_VERTEX_ATTRIBS];
215     mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
216 
217     for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
218     {
219         if (mVertexExecutables[executableIndex]->matchesSignature(signature))
220         {
221             return mVertexExecutables[executableIndex]->shaderExecutable();
222         }
223     }
224 
225     // Generate new dynamic layout with attribute conversions
226     const std::string &layoutHLSL = mDynamicHLSL->generateInputLayoutHLSL(inputLayout, mShaderAttributes);
227 
228     // Generate new shader source by replacing the attributes stub with the defined input layout
229     std::string vertexHLSL = mVertexHLSL;
230     size_t insertPos = vertexHLSL.find(DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING);
231     vertexHLSL.replace(insertPos, DynamicHLSL::VERTEX_ATTRIBUTE_STUB_STRING.length(), layoutHLSL);
232 
233     // Generate new vertex executable
234     InfoLog tempInfoLog;
235     rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, vertexHLSL.c_str(),
236                                                                             rx::SHADER_VERTEX,
237                                                                             mTransformFeedbackLinkedVaryings,
238                                                                             (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
239                                                                             mVertexWorkarounds);
240 
241     if (!vertexExecutable)
242     {
243         std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
244         tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
245         ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
246     }
247     else
248     {
249         mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, signature, vertexExecutable));
250     }
251 
252     return vertexExecutable;
253 }
254 
getGeometryExecutable() const255 rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const
256 {
257     return mGeometryExecutable;
258 }
259 
getAttributeLocation(const char * name)260 GLuint ProgramBinary::getAttributeLocation(const char *name)
261 {
262     if (name)
263     {
264         for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
265         {
266             if (mLinkedAttribute[index].name == std::string(name))
267             {
268                 return index;
269             }
270         }
271     }
272 
273     return -1;
274 }
275 
getSemanticIndex(int attributeIndex)276 int ProgramBinary::getSemanticIndex(int attributeIndex)
277 {
278     ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
279 
280     return mSemanticIndex[attributeIndex];
281 }
282 
283 // Returns one more than the highest sampler index used.
getUsedSamplerRange(SamplerType type)284 GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
285 {
286     switch (type)
287     {
288       case SAMPLER_PIXEL:
289         return mUsedPixelSamplerRange;
290       case SAMPLER_VERTEX:
291         return mUsedVertexSamplerRange;
292       default:
293         UNREACHABLE();
294         return 0;
295     }
296 }
297 
usesPointSize() const298 bool ProgramBinary::usesPointSize() const
299 {
300     return mUsesPointSize;
301 }
302 
usesPointSpriteEmulation() const303 bool ProgramBinary::usesPointSpriteEmulation() const
304 {
305     return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
306 }
307 
usesGeometryShader() const308 bool ProgramBinary::usesGeometryShader() const
309 {
310     return usesPointSpriteEmulation();
311 }
312 
313 // Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
314 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
getSamplerMapping(SamplerType type,unsigned int samplerIndex)315 GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
316 {
317     GLint logicalTextureUnit = -1;
318 
319     switch (type)
320     {
321       case SAMPLER_PIXEL:
322         ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
323 
324         if (mSamplersPS[samplerIndex].active)
325         {
326             logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
327         }
328         break;
329       case SAMPLER_VERTEX:
330         ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
331 
332         if (mSamplersVS[samplerIndex].active)
333         {
334             logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
335         }
336         break;
337       default: UNREACHABLE();
338     }
339 
340     if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits())
341     {
342         return logicalTextureUnit;
343     }
344 
345     return -1;
346 }
347 
348 // Returns the texture type for a given Direct3D 9 sampler type and
349 // index (0-15 for the pixel shader and 0-3 for the vertex shader).
getSamplerTextureType(SamplerType type,unsigned int samplerIndex)350 TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
351 {
352     switch (type)
353     {
354       case SAMPLER_PIXEL:
355         ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
356         ASSERT(mSamplersPS[samplerIndex].active);
357         return mSamplersPS[samplerIndex].textureType;
358       case SAMPLER_VERTEX:
359         ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
360         ASSERT(mSamplersVS[samplerIndex].active);
361         return mSamplersVS[samplerIndex].textureType;
362       default: UNREACHABLE();
363     }
364 
365     return TEXTURE_2D;
366 }
367 
getUniformLocation(std::string name)368 GLint ProgramBinary::getUniformLocation(std::string name)
369 {
370     unsigned int subscript = ParseAndStripArrayIndex(&name);
371 
372     unsigned int numUniforms = mUniformIndex.size();
373     for (unsigned int location = 0; location < numUniforms; location++)
374     {
375         if (mUniformIndex[location].name == name)
376         {
377             const int index = mUniformIndex[location].index;
378             const bool isArray = mUniforms[index]->isArray();
379 
380             if ((isArray && mUniformIndex[location].element == subscript) ||
381                 (subscript == GL_INVALID_INDEX))
382             {
383                 return location;
384             }
385         }
386     }
387 
388     return -1;
389 }
390 
getUniformIndex(std::string name)391 GLuint ProgramBinary::getUniformIndex(std::string name)
392 {
393     unsigned int subscript = ParseAndStripArrayIndex(&name);
394 
395     // The app is not allowed to specify array indices other than 0 for arrays of basic types
396     if (subscript != 0 && subscript != GL_INVALID_INDEX)
397     {
398         return GL_INVALID_INDEX;
399     }
400 
401     unsigned int numUniforms = mUniforms.size();
402     for (unsigned int index = 0; index < numUniforms; index++)
403     {
404         if (mUniforms[index]->name == name)
405         {
406             if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
407             {
408                 return index;
409             }
410         }
411     }
412 
413     return GL_INVALID_INDEX;
414 }
415 
getUniformBlockIndex(std::string name)416 GLuint ProgramBinary::getUniformBlockIndex(std::string name)
417 {
418     unsigned int subscript = ParseAndStripArrayIndex(&name);
419 
420     unsigned int numUniformBlocks = mUniformBlocks.size();
421     for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
422     {
423         const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex];
424         if (uniformBlock.name == name)
425         {
426             const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
427             if (subscript == uniformBlock.elementIndex || arrayElementZero)
428             {
429                 return blockIndex;
430             }
431         }
432     }
433 
434     return GL_INVALID_INDEX;
435 }
436 
getUniformBlockByIndex(GLuint blockIndex)437 UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex)
438 {
439     ASSERT(blockIndex < mUniformBlocks.size());
440     return mUniformBlocks[blockIndex];
441 }
442 
getFragDataLocation(const char * name) const443 GLint ProgramBinary::getFragDataLocation(const char *name) const
444 {
445     std::string baseName(name);
446     unsigned int arrayIndex;
447     arrayIndex = ParseAndStripArrayIndex(&baseName);
448 
449     for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
450     {
451         const VariableLocation &outputVariable = locationIt->second;
452 
453         if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
454         {
455             return static_cast<GLint>(locationIt->first);
456         }
457     }
458 
459     return -1;
460 }
461 
getTransformFeedbackVaryingCount() const462 size_t ProgramBinary::getTransformFeedbackVaryingCount() const
463 {
464     return mTransformFeedbackLinkedVaryings.size();
465 }
466 
getTransformFeedbackVarying(size_t idx) const467 const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
468 {
469     return mTransformFeedbackLinkedVaryings[idx];
470 }
471 
getTransformFeedbackBufferMode() const472 GLenum ProgramBinary::getTransformFeedbackBufferMode() const
473 {
474     return mTransformFeedbackBufferMode;
475 }
476 
477 template <typename T>
SetIfDirty(T * dest,const T & source,bool * dirtyFlag)478 static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag)
479 {
480     ASSERT(dest != NULL);
481     ASSERT(dirtyFlag != NULL);
482 
483     *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
484     *dest = source;
485 }
486 
487 template <typename T>
setUniform(GLint location,GLsizei count,const T * v,GLenum targetUniformType)488 void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType)
489 {
490     const int components = UniformComponentCount(targetUniformType);
491     const GLenum targetBoolType = UniformBoolVectorType(targetUniformType);
492 
493     LinkedUniform *targetUniform = getUniformByLocation(location);
494 
495     int elementCount = targetUniform->elementCount();
496 
497     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
498 
499     if (targetUniform->type == targetUniformType)
500     {
501         T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4;
502 
503         for (int i = 0; i < count; i++)
504         {
505             for (int c = 0; c < components; c++)
506             {
507                 SetIfDirty(target + c, v[c], &targetUniform->dirty);
508             }
509             for (int c = components; c < 4; c++)
510             {
511                 SetIfDirty(target + c, T(0), &targetUniform->dirty);
512             }
513             target += 4;
514             v += components;
515         }
516     }
517     else if (targetUniform->type == targetBoolType)
518     {
519         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
520 
521         for (int i = 0; i < count; i++)
522         {
523             for (int c = 0; c < components; c++)
524             {
525                 SetIfDirty(boolParams + c, (v[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
526             }
527             for (int c = components; c < 4; c++)
528             {
529                 SetIfDirty(boolParams + c, GL_FALSE, &targetUniform->dirty);
530             }
531             boolParams += 4;
532             v += components;
533         }
534     }
535     else UNREACHABLE();
536 }
537 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)538 void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
539 {
540     setUniform(location, count, v, GL_FLOAT);
541 }
542 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)543 void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
544 {
545     setUniform(location, count, v, GL_FLOAT_VEC2);
546 }
547 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)548 void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
549 {
550     setUniform(location, count, v, GL_FLOAT_VEC3);
551 }
552 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)553 void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
554 {
555     setUniform(location, count, v, GL_FLOAT_VEC4);
556 }
557 
558 template<typename T>
transposeMatrix(T * target,const GLfloat * value,int targetWidth,int targetHeight,int srcWidth,int srcHeight)559 bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
560 {
561     bool dirty = false;
562     int copyWidth = std::min(targetHeight, srcWidth);
563     int copyHeight = std::min(targetWidth, srcHeight);
564 
565     for (int x = 0; x < copyWidth; x++)
566     {
567         for (int y = 0; y < copyHeight; y++)
568         {
569             SetIfDirty(target + (x * targetWidth + y), static_cast<T>(value[y * srcWidth + x]), &dirty);
570         }
571     }
572     // clear unfilled right side
573     for (int y = 0; y < copyWidth; y++)
574     {
575         for (int x = copyHeight; x < targetWidth; x++)
576         {
577             SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
578         }
579     }
580     // clear unfilled bottom.
581     for (int y = copyWidth; y < targetHeight; y++)
582     {
583         for (int x = 0; x < targetWidth; x++)
584         {
585             SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
586         }
587     }
588 
589     return dirty;
590 }
591 
592 template<typename T>
expandMatrix(T * target,const GLfloat * value,int targetWidth,int targetHeight,int srcWidth,int srcHeight)593 bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight)
594 {
595     bool dirty = false;
596     int copyWidth = std::min(targetWidth, srcWidth);
597     int copyHeight = std::min(targetHeight, srcHeight);
598 
599     for (int y = 0; y < copyHeight; y++)
600     {
601         for (int x = 0; x < copyWidth; x++)
602         {
603             SetIfDirty(target + (y * targetWidth + x), static_cast<T>(value[y * srcWidth + x]), &dirty);
604         }
605     }
606     // clear unfilled right side
607     for (int y = 0; y < copyHeight; y++)
608     {
609         for (int x = copyWidth; x < targetWidth; x++)
610         {
611             SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
612         }
613     }
614     // clear unfilled bottom.
615     for (int y = copyHeight; y < targetHeight; y++)
616     {
617         for (int x = 0; x < targetWidth; x++)
618         {
619             SetIfDirty(target + (y * targetWidth + x), static_cast<T>(0), &dirty);
620         }
621     }
622 
623     return dirty;
624 }
625 
626 template <int cols, int rows>
setUniformMatrixfv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value,GLenum targetUniformType)627 void ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType)
628 {
629     LinkedUniform *targetUniform = getUniformByLocation(location);
630 
631     int elementCount = targetUniform->elementCount();
632 
633     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
634     const unsigned int targetMatrixStride = (4 * rows);
635     GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride);
636 
637     for (int i = 0; i < count; i++)
638     {
639         // Internally store matrices as transposed versions to accomodate HLSL matrix indexing
640         if (transpose == GL_FALSE)
641         {
642             targetUniform->dirty = transposeMatrix<GLfloat>(target, value, 4, rows, rows, cols) || targetUniform->dirty;
643         }
644         else
645         {
646             targetUniform->dirty = expandMatrix<GLfloat>(target, value, 4, rows, cols, rows) || targetUniform->dirty;
647         }
648         target += targetMatrixStride;
649         value += cols * rows;
650     }
651 }
652 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)653 void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
654 {
655     setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2);
656 }
657 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)658 void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
659 {
660     setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3);
661 }
662 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)663 void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
664 {
665     setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4);
666 }
667 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)668 void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
669 {
670     setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3);
671 }
672 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)673 void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
674 {
675     setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2);
676 }
677 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)678 void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
679 {
680     setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4);
681 }
682 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)683 void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
684 {
685     setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2);
686 }
687 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)688 void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
689 {
690     setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4);
691 }
692 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)693 void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
694 {
695     setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3);
696 }
697 
setUniform1iv(GLint location,GLsizei count,const GLint * v)698 void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
699 {
700     LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
701 
702     int elementCount = targetUniform->elementCount();
703 
704     count = std::min(elementCount - (int)mUniformIndex[location].element, count);
705 
706     if (targetUniform->type == GL_INT || IsSampler(targetUniform->type))
707     {
708         GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
709 
710         for (int i = 0; i < count; i++)
711         {
712             SetIfDirty(target + 0, v[0], &targetUniform->dirty);
713             SetIfDirty(target + 1, 0, &targetUniform->dirty);
714             SetIfDirty(target + 2, 0, &targetUniform->dirty);
715             SetIfDirty(target + 3, 0, &targetUniform->dirty);
716             target += 4;
717             v += 1;
718         }
719     }
720     else if (targetUniform->type == GL_BOOL)
721     {
722         GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
723 
724         for (int i = 0; i < count; i++)
725         {
726             SetIfDirty(boolParams + 0, (v[0] == 0) ? GL_FALSE : GL_TRUE, &targetUniform->dirty);
727             SetIfDirty(boolParams + 1, GL_FALSE, &targetUniform->dirty);
728             SetIfDirty(boolParams + 2, GL_FALSE, &targetUniform->dirty);
729             SetIfDirty(boolParams + 3, GL_FALSE, &targetUniform->dirty);
730             boolParams += 4;
731             v += 1;
732         }
733     }
734     else UNREACHABLE();
735 }
736 
setUniform2iv(GLint location,GLsizei count,const GLint * v)737 void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
738 {
739     setUniform(location, count, v, GL_INT_VEC2);
740 }
741 
setUniform3iv(GLint location,GLsizei count,const GLint * v)742 void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
743 {
744     setUniform(location, count, v, GL_INT_VEC3);
745 }
746 
setUniform4iv(GLint location,GLsizei count,const GLint * v)747 void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
748 {
749     setUniform(location, count, v, GL_INT_VEC4);
750 }
751 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)752 void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
753 {
754     setUniform(location, count, v, GL_UNSIGNED_INT);
755 }
756 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)757 void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
758 {
759     setUniform(location, count, v, GL_UNSIGNED_INT_VEC2);
760 }
761 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)762 void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
763 {
764     setUniform(location, count, v, GL_UNSIGNED_INT_VEC3);
765 }
766 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)767 void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
768 {
769     setUniform(location, count, v, GL_UNSIGNED_INT_VEC4);
770 }
771 
772 template <typename T>
getUniformv(GLint location,GLsizei * bufSize,T * params,GLenum uniformType)773 bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType)
774 {
775     LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index];
776 
777     // sized queries -- ensure the provided buffer is large enough
778     if (bufSize)
779     {
780         int requiredBytes = UniformExternalSize(targetUniform->type);
781         if (*bufSize < requiredBytes)
782         {
783             return false;
784         }
785     }
786 
787     if (IsMatrixType(targetUniform->type))
788     {
789         const int rows = VariableRowCount(targetUniform->type);
790         const int cols = VariableColumnCount(targetUniform->type);
791         transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows);
792     }
793     else if (uniformType == UniformComponentType(targetUniform->type))
794     {
795         unsigned int size = UniformComponentCount(targetUniform->type);
796         memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T),
797                 size * sizeof(T));
798     }
799     else
800     {
801         unsigned int size = UniformComponentCount(targetUniform->type);
802         switch (UniformComponentType(targetUniform->type))
803         {
804           case GL_BOOL:
805             {
806                 GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
807 
808                 for (unsigned int i = 0; i < size; i++)
809                 {
810                     params[i] = (boolParams[i] == GL_FALSE) ? static_cast<T>(0) : static_cast<T>(1);
811                 }
812             }
813             break;
814 
815           case GL_FLOAT:
816             {
817                 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
818 
819                 for (unsigned int i = 0; i < size; i++)
820                 {
821                     params[i] = static_cast<T>(floatParams[i]);
822                 }
823             }
824             break;
825 
826           case GL_INT:
827             {
828                 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4;
829 
830                 for (unsigned int i = 0; i < size; i++)
831                 {
832                     params[i] = static_cast<T>(intParams[i]);
833                 }
834             }
835             break;
836 
837           case GL_UNSIGNED_INT:
838             {
839                 GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4;
840 
841                 for (unsigned int i = 0; i < size; i++)
842                 {
843                     params[i] = static_cast<T>(uintParams[i]);
844                 }
845             }
846             break;
847 
848           default: UNREACHABLE();
849         }
850     }
851 
852     return true;
853 }
854 
getUniformfv(GLint location,GLsizei * bufSize,GLfloat * params)855 bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
856 {
857     return getUniformv(location, bufSize, params, GL_FLOAT);
858 }
859 
getUniformiv(GLint location,GLsizei * bufSize,GLint * params)860 bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
861 {
862     return getUniformv(location, bufSize, params, GL_INT);
863 }
864 
getUniformuiv(GLint location,GLsizei * bufSize,GLuint * params)865 bool ProgramBinary::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params)
866 {
867     return getUniformv(location, bufSize, params, GL_UNSIGNED_INT);
868 }
869 
dirtyAllUniforms()870 void ProgramBinary::dirtyAllUniforms()
871 {
872     unsigned int numUniforms = mUniforms.size();
873     for (unsigned int index = 0; index < numUniforms; index++)
874     {
875         mUniforms[index]->dirty = true;
876     }
877 }
878 
879 // Applies all the uniforms set for this program object to the renderer
applyUniforms()880 void ProgramBinary::applyUniforms()
881 {
882     // Retrieve sampler uniform values
883     for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
884     {
885         LinkedUniform *targetUniform = mUniforms[uniformIndex];
886 
887         if (targetUniform->dirty)
888         {
889             if (IsSampler(targetUniform->type))
890             {
891                 int count = targetUniform->elementCount();
892                 GLint (*v)[4] = (GLint(*)[4])targetUniform->data;
893 
894                 if (targetUniform->isReferencedByFragmentShader())
895                 {
896                     unsigned int firstIndex = targetUniform->psRegisterIndex;
897 
898                     for (int i = 0; i < count; i++)
899                     {
900                         unsigned int samplerIndex = firstIndex + i;
901 
902                         if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
903                         {
904                             ASSERT(mSamplersPS[samplerIndex].active);
905                             mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0];
906                         }
907                     }
908                 }
909 
910                 if (targetUniform->isReferencedByVertexShader())
911                 {
912                     unsigned int firstIndex = targetUniform->vsRegisterIndex;
913 
914                     for (int i = 0; i < count; i++)
915                     {
916                         unsigned int samplerIndex = firstIndex + i;
917 
918                         if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
919                         {
920                             ASSERT(mSamplersVS[samplerIndex].active);
921                             mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0];
922                         }
923                     }
924                 }
925             }
926         }
927     }
928 
929     mRenderer->applyUniforms(*this);
930 
931     for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
932     {
933         mUniforms[uniformIndex]->dirty = false;
934     }
935 }
936 
applyUniformBuffers(const std::vector<gl::Buffer * > boundBuffers)937 bool ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers)
938 {
939     const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
940     const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
941 
942     const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
943     const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
944 
945     ASSERT(boundBuffers.size() == mUniformBlocks.size());
946 
947     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
948     {
949         gl::UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex);
950         gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
951 
952         ASSERT(uniformBlock && uniformBuffer);
953 
954         if (uniformBuffer->size() < uniformBlock->dataSize)
955         {
956             // undefined behaviour
957             return false;
958         }
959 
960         ASSERT(uniformBlock->isReferencedByVertexShader() || uniformBlock->isReferencedByFragmentShader());
961 
962         if (uniformBlock->isReferencedByVertexShader())
963         {
964             unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
965             ASSERT(vertexUniformBuffers[registerIndex] == NULL);
966             ASSERT(registerIndex < mRenderer->getMaxVertexShaderUniformBuffers());
967             vertexUniformBuffers[registerIndex] = uniformBuffer;
968         }
969 
970         if (uniformBlock->isReferencedByFragmentShader())
971         {
972             unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
973             ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
974             ASSERT(registerIndex < mRenderer->getMaxFragmentShaderUniformBuffers());
975             fragmentUniformBuffers[registerIndex] = uniformBuffer;
976         }
977     }
978 
979     return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
980 }
981 
linkVaryings(InfoLog & infoLog,FragmentShader * fragmentShader,VertexShader * vertexShader)982 bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader)
983 {
984     std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
985     std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
986 
987     for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
988     {
989         PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
990         bool matched = false;
991 
992         for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
993         {
994             PackedVarying *output = &vertexVaryings[vertVaryingIndex];
995             if (output->name == input->name)
996             {
997                 if (!linkValidateVariables(infoLog, output->name, *input, *output))
998                 {
999                     return false;
1000                 }
1001 
1002                 output->registerIndex = input->registerIndex;
1003 
1004                 matched = true;
1005                 break;
1006             }
1007         }
1008 
1009         if (!matched)
1010         {
1011             infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
1012             return false;
1013         }
1014     }
1015 
1016     return true;
1017 }
1018 
load(InfoLog & infoLog,const void * binary,GLsizei length)1019 bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length)
1020 {
1021 #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
1022     return false;
1023 #else
1024     BinaryInputStream stream(binary, length);
1025 
1026     int format = stream.readInt<int>();
1027     if (format != GL_PROGRAM_BINARY_ANGLE)
1028     {
1029         infoLog.append("Invalid program binary format.");
1030         return false;
1031     }
1032 
1033     int majorVersion = stream.readInt<int>();
1034     int minorVersion = stream.readInt<int>();
1035     if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
1036     {
1037         infoLog.append("Invalid program binary version.");
1038         return false;
1039     }
1040 
1041     unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
1042     stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
1043     if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
1044     {
1045         infoLog.append("Invalid program binary version.");
1046         return false;
1047     }
1048 
1049     int compileFlags = stream.readInt<int>();
1050     if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
1051     {
1052         infoLog.append("Mismatched compilation flags.");
1053         return false;
1054     }
1055 
1056     for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1057     {
1058         stream.readInt(&mLinkedAttribute[i].type);
1059         stream.readString(&mLinkedAttribute[i].name);
1060         stream.readInt(&mShaderAttributes[i].type);
1061         stream.readString(&mShaderAttributes[i].name);
1062         stream.readInt(&mSemanticIndex[i]);
1063     }
1064 
1065     initAttributesByLayout();
1066 
1067     for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1068     {
1069         stream.readBool(&mSamplersPS[i].active);
1070         stream.readInt(&mSamplersPS[i].logicalTextureUnit);
1071         stream.readInt(&mSamplersPS[i].textureType);
1072     }
1073 
1074     for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
1075     {
1076         stream.readBool(&mSamplersVS[i].active);
1077         stream.readInt(&mSamplersVS[i].logicalTextureUnit);
1078         stream.readInt(&mSamplersVS[i].textureType);
1079     }
1080 
1081     stream.readInt(&mUsedVertexSamplerRange);
1082     stream.readInt(&mUsedPixelSamplerRange);
1083     stream.readBool(&mUsesPointSize);
1084     stream.readInt(&mShaderVersion);
1085 
1086     const unsigned int uniformCount = stream.readInt<unsigned int>();
1087     if (stream.error())
1088     {
1089         infoLog.append("Invalid program binary.");
1090         return false;
1091     }
1092 
1093     mUniforms.resize(uniformCount);
1094     for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
1095     {
1096         GLenum type = stream.readInt<GLenum>();
1097         GLenum precision = stream.readInt<GLenum>();
1098         std::string name = stream.readString();
1099         unsigned int arraySize = stream.readInt<unsigned int>();
1100         int blockIndex = stream.readInt<int>();
1101 
1102         int offset = stream.readInt<int>();
1103         int arrayStride = stream.readInt<int>();
1104         int matrixStride = stream.readInt<int>();
1105         bool isRowMajorMatrix = stream.readBool();
1106 
1107         const gl::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix);
1108 
1109         LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo);
1110 
1111         stream.readInt(&uniform->psRegisterIndex);
1112         stream.readInt(&uniform->vsRegisterIndex);
1113         stream.readInt(&uniform->registerCount);
1114         stream.readInt(&uniform->registerElement);
1115 
1116         mUniforms[uniformIndex] = uniform;
1117     }
1118 
1119     unsigned int uniformBlockCount = stream.readInt<unsigned int>();
1120     if (stream.error())
1121     {
1122         infoLog.append("Invalid program binary.");
1123         return false;
1124     }
1125 
1126     mUniformBlocks.resize(uniformBlockCount);
1127     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
1128     {
1129         std::string name = stream.readString();
1130         unsigned int elementIndex = stream.readInt<unsigned int>();
1131         unsigned int dataSize = stream.readInt<unsigned int>();
1132 
1133         UniformBlock *uniformBlock = new UniformBlock(name, elementIndex, dataSize);
1134 
1135         stream.readInt(&uniformBlock->psRegisterIndex);
1136         stream.readInt(&uniformBlock->vsRegisterIndex);
1137 
1138         unsigned int numMembers = stream.readInt<unsigned int>();
1139         uniformBlock->memberUniformIndexes.resize(numMembers);
1140         for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
1141         {
1142             stream.readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]);
1143         }
1144 
1145         mUniformBlocks[uniformBlockIndex] = uniformBlock;
1146     }
1147 
1148     const unsigned int uniformIndexCount = stream.readInt<unsigned int>();
1149     if (stream.error())
1150     {
1151         infoLog.append("Invalid program binary.");
1152         return false;
1153     }
1154 
1155     mUniformIndex.resize(uniformIndexCount);
1156     for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++)
1157     {
1158         stream.readString(&mUniformIndex[uniformIndexIndex].name);
1159         stream.readInt(&mUniformIndex[uniformIndexIndex].element);
1160         stream.readInt(&mUniformIndex[uniformIndexIndex].index);
1161     }
1162 
1163     stream.readInt(&mTransformFeedbackBufferMode);
1164     const unsigned int transformFeedbackVaryingCount = stream.readInt<unsigned int>();
1165     mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount);
1166     for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++)
1167     {
1168         LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex];
1169 
1170         stream.readString(&varying.name);
1171         stream.readInt(&varying.type);
1172         stream.readInt(&varying.size);
1173         stream.readString(&varying.semanticName);
1174         stream.readInt(&varying.semanticIndex);
1175         stream.readInt(&varying.semanticIndexCount);
1176     }
1177 
1178     stream.readString(&mVertexHLSL);
1179 
1180     stream.readInt(&mVertexWorkarounds);
1181 
1182     const unsigned int vertexShaderCount = stream.readInt<unsigned int>();
1183 
1184     for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
1185     {
1186         VertexFormat inputLayout[MAX_VERTEX_ATTRIBS];
1187 
1188         for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++)
1189         {
1190             VertexFormat *vertexInput = &inputLayout[inputIndex];
1191             stream.readInt(&vertexInput->mType);
1192             stream.readInt(&vertexInput->mNormalized);
1193             stream.readInt(&vertexInput->mComponents);
1194             stream.readBool(&vertexInput->mPureInteger);
1195         }
1196 
1197         unsigned int vertexShaderSize = stream.readInt<unsigned int>();
1198 
1199         const char *vertexShaderFunction = (const char*) binary + stream.offset();
1200 
1201         rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(vertexShaderFunction),
1202                                                                            vertexShaderSize, rx::SHADER_VERTEX,
1203                                                                            mTransformFeedbackLinkedVaryings,
1204                                                                            (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
1205         if (!shaderExecutable)
1206         {
1207             infoLog.append("Could not create vertex shader.");
1208             return false;
1209         }
1210 
1211         // generated converted input layout
1212         GLenum signature[MAX_VERTEX_ATTRIBS];
1213         mDynamicHLSL->getInputLayoutSignature(inputLayout, signature);
1214 
1215         // add new binary
1216         mVertexExecutables.push_back(new VertexExecutable(mRenderer, inputLayout, signature, shaderExecutable));
1217 
1218         stream.skip(vertexShaderSize);
1219     }
1220 
1221     unsigned int pixelShaderSize = stream.readInt<unsigned int>();
1222 
1223     const char *pixelShaderFunction = (const char*) binary + stream.offset();
1224     mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(pixelShaderFunction),
1225                                                  pixelShaderSize, rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings,
1226                                                  (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
1227     if (!mPixelExecutable)
1228     {
1229         infoLog.append("Could not create pixel shader.");
1230         return false;
1231     }
1232     stream.skip(pixelShaderSize);
1233 
1234     unsigned int geometryShaderSize = stream.readInt<unsigned int>();
1235 
1236     if (geometryShaderSize > 0)
1237     {
1238         const char *geometryShaderFunction = (const char*) binary + stream.offset();
1239         mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast<const DWORD*>(geometryShaderFunction),
1240                                                         geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
1241                                                         (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS));
1242         if (!mGeometryExecutable)
1243         {
1244             infoLog.append("Could not create geometry shader.");
1245             SafeDelete(mPixelExecutable);
1246             return false;
1247         }
1248         stream.skip(geometryShaderSize);
1249     }
1250 
1251     const char *ptr = (const char*) binary + stream.offset();
1252 
1253     const GUID *binaryIdentifier = (const GUID *) ptr;
1254     ptr += sizeof(GUID);
1255 
1256     GUID identifier = mRenderer->getAdapterIdentifier();
1257     if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0)
1258     {
1259         infoLog.append("Invalid program binary.");
1260         return false;
1261     }
1262 
1263     initializeUniformStorage();
1264 
1265     return true;
1266 #endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD
1267 }
1268 
save(void * binary,GLsizei bufSize,GLsizei * length)1269 bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length)
1270 {
1271     BinaryOutputStream stream;
1272 
1273     stream.writeInt(GL_PROGRAM_BINARY_ANGLE);
1274     stream.writeInt(ANGLE_MAJOR_VERSION);
1275     stream.writeInt(ANGLE_MINOR_VERSION);
1276     stream.writeBytes(reinterpret_cast<unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
1277     stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
1278 
1279     for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
1280     {
1281         stream.writeInt(mLinkedAttribute[i].type);
1282         stream.writeString(mLinkedAttribute[i].name);
1283         stream.writeInt(mShaderAttributes[i].type);
1284         stream.writeString(mShaderAttributes[i].name);
1285         stream.writeInt(mSemanticIndex[i]);
1286     }
1287 
1288     for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
1289     {
1290         stream.writeInt(mSamplersPS[i].active);
1291         stream.writeInt(mSamplersPS[i].logicalTextureUnit);
1292         stream.writeInt(mSamplersPS[i].textureType);
1293     }
1294 
1295     for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i)
1296     {
1297         stream.writeInt(mSamplersVS[i].active);
1298         stream.writeInt(mSamplersVS[i].logicalTextureUnit);
1299         stream.writeInt(mSamplersVS[i].textureType);
1300     }
1301 
1302     stream.writeInt(mUsedVertexSamplerRange);
1303     stream.writeInt(mUsedPixelSamplerRange);
1304     stream.writeInt(mUsesPointSize);
1305     stream.writeInt(mShaderVersion);
1306 
1307     stream.writeInt(mUniforms.size());
1308     for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex)
1309     {
1310         const LinkedUniform &uniform = *mUniforms[uniformIndex];
1311 
1312         stream.writeInt(uniform.type);
1313         stream.writeInt(uniform.precision);
1314         stream.writeString(uniform.name);
1315         stream.writeInt(uniform.arraySize);
1316         stream.writeInt(uniform.blockIndex);
1317 
1318         stream.writeInt(uniform.blockInfo.offset);
1319         stream.writeInt(uniform.blockInfo.arrayStride);
1320         stream.writeInt(uniform.blockInfo.matrixStride);
1321         stream.writeInt(uniform.blockInfo.isRowMajorMatrix);
1322 
1323         stream.writeInt(uniform.psRegisterIndex);
1324         stream.writeInt(uniform.vsRegisterIndex);
1325         stream.writeInt(uniform.registerCount);
1326         stream.writeInt(uniform.registerElement);
1327     }
1328 
1329     stream.writeInt(mUniformBlocks.size());
1330     for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex)
1331     {
1332         const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex];
1333 
1334         stream.writeString(uniformBlock.name);
1335         stream.writeInt(uniformBlock.elementIndex);
1336         stream.writeInt(uniformBlock.dataSize);
1337 
1338         stream.writeInt(uniformBlock.memberUniformIndexes.size());
1339         for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
1340         {
1341             stream.writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]);
1342         }
1343 
1344         stream.writeInt(uniformBlock.psRegisterIndex);
1345         stream.writeInt(uniformBlock.vsRegisterIndex);
1346     }
1347 
1348     stream.writeInt(mUniformIndex.size());
1349     for (size_t i = 0; i < mUniformIndex.size(); ++i)
1350     {
1351         stream.writeString(mUniformIndex[i].name);
1352         stream.writeInt(mUniformIndex[i].element);
1353         stream.writeInt(mUniformIndex[i].index);
1354     }
1355 
1356     stream.writeInt(mTransformFeedbackBufferMode);
1357     stream.writeInt(mTransformFeedbackLinkedVaryings.size());
1358     for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++)
1359     {
1360         const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i];
1361 
1362         stream.writeString(varying.name);
1363         stream.writeInt(varying.type);
1364         stream.writeInt(varying.size);
1365         stream.writeString(varying.semanticName);
1366         stream.writeInt(varying.semanticIndex);
1367         stream.writeInt(varying.semanticIndexCount);
1368     }
1369 
1370     stream.writeString(mVertexHLSL);
1371     stream.writeInt(mVertexWorkarounds);
1372 
1373     stream.writeInt(mVertexExecutables.size());
1374     for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++)
1375     {
1376         VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex];
1377 
1378         for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++)
1379         {
1380             const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex];
1381             stream.writeInt(vertexInput.mType);
1382             stream.writeInt(vertexInput.mNormalized);
1383             stream.writeInt(vertexInput.mComponents);
1384             stream.writeInt(vertexInput.mPureInteger);
1385         }
1386 
1387         size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
1388         stream.writeInt(vertexShaderSize);
1389 
1390         unsigned char *vertexBlob = static_cast<unsigned char *>(vertexExecutable->shaderExecutable()->getFunction());
1391         stream.writeBytes(vertexBlob, vertexShaderSize);
1392     }
1393 
1394     size_t pixelShaderSize = mPixelExecutable->getLength();
1395     stream.writeInt(pixelShaderSize);
1396 
1397     unsigned char *pixelBlob = static_cast<unsigned char *>(mPixelExecutable->getFunction());
1398     stream.writeBytes(pixelBlob, pixelShaderSize);
1399 
1400     size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0;
1401     stream.writeInt(geometryShaderSize);
1402 
1403     if (mGeometryExecutable != NULL && geometryShaderSize > 0)
1404     {
1405         unsigned char *geometryBlob = static_cast<unsigned char *>(mGeometryExecutable->getFunction());
1406         stream.writeBytes(geometryBlob, geometryShaderSize);
1407     }
1408 
1409     GUID identifier = mRenderer->getAdapterIdentifier();
1410 
1411     GLsizei streamLength = stream.length();
1412     const void *streamData = stream.data();
1413 
1414     GLsizei totalLength = streamLength + sizeof(GUID);
1415     if (totalLength > bufSize)
1416     {
1417         if (length)
1418         {
1419             *length = 0;
1420         }
1421 
1422         return false;
1423     }
1424 
1425     if (binary)
1426     {
1427         char *ptr = (char*) binary;
1428 
1429         memcpy(ptr, streamData, streamLength);
1430         ptr += streamLength;
1431 
1432         memcpy(ptr, &identifier, sizeof(GUID));
1433         ptr += sizeof(GUID);
1434 
1435         ASSERT(ptr - totalLength == binary);
1436     }
1437 
1438     if (length)
1439     {
1440         *length = totalLength;
1441     }
1442 
1443     return true;
1444 }
1445 
getLength()1446 GLint ProgramBinary::getLength()
1447 {
1448     GLint length;
1449     if (save(NULL, INT_MAX, &length))
1450     {
1451         return length;
1452     }
1453     else
1454     {
1455         return 0;
1456     }
1457 }
1458 
link(InfoLog & infoLog,const AttributeBindings & attributeBindings,FragmentShader * fragmentShader,VertexShader * vertexShader,const std::vector<std::string> & transformFeedbackVaryings,GLenum transformFeedbackBufferMode)1459 bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader,
1460                          const std::vector<std::string>& transformFeedbackVaryings, GLenum transformFeedbackBufferMode)
1461 {
1462     if (!fragmentShader || !fragmentShader->isCompiled())
1463     {
1464         return false;
1465     }
1466 
1467     if (!vertexShader || !vertexShader->isCompiled())
1468     {
1469         return false;
1470     }
1471 
1472     mTransformFeedbackLinkedVaryings.clear();
1473     mTransformFeedbackBufferMode = transformFeedbackBufferMode;
1474 
1475     mShaderVersion = vertexShader->getShaderVersion();
1476 
1477     std::string pixelHLSL = fragmentShader->getHLSL();
1478     mVertexHLSL = vertexShader->getHLSL();
1479     mVertexWorkarounds = vertexShader->getD3DWorkarounds();
1480 
1481     // Map the varyings to the register file
1482     VaryingPacking packing = { NULL };
1483     int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader, vertexShader, transformFeedbackVaryings);
1484 
1485     if (registers < 0)
1486     {
1487         return false;
1488     }
1489 
1490     if (!linkVaryings(infoLog, fragmentShader, vertexShader))
1491     {
1492         return false;
1493     }
1494 
1495     mUsesPointSize = vertexShader->usesPointSize();
1496     std::vector<LinkedVarying> linkedVaryings;
1497     if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, pixelHLSL, mVertexHLSL,
1498                                               fragmentShader, vertexShader, transformFeedbackVaryings,
1499                                               &linkedVaryings, &mOutputVariables))
1500     {
1501         return false;
1502     }
1503 
1504     bool success = true;
1505 
1506     if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader))
1507     {
1508         success = false;
1509     }
1510 
1511     if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms()))
1512     {
1513         success = false;
1514     }
1515 
1516     // special case for gl_DepthRange, the only built-in uniform (also a struct)
1517     if (vertexShader->usesDepthRange() || fragmentShader->usesDepthRange())
1518     {
1519         mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, BlockMemberInfo::getDefaultBlockInfo()));
1520         mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, BlockMemberInfo::getDefaultBlockInfo()));
1521         mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, BlockMemberInfo::getDefaultBlockInfo()));
1522     }
1523 
1524     if (!linkUniformBlocks(infoLog, vertexShader->getInterfaceBlocks(), fragmentShader->getInterfaceBlocks()))
1525     {
1526         success = false;
1527     }
1528 
1529     if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
1530                                                transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings))
1531     {
1532         success = false;
1533     }
1534 
1535     if (success)
1536     {
1537         VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS];
1538         GetInputLayoutFromShader(vertexShader->activeAttributes(), defaultInputLayout);
1539 
1540         rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout);
1541         mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL,
1542                                                           mTransformFeedbackLinkedVaryings,
1543                                                           (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
1544                                                           fragmentShader->getD3DWorkarounds());
1545 
1546         if (usesGeometryShader())
1547         {
1548             std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShader, vertexShader);
1549             mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY,
1550                                                                  mTransformFeedbackLinkedVaryings,
1551                                                                  (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
1552                                                                  rx::ANGLE_D3D_WORKAROUND_NONE);
1553         }
1554 
1555         if (!defaultVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable))
1556         {
1557             infoLog.append("Failed to create D3D shaders.");
1558             success = false;
1559 
1560             while (!mVertexExecutables.empty())
1561             {
1562                 delete mVertexExecutables.back();
1563                 mVertexExecutables.pop_back();
1564             }
1565 
1566             SafeDelete(mGeometryExecutable);
1567             SafeDelete(mPixelExecutable);
1568 
1569             mTransformFeedbackLinkedVaryings.clear();
1570         }
1571     }
1572 
1573     return success;
1574 }
1575 
1576 // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
linkAttributes(InfoLog & infoLog,const AttributeBindings & attributeBindings,FragmentShader * fragmentShader,VertexShader * vertexShader)1577 bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
1578 {
1579     unsigned int usedLocations = 0;
1580     const std::vector<gl::Attribute> &activeAttributes = vertexShader->activeAttributes();
1581 
1582     // Link attributes that have a binding location
1583     for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
1584     {
1585         const gl::Attribute &attribute = activeAttributes[attributeIndex];
1586         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
1587 
1588         mShaderAttributes[attributeIndex] = attribute;
1589 
1590         if (location != -1)   // Set by glBindAttribLocation or by location layout qualifier
1591         {
1592             const int rows = AttributeRegisterCount(attribute.type);
1593 
1594             if (rows + location > MAX_VERTEX_ATTRIBS)
1595             {
1596                 infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
1597 
1598                 return false;
1599             }
1600 
1601             for (int row = 0; row < rows; row++)
1602             {
1603                 const int rowLocation = location + row;
1604                 gl::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation];
1605 
1606                 // In GLSL 3.00, attribute aliasing produces a link error
1607                 // In GLSL 1.00, attribute aliasing is allowed
1608                 if (mShaderVersion >= 300)
1609                 {
1610                     if (!linkedAttribute.name.empty())
1611                     {
1612                         infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation);
1613                         return false;
1614                     }
1615                 }
1616 
1617                 linkedAttribute = attribute;
1618                 usedLocations |= 1 << rowLocation;
1619             }
1620         }
1621     }
1622 
1623     // Link attributes that don't have a binding location
1624     for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
1625     {
1626         const gl::Attribute &attribute = activeAttributes[attributeIndex];
1627         const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
1628 
1629         if (location == -1)   // Not set by glBindAttribLocation or by location layout qualifier
1630         {
1631             int rows = AttributeRegisterCount(attribute.type);
1632             int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
1633 
1634             if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
1635             {
1636                 infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
1637 
1638                 return false;   // Fail to link
1639             }
1640 
1641             mLinkedAttribute[availableIndex] = attribute;
1642         }
1643     }
1644 
1645     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
1646     {
1647         int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
1648         int rows = AttributeRegisterCount(mLinkedAttribute[attributeIndex].type);
1649 
1650         for (int r = 0; r < rows; r++)
1651         {
1652             mSemanticIndex[attributeIndex++] = index++;
1653         }
1654     }
1655 
1656     initAttributesByLayout();
1657 
1658     return true;
1659 }
1660 
linkValidateVariablesBase(InfoLog & infoLog,const std::string & variableName,const gl::ShaderVariable & vertexVariable,const gl::ShaderVariable & fragmentVariable,bool validatePrecision)1661 bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const gl::ShaderVariable &vertexVariable, const gl::ShaderVariable &fragmentVariable, bool validatePrecision)
1662 {
1663     if (vertexVariable.type != fragmentVariable.type)
1664     {
1665         infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str());
1666         return false;
1667     }
1668     if (vertexVariable.arraySize != fragmentVariable.arraySize)
1669     {
1670         infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
1671         return false;
1672     }
1673     if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
1674     {
1675         infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
1676         return false;
1677     }
1678 
1679     return true;
1680 }
1681 
1682 template <class ShaderVarType>
linkValidateFields(InfoLog & infoLog,const std::string & varName,const ShaderVarType & vertexVar,const ShaderVarType & fragmentVar)1683 bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar)
1684 {
1685     if (vertexVar.fields.size() != fragmentVar.fields.size())
1686     {
1687         infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", varName.c_str());
1688         return false;
1689     }
1690     const unsigned int numMembers = vertexVar.fields.size();
1691     for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
1692     {
1693         const ShaderVarType &vertexMember = vertexVar.fields[memberIndex];
1694         const ShaderVarType &fragmentMember = fragmentVar.fields[memberIndex];
1695 
1696         if (vertexMember.name != fragmentMember.name)
1697         {
1698             infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
1699                            memberIndex, varName.c_str(), vertexMember.name.c_str(), fragmentMember.name.c_str());
1700             return false;
1701         }
1702 
1703         const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'";
1704         if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember))
1705         {
1706             return false;
1707         }
1708     }
1709 
1710     return true;
1711 }
1712 
linkValidateVariables(InfoLog & infoLog,const std::string & uniformName,const gl::Uniform & vertexUniform,const gl::Uniform & fragmentUniform)1713 bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const gl::Uniform &vertexUniform, const gl::Uniform &fragmentUniform)
1714 {
1715     if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
1716     {
1717         return false;
1718     }
1719 
1720     if (!linkValidateFields<gl::Uniform>(infoLog, uniformName, vertexUniform, fragmentUniform))
1721     {
1722         return false;
1723     }
1724 
1725     return true;
1726 }
1727 
linkValidateVariables(InfoLog & infoLog,const std::string & varyingName,const gl::Varying & vertexVarying,const gl::Varying & fragmentVarying)1728 bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const gl::Varying &vertexVarying, const gl::Varying &fragmentVarying)
1729 {
1730     if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
1731     {
1732         return false;
1733     }
1734 
1735     if (vertexVarying.interpolation != fragmentVarying.interpolation)
1736     {
1737         infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
1738         return false;
1739     }
1740 
1741     if (!linkValidateFields<gl::Varying>(infoLog, varyingName, vertexVarying, fragmentVarying))
1742     {
1743         return false;
1744     }
1745 
1746     return true;
1747 }
1748 
linkValidateVariables(InfoLog & infoLog,const std::string & uniformName,const gl::InterfaceBlockField & vertexUniform,const gl::InterfaceBlockField & fragmentUniform)1749 bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const gl::InterfaceBlockField &vertexUniform, const gl::InterfaceBlockField &fragmentUniform)
1750 {
1751     if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
1752     {
1753         return false;
1754     }
1755 
1756     if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix)
1757     {
1758         infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
1759         return false;
1760     }
1761 
1762     if (!linkValidateFields<gl::InterfaceBlockField>(infoLog, uniformName, vertexUniform, fragmentUniform))
1763     {
1764         return false;
1765     }
1766 
1767     return true;
1768 }
1769 
linkUniforms(InfoLog & infoLog,const std::vector<gl::Uniform> & vertexUniforms,const std::vector<gl::Uniform> & fragmentUniforms)1770 bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<gl::Uniform> &vertexUniforms, const std::vector<gl::Uniform> &fragmentUniforms)
1771 {
1772     // Check that uniforms defined in the vertex and fragment shaders are identical
1773     typedef std::map<std::string, const gl::Uniform*> UniformMap;
1774     UniformMap linkedUniforms;
1775 
1776     for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++)
1777     {
1778         const gl::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex];
1779         linkedUniforms[vertexUniform.name] = &vertexUniform;
1780     }
1781 
1782     for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++)
1783     {
1784         const gl::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex];
1785         UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name);
1786         if (entry != linkedUniforms.end())
1787         {
1788             const gl::Uniform &vertexUniform = *entry->second;
1789             const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
1790             if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform))
1791             {
1792                 return false;
1793             }
1794         }
1795     }
1796 
1797     for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
1798     {
1799         if (!defineUniform(GL_VERTEX_SHADER, vertexUniforms[uniformIndex], infoLog))
1800         {
1801             return false;
1802         }
1803     }
1804 
1805     for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
1806     {
1807         if (!defineUniform(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex], infoLog))
1808         {
1809             return false;
1810         }
1811     }
1812 
1813     initializeUniformStorage();
1814 
1815     return true;
1816 }
1817 
getTextureType(GLenum samplerType,InfoLog & infoLog)1818 TextureType ProgramBinary::getTextureType(GLenum samplerType, InfoLog &infoLog)
1819 {
1820     switch(samplerType)
1821     {
1822       case GL_SAMPLER_2D:
1823       case GL_INT_SAMPLER_2D:
1824       case GL_UNSIGNED_INT_SAMPLER_2D:
1825       case GL_SAMPLER_2D_SHADOW:
1826         return TEXTURE_2D;
1827       case GL_SAMPLER_3D:
1828       case GL_INT_SAMPLER_3D:
1829       case GL_UNSIGNED_INT_SAMPLER_3D:
1830         return TEXTURE_3D;
1831       case GL_SAMPLER_CUBE:
1832       case GL_SAMPLER_CUBE_SHADOW:
1833         return TEXTURE_CUBE;
1834       case GL_INT_SAMPLER_CUBE:
1835       case GL_UNSIGNED_INT_SAMPLER_CUBE:
1836         return TEXTURE_CUBE;
1837       case GL_SAMPLER_2D_ARRAY:
1838       case GL_INT_SAMPLER_2D_ARRAY:
1839       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
1840       case GL_SAMPLER_2D_ARRAY_SHADOW:
1841         return TEXTURE_2D_ARRAY;
1842       default: UNREACHABLE();
1843     }
1844 
1845     return TEXTURE_2D;
1846 }
1847 
defineUniform(GLenum shader,const gl::Uniform & constant,InfoLog & infoLog)1848 bool ProgramBinary::defineUniform(GLenum shader, const gl::Uniform &constant, InfoLog &infoLog)
1849 {
1850     if (constant.isStruct())
1851     {
1852         if (constant.arraySize > 0)
1853         {
1854             ShShaderOutput outputType = Shader::getCompilerOutputType(shader);
1855             const unsigned int elementRegisterCount = HLSLVariableRegisterCount(constant, outputType) / constant.arraySize;
1856 
1857             for (unsigned int elementIndex = 0; elementIndex < constant.arraySize; elementIndex++)
1858             {
1859                 const unsigned int elementRegisterOffset = elementRegisterCount * elementIndex;
1860 
1861                 for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++)
1862                 {
1863                     const gl::Uniform &field = constant.fields[fieldIndex];
1864                     const std::string &uniformName = constant.name + ArrayString(elementIndex) + "." + field.name;
1865                     const unsigned int fieldRegisterIndex = field.registerIndex + elementRegisterOffset;
1866                     gl::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize,
1867                                              fieldRegisterIndex, field.elementIndex);
1868 
1869                     fieldUniform.fields = field.fields;
1870                     if (!defineUniform(shader, fieldUniform, infoLog))
1871                     {
1872                         return false;
1873                     }
1874                 }
1875             }
1876         }
1877         else
1878         {
1879             for (size_t fieldIndex = 0; fieldIndex < constant.fields.size(); fieldIndex++)
1880             {
1881                 const gl::Uniform &field = constant.fields[fieldIndex];
1882                 const std::string &uniformName = constant.name + "." + field.name;
1883 
1884                 gl::Uniform fieldUniform(field.type, field.precision, uniformName.c_str(), field.arraySize,
1885                                          field.registerIndex, field.elementIndex);
1886 
1887                 fieldUniform.fields = field.fields;
1888 
1889                 if (!defineUniform(shader, fieldUniform, infoLog))
1890                 {
1891                     return false;
1892                 }
1893             }
1894         }
1895 
1896         return true;
1897     }
1898 
1899     if (IsSampler(constant.type))
1900     {
1901         unsigned int samplerIndex = constant.registerIndex;
1902 
1903         do
1904         {
1905             if (shader == GL_VERTEX_SHADER)
1906             {
1907                 if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits())
1908                 {
1909                     mSamplersVS[samplerIndex].active = true;
1910                     mSamplersVS[samplerIndex].textureType = getTextureType(constant.type, infoLog);
1911                     mSamplersVS[samplerIndex].logicalTextureUnit = 0;
1912                     mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
1913                 }
1914                 else
1915                 {
1916                     infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits());
1917                     return false;
1918                 }
1919             }
1920             else if (shader == GL_FRAGMENT_SHADER)
1921             {
1922                 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
1923                 {
1924                     mSamplersPS[samplerIndex].active = true;
1925                     mSamplersPS[samplerIndex].textureType = getTextureType(constant.type, infoLog);
1926                     mSamplersPS[samplerIndex].logicalTextureUnit = 0;
1927                     mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
1928                 }
1929                 else
1930                 {
1931                     infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1932                     return false;
1933                 }
1934             }
1935             else UNREACHABLE();
1936 
1937             samplerIndex++;
1938         }
1939         while (samplerIndex < constant.registerIndex + constant.arraySize);
1940     }
1941 
1942     LinkedUniform *uniform = NULL;
1943     GLint location = getUniformLocation(constant.name);
1944 
1945     if (location >= 0)   // Previously defined, type and precision must match
1946     {
1947         uniform = mUniforms[mUniformIndex[location].index];
1948     }
1949     else
1950     {
1951         uniform = new LinkedUniform(constant.type, constant.precision, constant.name, constant.arraySize,
1952                                     -1, BlockMemberInfo::getDefaultBlockInfo());
1953         uniform->registerElement = constant.elementIndex;
1954     }
1955 
1956     if (!uniform)
1957     {
1958         return false;
1959     }
1960 
1961     if (shader == GL_FRAGMENT_SHADER)
1962     {
1963         uniform->psRegisterIndex = constant.registerIndex;
1964     }
1965     else if (shader == GL_VERTEX_SHADER)
1966     {
1967         uniform->vsRegisterIndex = constant.registerIndex;
1968     }
1969     else UNREACHABLE();
1970 
1971     if (location >= 0)
1972     {
1973         return uniform->type == constant.type;
1974     }
1975 
1976     mUniforms.push_back(uniform);
1977     unsigned int uniformIndex = mUniforms.size() - 1;
1978 
1979     for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform->elementCount(); arrayElementIndex++)
1980     {
1981         mUniformIndex.push_back(VariableLocation(uniform->name, arrayElementIndex, uniformIndex));
1982     }
1983 
1984     if (shader == GL_VERTEX_SHADER)
1985     {
1986         if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
1987         {
1988             infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors());
1989             return false;
1990         }
1991     }
1992     else if (shader == GL_FRAGMENT_SHADER)
1993     {
1994         if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors())
1995         {
1996             infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors());
1997             return false;
1998         }
1999     }
2000     else UNREACHABLE();
2001 
2002     return true;
2003 }
2004 
areMatchingInterfaceBlocks(InfoLog & infoLog,const gl::InterfaceBlock & vertexInterfaceBlock,const gl::InterfaceBlock & fragmentInterfaceBlock)2005 bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const gl::InterfaceBlock &vertexInterfaceBlock, const gl::InterfaceBlock &fragmentInterfaceBlock)
2006 {
2007     const char* blockName = vertexInterfaceBlock.name.c_str();
2008 
2009     // validate blocks for the same member types
2010     if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
2011     {
2012         infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
2013         return false;
2014     }
2015 
2016     if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
2017     {
2018         infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
2019         return false;
2020     }
2021 
2022     if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
2023     {
2024         infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
2025         return false;
2026     }
2027 
2028     const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
2029     for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
2030     {
2031         const gl::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
2032         const gl::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
2033 
2034         if (vertexMember.name != fragmentMember.name)
2035         {
2036             infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
2037                            blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
2038             return false;
2039         }
2040 
2041         std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
2042         if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember))
2043         {
2044             return false;
2045         }
2046     }
2047 
2048     return true;
2049 }
2050 
linkUniformBlocks(InfoLog & infoLog,const std::vector<gl::InterfaceBlock> & vertexInterfaceBlocks,const std::vector<gl::InterfaceBlock> & fragmentInterfaceBlocks)2051 bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const std::vector<gl::InterfaceBlock> &vertexInterfaceBlocks,
2052                                       const std::vector<gl::InterfaceBlock> &fragmentInterfaceBlocks)
2053 {
2054     // Check that interface blocks defined in the vertex and fragment shaders are identical
2055     typedef std::map<std::string, const gl::InterfaceBlock*> UniformBlockMap;
2056     UniformBlockMap linkedUniformBlocks;
2057 
2058     for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
2059     {
2060         const gl::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
2061         linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
2062     }
2063 
2064     for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
2065     {
2066         const gl::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
2067         UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
2068         if (entry != linkedUniformBlocks.end())
2069         {
2070             const gl::InterfaceBlock &vertexInterfaceBlock = *entry->second;
2071             if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
2072             {
2073                 return false;
2074             }
2075         }
2076     }
2077 
2078     for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
2079     {
2080         if (!defineUniformBlock(infoLog, GL_VERTEX_SHADER, vertexInterfaceBlocks[blockIndex]))
2081         {
2082             return false;
2083         }
2084     }
2085 
2086     for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
2087     {
2088         if (!defineUniformBlock(infoLog, GL_FRAGMENT_SHADER, fragmentInterfaceBlocks[blockIndex]))
2089         {
2090             return false;
2091         }
2092     }
2093 
2094     return true;
2095 }
2096 
gatherTransformFeedbackLinkedVaryings(InfoLog & infoLog,const std::vector<LinkedVarying> & linkedVaryings,const std::vector<std::string> & transformFeedbackVaryingNames,GLenum transformFeedbackBufferMode,std::vector<LinkedVarying> * outTransformFeedbackLinkedVaryings) const2097 bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
2098                                                           const std::vector<std::string> &transformFeedbackVaryingNames,
2099                                                           GLenum transformFeedbackBufferMode,
2100                                                           std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings) const
2101 {
2102     size_t totalComponents = 0;
2103     const size_t maxSeparateComponents = mRenderer->getMaxTransformFeedbackSeparateComponents();
2104     const size_t maxInterleavedComponents = mRenderer->getMaxTransformFeedbackInterleavedComponents();
2105 
2106     // Gather the linked varyings that are used for transform feedback, they should all exist.
2107     outTransformFeedbackLinkedVaryings->clear();
2108     for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++)
2109     {
2110         bool found = false;
2111         for (size_t j = 0; j < linkedVaryings.size(); j++)
2112         {
2113             if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name)
2114             {
2115                 for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++)
2116                 {
2117                     if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name)
2118                     {
2119                         infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str());
2120                         return false;
2121                     }
2122                 }
2123 
2124                 size_t componentCount = linkedVaryings[j].semanticIndexCount * 4;
2125                 if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
2126                     componentCount > maxSeparateComponents)
2127                 {
2128                     infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).",
2129                                    linkedVaryings[j].name.c_str(), componentCount, maxSeparateComponents);
2130                     return false;
2131                 }
2132 
2133                 totalComponents += componentCount;
2134 
2135                 outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]);
2136                 found = true;
2137                 break;
2138             }
2139         }
2140 
2141         // All transform feedback varyings are expected to exist since packVaryings checks for them.
2142         ASSERT(found);
2143     }
2144 
2145     if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > maxInterleavedComponents)
2146     {
2147         infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).",
2148                        totalComponents, maxInterleavedComponents);
2149         return false;
2150     }
2151 
2152     return true;
2153 }
2154 
defineUniformBlockMembers(const std::vector<gl::InterfaceBlockField> & fields,const std::string & prefix,int blockIndex,BlockInfoItr * blockInfoItr,std::vector<unsigned int> * blockUniformIndexes)2155 void ProgramBinary::defineUniformBlockMembers(const std::vector<gl::InterfaceBlockField> &fields, const std::string &prefix, int blockIndex, BlockInfoItr *blockInfoItr, std::vector<unsigned int> *blockUniformIndexes)
2156 {
2157     for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++)
2158     {
2159         const gl::InterfaceBlockField &field = fields[uniformIndex];
2160         const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name);
2161 
2162         if (!field.fields.empty())
2163         {
2164             if (field.arraySize > 0)
2165             {
2166                 for (unsigned int arrayElement = 0; arrayElement < field.arraySize; arrayElement++)
2167                 {
2168                     const std::string uniformElementName = fieldName + ArrayString(arrayElement);
2169                     defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, blockInfoItr, blockUniformIndexes);
2170                 }
2171             }
2172             else
2173             {
2174                 defineUniformBlockMembers(field.fields, fieldName, blockIndex, blockInfoItr, blockUniformIndexes);
2175             }
2176         }
2177         else
2178         {
2179             LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize,
2180                                                           blockIndex, **blockInfoItr);
2181 
2182             // add to uniform list, but not index, since uniform block uniforms have no location
2183             blockUniformIndexes->push_back(mUniforms.size());
2184             mUniforms.push_back(newUniform);
2185             (*blockInfoItr)++;
2186         }
2187     }
2188 }
2189 
defineUniformBlock(InfoLog & infoLog,GLenum shader,const gl::InterfaceBlock & interfaceBlock)2190 bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, GLenum shader, const gl::InterfaceBlock &interfaceBlock)
2191 {
2192     // create uniform block entries if they do not exist
2193     if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX)
2194     {
2195         std::vector<unsigned int> blockUniformIndexes;
2196         const unsigned int blockIndex = mUniformBlocks.size();
2197 
2198         // define member uniforms
2199         BlockInfoItr blockInfoItr = interfaceBlock.blockInfo.cbegin();
2200         defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, &blockInfoItr, &blockUniformIndexes);
2201 
2202         // create all the uniform blocks
2203         if (interfaceBlock.arraySize > 0)
2204         {
2205             for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++)
2206             {
2207                 gl::UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, interfaceBlock.dataSize);
2208                 newUniformBlock->memberUniformIndexes = blockUniformIndexes;
2209                 mUniformBlocks.push_back(newUniformBlock);
2210             }
2211         }
2212         else
2213         {
2214             gl::UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, interfaceBlock.dataSize);
2215             newUniformBlock->memberUniformIndexes = blockUniformIndexes;
2216             mUniformBlocks.push_back(newUniformBlock);
2217         }
2218     }
2219 
2220     // Assign registers to the uniform blocks
2221     const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name);
2222     const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize);
2223     ASSERT(blockIndex != GL_INVALID_INDEX);
2224     ASSERT(blockIndex + elementCount <= mUniformBlocks.size());
2225 
2226     for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++)
2227     {
2228         gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement];
2229         ASSERT(uniformBlock->name == interfaceBlock.name);
2230 
2231         if (!assignUniformBlockRegister(infoLog, uniformBlock, shader, interfaceBlock.registerIndex + uniformBlockElement))
2232         {
2233             return false;
2234         }
2235     }
2236 
2237     return true;
2238 }
2239 
assignUniformBlockRegister(InfoLog & infoLog,UniformBlock * uniformBlock,GLenum shader,unsigned int registerIndex)2240 bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex)
2241 {
2242     if (shader == GL_VERTEX_SHADER)
2243     {
2244         uniformBlock->vsRegisterIndex = registerIndex;
2245         unsigned int maximumBlocks = mRenderer->getMaxVertexShaderUniformBuffers();
2246 
2247         if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= maximumBlocks)
2248         {
2249             infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", maximumBlocks);
2250             return false;
2251         }
2252     }
2253     else if (shader == GL_FRAGMENT_SHADER)
2254     {
2255         uniformBlock->psRegisterIndex = registerIndex;
2256         unsigned int maximumBlocks = mRenderer->getMaxFragmentShaderUniformBuffers();
2257 
2258         if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= maximumBlocks)
2259         {
2260             infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", maximumBlocks);
2261             return false;
2262         }
2263     }
2264     else UNREACHABLE();
2265 
2266     return true;
2267 }
2268 
isValidated() const2269 bool ProgramBinary::isValidated() const
2270 {
2271     return mValidated;
2272 }
2273 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2274 void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2275 {
2276     // Skip over inactive attributes
2277     unsigned int activeAttribute = 0;
2278     unsigned int attribute;
2279     for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2280     {
2281         if (mLinkedAttribute[attribute].name.empty())
2282         {
2283             continue;
2284         }
2285 
2286         if (activeAttribute == index)
2287         {
2288             break;
2289         }
2290 
2291         activeAttribute++;
2292     }
2293 
2294     if (bufsize > 0)
2295     {
2296         const char *string = mLinkedAttribute[attribute].name.c_str();
2297 
2298         strncpy(name, string, bufsize);
2299         name[bufsize - 1] = '\0';
2300 
2301         if (length)
2302         {
2303             *length = strlen(name);
2304         }
2305     }
2306 
2307     *size = 1;   // Always a single 'type' instance
2308 
2309     *type = mLinkedAttribute[attribute].type;
2310 }
2311 
getActiveAttributeCount() const2312 GLint ProgramBinary::getActiveAttributeCount() const
2313 {
2314     int count = 0;
2315 
2316     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2317     {
2318         if (!mLinkedAttribute[attributeIndex].name.empty())
2319         {
2320             count++;
2321         }
2322     }
2323 
2324     return count;
2325 }
2326 
getActiveAttributeMaxLength() const2327 GLint ProgramBinary::getActiveAttributeMaxLength() const
2328 {
2329     int maxLength = 0;
2330 
2331     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2332     {
2333         if (!mLinkedAttribute[attributeIndex].name.empty())
2334         {
2335             maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2336         }
2337     }
2338 
2339     return maxLength;
2340 }
2341 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2342 void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2343 {
2344     ASSERT(index < mUniforms.size());   // index must be smaller than getActiveUniformCount()
2345 
2346     if (bufsize > 0)
2347     {
2348         std::string string = mUniforms[index]->name;
2349 
2350         if (mUniforms[index]->isArray())
2351         {
2352             string += "[0]";
2353         }
2354 
2355         strncpy(name, string.c_str(), bufsize);
2356         name[bufsize - 1] = '\0';
2357 
2358         if (length)
2359         {
2360             *length = strlen(name);
2361         }
2362     }
2363 
2364     *size = mUniforms[index]->elementCount();
2365 
2366     *type = mUniforms[index]->type;
2367 }
2368 
getActiveUniformCount() const2369 GLint ProgramBinary::getActiveUniformCount() const
2370 {
2371     return mUniforms.size();
2372 }
2373 
getActiveUniformMaxLength() const2374 GLint ProgramBinary::getActiveUniformMaxLength() const
2375 {
2376     int maxLength = 0;
2377 
2378     unsigned int numUniforms = mUniforms.size();
2379     for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
2380     {
2381         if (!mUniforms[uniformIndex]->name.empty())
2382         {
2383             int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
2384             if (mUniforms[uniformIndex]->isArray())
2385             {
2386                 length += 3;  // Counting in "[0]".
2387             }
2388             maxLength = std::max(length, maxLength);
2389         }
2390     }
2391 
2392     return maxLength;
2393 }
2394 
getActiveUniformi(GLuint index,GLenum pname) const2395 GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
2396 {
2397     const gl::LinkedUniform& uniform = *mUniforms[index];
2398 
2399     switch (pname)
2400     {
2401       case GL_UNIFORM_TYPE:         return static_cast<GLint>(uniform.type);
2402       case GL_UNIFORM_SIZE:         return static_cast<GLint>(uniform.elementCount());
2403       case GL_UNIFORM_NAME_LENGTH:  return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
2404       case GL_UNIFORM_BLOCK_INDEX:  return uniform.blockIndex;
2405 
2406       case GL_UNIFORM_OFFSET:       return uniform.blockInfo.offset;
2407       case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
2408       case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
2409       case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
2410 
2411       default:
2412         UNREACHABLE();
2413         break;
2414     }
2415     return 0;
2416 }
2417 
isValidUniformLocation(GLint location) const2418 bool ProgramBinary::isValidUniformLocation(GLint location) const
2419 {
2420     ASSERT(rx::IsIntegerCastSafe<GLint>(mUniformIndex.size()));
2421     return (location >= 0 && location < static_cast<GLint>(mUniformIndex.size()));
2422 }
2423 
getUniformByLocation(GLint location) const2424 LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
2425 {
2426     ASSERT(location >= 0 && static_cast<size_t>(location) < mUniformIndex.size());
2427     return mUniforms[mUniformIndex[location].index];
2428 }
2429 
getActiveUniformBlockName(GLuint uniformBlockIndex,GLsizei bufSize,GLsizei * length,GLchar * uniformBlockName) const2430 void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
2431 {
2432     ASSERT(uniformBlockIndex < mUniformBlocks.size());   // index must be smaller than getActiveUniformBlockCount()
2433 
2434     const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
2435 
2436     if (bufSize > 0)
2437     {
2438         std::string string = uniformBlock.name;
2439 
2440         if (uniformBlock.isArrayElement())
2441         {
2442             string += ArrayString(uniformBlock.elementIndex);
2443         }
2444 
2445         strncpy(uniformBlockName, string.c_str(), bufSize);
2446         uniformBlockName[bufSize - 1] = '\0';
2447 
2448         if (length)
2449         {
2450             *length = strlen(uniformBlockName);
2451         }
2452     }
2453 }
2454 
getActiveUniformBlockiv(GLuint uniformBlockIndex,GLenum pname,GLint * params) const2455 void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
2456 {
2457     ASSERT(uniformBlockIndex < mUniformBlocks.size());   // index must be smaller than getActiveUniformBlockCount()
2458 
2459     const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
2460 
2461     switch (pname)
2462     {
2463       case GL_UNIFORM_BLOCK_DATA_SIZE:
2464         *params = static_cast<GLint>(uniformBlock.dataSize);
2465         break;
2466       case GL_UNIFORM_BLOCK_NAME_LENGTH:
2467         *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
2468         break;
2469       case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
2470         *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
2471         break;
2472       case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
2473         {
2474             for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
2475             {
2476                 params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
2477             }
2478         }
2479         break;
2480       case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
2481         *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
2482         break;
2483       case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
2484         *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
2485         break;
2486       default: UNREACHABLE();
2487     }
2488 }
2489 
getActiveUniformBlockCount() const2490 GLuint ProgramBinary::getActiveUniformBlockCount() const
2491 {
2492     return mUniformBlocks.size();
2493 }
2494 
getActiveUniformBlockMaxLength() const2495 GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
2496 {
2497     unsigned int maxLength = 0;
2498 
2499     unsigned int numUniformBlocks = mUniformBlocks.size();
2500     for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
2501     {
2502         const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex];
2503         if (!uniformBlock.name.empty())
2504         {
2505             const unsigned int length = uniformBlock.name.length() + 1;
2506 
2507             // Counting in "[0]".
2508             const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
2509 
2510             maxLength = std::max(length + arrayLength, maxLength);
2511         }
2512     }
2513 
2514     return maxLength;
2515 }
2516 
validate(InfoLog & infoLog)2517 void ProgramBinary::validate(InfoLog &infoLog)
2518 {
2519     applyUniforms();
2520     if (!validateSamplers(&infoLog))
2521     {
2522         mValidated = false;
2523     }
2524     else
2525     {
2526         mValidated = true;
2527     }
2528 }
2529 
validateSamplers(InfoLog * infoLog)2530 bool ProgramBinary::validateSamplers(InfoLog *infoLog)
2531 {
2532     // if any two active samplers in a program are of different types, but refer to the same
2533     // texture image unit, and this is the current program, then ValidateProgram will fail, and
2534     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
2535 
2536     const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits();
2537     TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS];
2538 
2539     for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i)
2540     {
2541         textureUnitType[i] = TEXTURE_UNKNOWN;
2542     }
2543 
2544     for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
2545     {
2546         if (mSamplersPS[i].active)
2547         {
2548             unsigned int unit = mSamplersPS[i].logicalTextureUnit;
2549 
2550             if (unit >= maxCombinedTextureImageUnits)
2551             {
2552                 if (infoLog)
2553                 {
2554                     infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2555                 }
2556 
2557                 return false;
2558             }
2559 
2560             if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2561             {
2562                 if (mSamplersPS[i].textureType != textureUnitType[unit])
2563                 {
2564                     if (infoLog)
2565                     {
2566                         infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2567                     }
2568 
2569                     return false;
2570                 }
2571             }
2572             else
2573             {
2574                 textureUnitType[unit] = mSamplersPS[i].textureType;
2575             }
2576         }
2577     }
2578 
2579     for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
2580     {
2581         if (mSamplersVS[i].active)
2582         {
2583             unsigned int unit = mSamplersVS[i].logicalTextureUnit;
2584 
2585             if (unit >= maxCombinedTextureImageUnits)
2586             {
2587                 if (infoLog)
2588                 {
2589                     infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2590                 }
2591 
2592                 return false;
2593             }
2594 
2595             if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2596             {
2597                 if (mSamplersVS[i].textureType != textureUnitType[unit])
2598                 {
2599                     if (infoLog)
2600                     {
2601                         infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2602                     }
2603 
2604                     return false;
2605                 }
2606             }
2607             else
2608             {
2609                 textureUnitType[unit] = mSamplersVS[i].textureType;
2610             }
2611         }
2612     }
2613 
2614     return true;
2615 }
2616 
Sampler()2617 ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D)
2618 {
2619 }
2620 
2621 struct AttributeSorter
2622 {
AttributeSortergl::AttributeSorter2623     AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
2624         : originalIndices(semanticIndices)
2625     {
2626     }
2627 
operator ()gl::AttributeSorter2628     bool operator()(int a, int b)
2629     {
2630         if (originalIndices[a] == -1) return false;
2631         if (originalIndices[b] == -1) return true;
2632         return (originalIndices[a] < originalIndices[b]);
2633     }
2634 
2635     const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
2636 };
2637 
initAttributesByLayout()2638 void ProgramBinary::initAttributesByLayout()
2639 {
2640     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
2641     {
2642         mAttributesByLayout[i] = i;
2643     }
2644 
2645     std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
2646 }
2647 
sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS],int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const2648 void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
2649 {
2650     rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
2651 
2652     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
2653     {
2654         oldTranslatedAttributes[i] = attributes[i];
2655     }
2656 
2657     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
2658     {
2659         int oldIndex = mAttributesByLayout[i];
2660         sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
2661         attributes[i] = oldTranslatedAttributes[oldIndex];
2662     }
2663 }
2664 
initializeUniformStorage()2665 void ProgramBinary::initializeUniformStorage()
2666 {
2667     // Compute total default block size
2668     unsigned int vertexRegisters = 0;
2669     unsigned int fragmentRegisters = 0;
2670     for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
2671     {
2672         const LinkedUniform &uniform = *mUniforms[uniformIndex];
2673 
2674         if (!IsSampler(uniform.type))
2675         {
2676             if (uniform.isReferencedByVertexShader())
2677             {
2678                 vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount);
2679             }
2680             if (uniform.isReferencedByFragmentShader())
2681             {
2682                 fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount);
2683             }
2684         }
2685     }
2686 
2687     mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u);
2688     mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u);
2689 }
2690 
2691 }
2692