1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // Program.cpp: Implements the Program class. Implements GL program objects
16 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
23 #include "TransformFeedback.h"
24 #include "utilities.h"
25 #include "common/debug.h"
26 #include "Shader/PixelShader.hpp"
27 #include "Shader/VertexShader.hpp"
35 unsigned int Program::currentSerial = 1;
37 std::string str(int i)
40 sprintf(buffer, "%d", i);
44 Uniform::BlockInfo::BlockInfo(const glsl::Uniform& uniform, int blockIndex)
49 offset = uniform.blockInfo.offset;
50 arrayStride = uniform.blockInfo.arrayStride;
51 matrixStride = uniform.blockInfo.matrixStride;
52 isRowMajorMatrix = uniform.blockInfo.isRowMajorMatrix;
60 isRowMajorMatrix = false;
64 Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize,
65 const BlockInfo &blockInfo)
66 : type(type), precision(precision), name(name), arraySize(arraySize), blockInfo(blockInfo)
68 if(blockInfo.index == -1)
70 size_t bytes = UniformTypeSize(type) * size();
71 data = new unsigned char[bytes];
72 memset(data, 0, bytes);
89 bool Uniform::isArray() const
91 return arraySize >= 1;
94 int Uniform::size() const
96 return arraySize > 0 ? arraySize : 1;
99 int Uniform::registerCount() const
101 return size() * VariableRegisterCount(type);
104 UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize, std::vector<unsigned int> memberUniformIndexes) :
105 name(name), elementIndex(elementIndex), dataSize(dataSize), memberUniformIndexes(memberUniformIndexes), psRegisterIndex(GL_INVALID_INDEX), vsRegisterIndex(GL_INVALID_INDEX)
109 void UniformBlock::setRegisterIndex(GLenum shader, unsigned int registerIndex)
113 case GL_VERTEX_SHADER:
114 vsRegisterIndex = registerIndex;
116 case GL_FRAGMENT_SHADER:
117 psRegisterIndex = registerIndex;
124 bool UniformBlock::isArrayElement() const
126 return elementIndex != GL_INVALID_INDEX;
129 bool UniformBlock::isReferencedByVertexShader() const
131 return vsRegisterIndex != GL_INVALID_INDEX;
134 bool UniformBlock::isReferencedByFragmentShader() const
136 return psRegisterIndex != GL_INVALID_INDEX;
139 UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index)
143 LinkedVarying::LinkedVarying()
147 LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col)
148 : name(name), type(type), size(size), reg(reg), col(col)
152 Program::Program(ResourceManager *manager, GLuint handle) : serial(issueSerial()), resourceManager(manager), handle(handle)
159 transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS;
160 totalLinkedVaryingsComponents = 0;
165 resetUniformBlockBindings();
169 retrievableBinary = false;
179 vertexShader->release();
184 fragmentShader->release();
188 bool Program::attachShader(Shader *shader)
190 if(shader->getType() == GL_VERTEX_SHADER)
197 vertexShader = (VertexShader*)shader;
198 vertexShader->addRef();
200 else if(shader->getType() == GL_FRAGMENT_SHADER)
207 fragmentShader = (FragmentShader*)shader;
208 fragmentShader->addRef();
210 else UNREACHABLE(shader->getType());
215 bool Program::detachShader(Shader *shader)
217 if(shader->getType() == GL_VERTEX_SHADER)
219 if(vertexShader != shader)
224 vertexShader->release();
227 else if(shader->getType() == GL_FRAGMENT_SHADER)
229 if(fragmentShader != shader)
234 fragmentShader->release();
237 else UNREACHABLE(shader->getType());
242 int Program::getAttachedShadersCount() const
244 return (vertexShader ? 1 : 0) + (fragmentShader ? 1 : 0);
247 sw::PixelShader *Program::getPixelShader()
252 sw::VertexShader *Program::getVertexShader()
257 GLint Program::getFragDataLocation(const GLchar *name)
261 std::string baseName(name);
262 unsigned int subscript = GL_INVALID_INDEX;
263 baseName = ParseUniformName(baseName, &subscript);
264 for(glsl::VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); ++input)
266 if(input->name == baseName)
268 int rowCount = VariableRowCount(input->type);
269 int colCount = VariableColumnCount(input->type);
270 return (subscript == GL_INVALID_INDEX) ? input->reg : input->reg + (rowCount > 1 ? colCount * subscript : subscript);
278 void Program::bindAttributeLocation(GLuint index, const char *name)
280 if(index < MAX_VERTEX_ATTRIBS)
282 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
284 attributeBinding[i].erase(name);
287 attributeBinding[index].insert(name);
291 GLint Program::getAttributeLocation(const char *name)
295 for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
297 if(linkedAttribute[index].name == std::string(name))
307 int Program::getAttributeStream(int attributeIndex)
309 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
311 return attributeStream[attributeIndex];
314 // Returns the index of the texture image unit (0-19) corresponding to a sampler index (0-15 for the pixel shader and 0-3 for the vertex shader)
315 GLint Program::getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex)
317 GLint logicalTextureUnit = -1;
321 case sw::SAMPLER_PIXEL:
322 ASSERT(samplerIndex < sizeof(samplersPS) / sizeof(samplersPS[0]));
324 if(samplersPS[samplerIndex].active)
326 logicalTextureUnit = samplersPS[samplerIndex].logicalTextureUnit;
329 case sw::SAMPLER_VERTEX:
330 ASSERT(samplerIndex < sizeof(samplersVS) / sizeof(samplersVS[0]));
332 if(samplersVS[samplerIndex].active)
334 logicalTextureUnit = samplersVS[samplerIndex].logicalTextureUnit;
337 default: UNREACHABLE(type);
340 if(logicalTextureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS)
342 return logicalTextureUnit;
348 // Returns the texture type for a given sampler type and index (0-15 for the pixel shader and 0-3 for the vertex shader)
349 TextureType Program::getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex)
353 case sw::SAMPLER_PIXEL:
354 ASSERT(samplerIndex < sizeof(samplersPS)/sizeof(samplersPS[0]));
355 ASSERT(samplersPS[samplerIndex].active);
356 return samplersPS[samplerIndex].textureType;
357 case sw::SAMPLER_VERTEX:
358 ASSERT(samplerIndex < sizeof(samplersVS)/sizeof(samplersVS[0]));
359 ASSERT(samplersVS[samplerIndex].active);
360 return samplersVS[samplerIndex].textureType;
361 default: UNREACHABLE(type);
367 bool Program::isUniformDefined(const std::string &name) const
369 unsigned int subscript = GL_INVALID_INDEX;
370 std::string baseName = es2::ParseUniformName(name, &subscript);
372 size_t numUniforms = uniformIndex.size();
373 for(size_t location = 0; location < numUniforms; location++)
375 const unsigned int index = uniformIndex[location].index;
376 if((uniformIndex[location].name == baseName) && ((index == GL_INVALID_INDEX) ||
377 ((uniforms[index]->isArray() && uniformIndex[location].element == subscript) ||
378 (subscript == GL_INVALID_INDEX))))
387 GLint Program::getUniformLocation(const std::string &name) const
389 unsigned int subscript = GL_INVALID_INDEX;
390 std::string baseName = es2::ParseUniformName(name, &subscript);
392 size_t numUniforms = uniformIndex.size();
393 for(size_t location = 0; location < numUniforms; location++)
395 const unsigned int index = uniformIndex[location].index;
396 if((index != GL_INVALID_INDEX) && (uniformIndex[location].name == baseName) &&
397 ((uniforms[index]->isArray() && uniformIndex[location].element == subscript) ||
398 (subscript == GL_INVALID_INDEX)))
400 return (GLint)location;
407 GLuint Program::getUniformIndex(const std::string &name) const
409 unsigned int subscript = GL_INVALID_INDEX;
410 std::string baseName = es2::ParseUniformName(name, &subscript);
412 // The app is not allowed to specify array indices other than 0 for arrays of basic types
413 if(subscript != 0 && subscript != GL_INVALID_INDEX)
415 return GL_INVALID_INDEX;
418 size_t numUniforms = uniforms.size();
419 for(GLuint index = 0; index < numUniforms; index++)
421 if(uniforms[index]->name == baseName)
423 if(uniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
430 return GL_INVALID_INDEX;
433 void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
435 ASSERT(uniformBlockIndex < getActiveUniformBlockCount());
437 const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
441 case GL_UNIFORM_BLOCK_DATA_SIZE:
442 *params = static_cast<GLint>(uniformBlock.dataSize);
444 case GL_UNIFORM_BLOCK_NAME_LENGTH:
445 *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
447 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
448 *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
450 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
452 for(unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
454 params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
458 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
459 *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
461 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
462 *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
464 default: UNREACHABLE(pname);
468 GLuint Program::getUniformBlockIndex(const std::string &name) const
470 unsigned int subscript = GL_INVALID_INDEX;
471 std::string baseName = es2::ParseUniformName(name, &subscript);
473 size_t numUniformBlocks = getActiveUniformBlockCount();
474 for(GLuint blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
476 const UniformBlock &uniformBlock = *uniformBlocks[blockIndex];
477 if(uniformBlock.name == baseName)
479 const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
480 if(subscript == uniformBlock.elementIndex || arrayElementZero)
487 return GL_INVALID_INDEX;
490 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
492 if(uniformBlockIndex >= getActiveUniformBlockCount())
494 return error(GL_INVALID_VALUE);
497 uniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
500 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
502 if(uniformBlockIndex >= getActiveUniformBlockCount())
504 return error(GL_INVALID_VALUE, GL_INVALID_INDEX);
506 return uniformBlockBindings[uniformBlockIndex];
509 void Program::resetUniformBlockBindings()
511 for(unsigned int blockId = 0; blockId < MAX_UNIFORM_BUFFER_BINDINGS; blockId++)
513 uniformBlockBindings[blockId] = 0;
517 bool Program::setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements)
519 ASSERT(numElements >= 1 && numElements <= 4);
521 static GLenum floatType[] = { GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4 };
522 static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 };
524 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
529 Uniform *targetUniform = uniforms[uniformIndex[location].index];
530 targetUniform->dirty = true;
532 int size = targetUniform->size();
534 if(size == 1 && count > 1)
536 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
539 count = std::min(size - (int)uniformIndex[location].element, count);
541 int index = numElements - 1;
542 if(targetUniform->type == floatType[index])
544 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat)* numElements,
545 v, numElements * sizeof(GLfloat) * count);
547 else if(targetUniform->type == boolType[index])
549 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * numElements;
551 for(int i = 0; i < count * numElements; i++)
553 boolParams[i] = (v[i] == 0.0f) ? GL_FALSE : GL_TRUE;
564 bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
566 return setUniformfv(location, count, v, 1);
569 bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
571 return setUniformfv(location, count, v, 2);
574 bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
576 return setUniformfv(location, count, v, 3);
579 bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
581 return setUniformfv(location, count, v, 4);
584 bool Program::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum type)
592 case GL_FLOAT_MAT2x3:
593 case GL_FLOAT_MAT3x2:
596 case GL_FLOAT_MAT2x4:
597 case GL_FLOAT_MAT4x2:
603 case GL_FLOAT_MAT3x4:
604 case GL_FLOAT_MAT4x3:
614 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
619 Uniform *targetUniform = uniforms[uniformIndex[location].index];
620 targetUniform->dirty = true;
622 if(targetUniform->type != type)
627 int size = targetUniform->size();
629 if(size == 1 && count > 1)
631 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
634 count = std::min(size - (int)uniformIndex[location].element, count);
636 GLfloat* dst = reinterpret_cast<GLfloat*>(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * numElements);
638 if(transpose == GL_FALSE)
640 memcpy(dst, value, numElements * sizeof(GLfloat) * count);
644 const int rowSize = VariableRowCount(type);
645 const int colSize = VariableColumnCount(type);
646 for(int n = 0; n < count; ++n)
648 for(int i = 0; i < colSize; ++i)
650 for(int j = 0; j < rowSize; ++j)
652 dst[i * rowSize + j] = value[j * colSize + i];
656 value += numElements;
664 bool Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
666 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2);
669 bool Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
671 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2x3);
674 bool Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
676 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2x4);
679 bool Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
681 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3);
684 bool Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
686 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3x2);
689 bool Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
691 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3x4);
694 bool Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
696 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4);
699 bool Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
701 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4x2);
704 bool Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
706 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4x3);
709 bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
711 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
716 Uniform *targetUniform = uniforms[uniformIndex[location].index];
717 targetUniform->dirty = true;
719 int size = targetUniform->size();
721 if(size == 1 && count > 1)
723 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
726 count = std::min(size - (int)uniformIndex[location].element, count);
728 if(targetUniform->type == GL_INT || IsSamplerUniform(targetUniform->type))
730 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint),
731 v, sizeof(GLint) * count);
733 else if(targetUniform->type == GL_BOOL)
735 GLboolean *boolParams = new GLboolean[count];
737 for(int i = 0; i < count; i++)
741 boolParams[i] = GL_FALSE;
745 boolParams[i] = GL_TRUE;
749 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean),
750 boolParams, sizeof(GLboolean) * count);
762 bool Program::setUniformiv(GLint location, GLsizei count, const GLint *v, int numElements)
764 static GLenum intType[] = { GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4 };
765 static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 };
767 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
772 Uniform *targetUniform = uniforms[uniformIndex[location].index];
773 targetUniform->dirty = true;
775 int size = targetUniform->size();
777 if(size == 1 && count > 1)
779 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
782 count = std::min(size - (int)uniformIndex[location].element, count);
784 int index = numElements - 1;
785 if(targetUniform->type == intType[index])
787 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint)* numElements,
788 v, numElements * sizeof(GLint)* count);
790 else if(targetUniform->type == boolType[index])
792 GLboolean *boolParams = new GLboolean[count * numElements];
794 for(int i = 0; i < count * numElements; i++)
796 boolParams[i] = (v[i] == 0) ? GL_FALSE : GL_TRUE;
799 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean)* numElements,
800 boolParams, numElements * sizeof(GLboolean)* count);
812 bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
814 return setUniformiv(location, count, v, 2);
817 bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
819 return setUniformiv(location, count, v, 3);
822 bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
824 return setUniformiv(location, count, v, 4);
827 bool Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
829 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
834 Uniform *targetUniform = uniforms[uniformIndex[location].index];
835 targetUniform->dirty = true;
837 int size = targetUniform->size();
839 if(size == 1 && count > 1)
841 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
844 count = std::min(size - (int)uniformIndex[location].element, count);
846 if(targetUniform->type == GL_UNSIGNED_INT)
848 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLuint),
849 v, sizeof(GLuint)* count);
851 else if(targetUniform->type == GL_BOOL)
853 GLboolean *boolParams = new GLboolean[count];
855 for(int i = 0; i < count; i++)
859 boolParams[i] = GL_FALSE;
863 boolParams[i] = GL_TRUE;
867 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean),
868 boolParams, sizeof(GLboolean)* count);
880 bool Program::setUniformuiv(GLint location, GLsizei count, const GLuint *v, int numElements)
882 static GLenum uintType[] = { GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3, GL_UNSIGNED_INT_VEC4 };
883 static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 };
885 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
890 Uniform *targetUniform = uniforms[uniformIndex[location].index];
891 targetUniform->dirty = true;
893 int size = targetUniform->size();
895 if(size == 1 && count > 1)
897 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
900 count = std::min(size - (int)uniformIndex[location].element, count);
902 int index = numElements - 1;
903 if(targetUniform->type == uintType[index])
905 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLuint)* numElements,
906 v, numElements * sizeof(GLuint)* count);
908 else if(targetUniform->type == boolType[index])
910 GLboolean *boolParams = new GLboolean[count * numElements];
912 for(int i = 0; i < count * numElements; i++)
914 boolParams[i] = (v[i] == 0) ? GL_FALSE : GL_TRUE;
917 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean)* numElements,
918 boolParams, numElements * sizeof(GLboolean)* count);
930 bool Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
932 return setUniformuiv(location, count, v, 2);
935 bool Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
937 return setUniformuiv(location, count, v, 3);
940 bool Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
942 return setUniformuiv(location, count, v, 4);
945 bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
947 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
952 Uniform *targetUniform = uniforms[uniformIndex[location].index];
953 unsigned int count = UniformComponentCount(targetUniform->type);
955 // Sized query - ensure the provided buffer is large enough
956 if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLfloat))
961 switch(UniformComponentType(targetUniform->type))
965 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * count;
967 for(unsigned int i = 0; i < count; i++)
969 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
974 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLfloat),
975 count * sizeof(GLfloat));
979 GLint *intParams = (GLint*)targetUniform->data + uniformIndex[location].element * count;
981 for(unsigned int i = 0; i < count; i++)
983 params[i] = (float)intParams[i];
987 case GL_UNSIGNED_INT:
989 GLuint *uintParams = (GLuint*)targetUniform->data + uniformIndex[location].element * count;
991 for(unsigned int i = 0; i < count; i++)
993 params[i] = (float)uintParams[i];
997 default: UNREACHABLE(targetUniform->type);
1003 bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
1005 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
1010 Uniform *targetUniform = uniforms[uniformIndex[location].index];
1011 unsigned int count = UniformComponentCount(targetUniform->type);
1013 // Sized query - ensure the provided buffer is large enough
1014 if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLint))
1019 switch(UniformComponentType(targetUniform->type))
1023 GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count;
1025 for(unsigned int i = 0; i < count; i++)
1027 params[i] = (GLint)boolParams[i];
1033 GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count;
1035 for(unsigned int i = 0; i < count; i++)
1037 params[i] = (GLint)floatParams[i];
1042 case GL_UNSIGNED_INT:
1043 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLint),
1044 count * sizeof(GLint));
1046 default: UNREACHABLE(targetUniform->type);
1052 bool Program::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params)
1054 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
1059 Uniform *targetUniform = uniforms[uniformIndex[location].index];
1060 unsigned int count = UniformComponentCount(targetUniform->type);
1062 // Sized query - ensure the provided buffer is large enough
1063 if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLuint))
1068 switch(UniformComponentType(targetUniform->type))
1072 GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count;
1074 for(unsigned int i = 0; i < count; i++)
1076 params[i] = (GLuint)boolParams[i];
1082 GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count;
1084 for(unsigned int i = 0; i < count; i++)
1086 params[i] = (GLuint)floatParams[i];
1091 case GL_UNSIGNED_INT:
1092 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLuint),
1093 count * sizeof(GLuint));
1095 default: UNREACHABLE(targetUniform->type);
1101 void Program::dirtyAllUniforms()
1103 size_t numUniforms = uniforms.size();
1104 for(size_t index = 0; index < numUniforms; index++)
1106 uniforms[index]->dirty = true;
1110 // Applies all the uniforms set for this program object to the device
1111 void Program::applyUniforms(Device *device)
1113 GLint numUniforms = static_cast<GLint>(uniformIndex.size());
1114 for(GLint location = 0; location < numUniforms; location++)
1116 if((uniformIndex[location].element != 0) || (uniformIndex[location].index == GL_INVALID_INDEX))
1121 Uniform *targetUniform = uniforms[uniformIndex[location].index];
1123 if(targetUniform->dirty && (targetUniform->blockInfo.index == -1))
1125 GLsizei size = targetUniform->size();
1126 GLfloat *f = (GLfloat*)targetUniform->data;
1127 GLint *i = (GLint*)targetUniform->data;
1128 GLuint *ui = (GLuint*)targetUniform->data;
1129 GLboolean *b = (GLboolean*)targetUniform->data;
1131 switch(targetUniform->type)
1133 case GL_BOOL: applyUniform1bv(device, location, size, b); break;
1134 case GL_BOOL_VEC2: applyUniform2bv(device, location, size, b); break;
1135 case GL_BOOL_VEC3: applyUniform3bv(device, location, size, b); break;
1136 case GL_BOOL_VEC4: applyUniform4bv(device, location, size, b); break;
1137 case GL_FLOAT: applyUniform1fv(device, location, size, f); break;
1138 case GL_FLOAT_VEC2: applyUniform2fv(device, location, size, f); break;
1139 case GL_FLOAT_VEC3: applyUniform3fv(device, location, size, f); break;
1140 case GL_FLOAT_VEC4: applyUniform4fv(device, location, size, f); break;
1141 case GL_FLOAT_MAT2: applyUniformMatrix2fv(device, location, size, f); break;
1142 case GL_FLOAT_MAT2x3: applyUniformMatrix2x3fv(device, location, size, f); break;
1143 case GL_FLOAT_MAT2x4: applyUniformMatrix2x4fv(device, location, size, f); break;
1144 case GL_FLOAT_MAT3x2: applyUniformMatrix3x2fv(device, location, size, f); break;
1145 case GL_FLOAT_MAT3: applyUniformMatrix3fv(device, location, size, f); break;
1146 case GL_FLOAT_MAT3x4: applyUniformMatrix3x4fv(device, location, size, f); break;
1147 case GL_FLOAT_MAT4x2: applyUniformMatrix4x2fv(device, location, size, f); break;
1148 case GL_FLOAT_MAT4x3: applyUniformMatrix4x3fv(device, location, size, f); break;
1149 case GL_FLOAT_MAT4: applyUniformMatrix4fv(device, location, size, f); break;
1151 case GL_SAMPLER_CUBE:
1152 case GL_SAMPLER_EXTERNAL_OES:
1153 case GL_SAMPLER_3D_OES:
1154 case GL_SAMPLER_2D_ARRAY:
1155 case GL_SAMPLER_2D_SHADOW:
1156 case GL_SAMPLER_CUBE_SHADOW:
1157 case GL_SAMPLER_2D_ARRAY_SHADOW:
1158 case GL_INT_SAMPLER_2D:
1159 case GL_UNSIGNED_INT_SAMPLER_2D:
1160 case GL_INT_SAMPLER_CUBE:
1161 case GL_UNSIGNED_INT_SAMPLER_CUBE:
1162 case GL_INT_SAMPLER_3D:
1163 case GL_UNSIGNED_INT_SAMPLER_3D:
1164 case GL_INT_SAMPLER_2D_ARRAY:
1165 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
1166 case GL_INT: applyUniform1iv(device, location, size, i); break;
1167 case GL_INT_VEC2: applyUniform2iv(device, location, size, i); break;
1168 case GL_INT_VEC3: applyUniform3iv(device, location, size, i); break;
1169 case GL_INT_VEC4: applyUniform4iv(device, location, size, i); break;
1170 case GL_UNSIGNED_INT: applyUniform1uiv(device, location, size, ui); break;
1171 case GL_UNSIGNED_INT_VEC2: applyUniform2uiv(device, location, size, ui); break;
1172 case GL_UNSIGNED_INT_VEC3: applyUniform3uiv(device, location, size, ui); break;
1173 case GL_UNSIGNED_INT_VEC4: applyUniform4uiv(device, location, size, ui); break;
1175 UNREACHABLE(targetUniform->type);
1178 targetUniform->dirty = false;
1183 void Program::applyUniformBuffers(Device *device, BufferBinding* uniformBuffers)
1185 GLint vertexUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
1186 GLint fragmentUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
1188 for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++)
1190 vertexUniformBuffers[bufferBindingIndex] = -1;
1193 for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++)
1195 fragmentUniformBuffers[bufferBindingIndex] = -1;
1198 int vertexUniformBufferIndex = 0;
1199 int fragmentUniformBufferIndex = 0;
1200 for(unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size(); uniformBlockIndex++)
1202 UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
1204 // Unnecessary to apply an unreferenced standard or shared UBO
1205 if(!uniformBlock.isReferencedByVertexShader() && !uniformBlock.isReferencedByFragmentShader())
1210 GLuint blockBinding = uniformBlockBindings[uniformBlockIndex];
1212 if(uniformBlock.isReferencedByVertexShader())
1214 vertexUniformBuffers[vertexUniformBufferIndex++] = blockBinding;
1217 if(uniformBlock.isReferencedByFragmentShader())
1219 fragmentUniformBuffers[fragmentUniformBufferIndex++] = blockBinding;
1223 for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++)
1225 int index = vertexUniformBuffers[bufferBindingIndex];
1226 Buffer* vsBuffer = (index != -1) ? (Buffer*)uniformBuffers[index].get() : nullptr;
1227 device->VertexProcessor::setUniformBuffer(bufferBindingIndex,
1228 vsBuffer ? vsBuffer->getResource() : nullptr, (index != -1) ? uniformBuffers[index].getOffset() : 0);
1229 index = fragmentUniformBuffers[bufferBindingIndex];
1230 Buffer* psBuffer = (index != -1) ? (Buffer*)uniformBuffers[index].get() : nullptr;
1231 device->PixelProcessor::setUniformBuffer(bufferBindingIndex,
1232 psBuffer ? psBuffer->getResource() : nullptr, (index != -1) ? uniformBuffers[index].getOffset() : 0);
1236 void Program::applyTransformFeedback(Device *device, TransformFeedback* transformFeedback)
1238 // Make sure the flags will fit in a 64 bit unsigned int variable
1239 ASSERT(sw::max<int>(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS) <= 64);
1241 BufferBinding* transformFeedbackBuffers = (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) ? transformFeedback->getBuffers() : nullptr;
1243 uint64_t enableTransformFeedback = 0;
1244 if(!transformFeedbackBuffers)
1246 for(unsigned int index = 0; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index)
1248 device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0);
1250 device->VertexProcessor::enableTransformFeedback(enableTransformFeedback);
1254 unsigned int maxVaryings = static_cast<unsigned int>(transformFeedbackLinkedVaryings.size());
1255 switch(transformFeedbackBufferMode)
1257 case GL_SEPARATE_ATTRIBS:
1259 maxVaryings = sw::min(maxVaryings, (unsigned int)MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
1260 // Attribs go to separate buffers
1261 for(unsigned int index = 0; index < maxVaryings; ++index)
1263 int size = transformFeedbackLinkedVaryings[index].size;
1264 int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type);
1265 int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type);
1266 int nbRegs = rowCount > 1 ? colCount * size : size;
1267 int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount;
1268 int componentStride = rowCount * colCount * size;
1269 int baseOffset = transformFeedback->vertexOffset() * componentStride * sizeof(float);
1270 device->VertexProcessor::setTransformFeedbackBuffer(index,
1271 transformFeedbackBuffers[index].get()->getResource(),
1272 transformFeedbackBuffers[index].getOffset() + baseOffset,
1273 transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col,
1274 nbRegs, nbComponentsPerReg, componentStride);
1275 enableTransformFeedback |= 1ULL << index;
1279 case GL_INTERLEAVED_ATTRIBS:
1281 // OpenGL ES 3.0.4 spec, section 2.15.2:
1282 // In INTERLEAVED_ATTRIBS mode, the values of one or more output variables
1283 // written by a vertex shader are written, interleaved, into the buffer object
1284 // bound to the first transform feedback binding point (index = 0).
1285 sw::Resource* resource = transformFeedbackBuffers[0].get()->getResource();
1286 int componentStride = static_cast<int>(totalLinkedVaryingsComponents);
1287 int baseOffset = transformFeedbackBuffers[0].getOffset() + (transformFeedback->vertexOffset() * componentStride * sizeof(float));
1288 maxVaryings = sw::min(maxVaryings, (unsigned int)sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
1289 int totalComponents = 0;
1290 for(unsigned int index = 0; index < maxVaryings; ++index)
1292 int size = transformFeedbackLinkedVaryings[index].size;
1293 int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type);
1294 int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type);
1295 int nbRegs = rowCount > 1 ? colCount * size : size;
1296 int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount;
1297 device->VertexProcessor::setTransformFeedbackBuffer(index, resource,
1298 baseOffset + (totalComponents * sizeof(float)),
1299 transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col,
1300 nbRegs, nbComponentsPerReg, componentStride);
1301 totalComponents += rowCount * colCount * size;
1302 enableTransformFeedback |= 1ULL << index;
1307 UNREACHABLE(transformFeedbackBufferMode);
1311 // Unset all other transform feedback buffers
1312 for(unsigned int index = maxVaryings; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index)
1314 device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0);
1317 device->VertexProcessor::enableTransformFeedback(enableTransformFeedback);
1320 bool Program::linkVaryings()
1322 for(glsl::VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); ++input)
1324 bool matched = false;
1326 for(glsl::VaryingList::iterator output = vertexShader->varyings.begin(); output != vertexShader->varyings.end(); ++output)
1328 if(output->name == input->name)
1330 if(output->type != input->type || output->size() != input->size())
1332 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
1344 appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
1350 glsl::VaryingList &psVaryings = fragmentShader->varyings;
1351 glsl::VaryingList &vsVaryings = vertexShader->varyings;
1353 for(glsl::VaryingList::iterator output = vsVaryings.begin(); output != vsVaryings.end(); ++output)
1355 bool matched = false;
1357 for(glsl::VaryingList::iterator input = psVaryings.begin(); input != psVaryings.end(); ++input)
1359 if(output->name == input->name)
1361 int in = input->reg;
1362 int out = output->reg;
1363 int components = VariableRegisterSize(output->type);
1364 int registers = VariableRegisterCount(output->type) * output->size();
1368 if(in + registers > MAX_VARYING_VECTORS)
1370 appendToInfoLog("Too many varyings");
1376 if(out + registers > MAX_VARYING_VECTORS)
1378 appendToInfoLog("Too many varyings");
1382 for(int i = 0; i < registers; i++)
1384 vertexBinary->setOutput(out + i, components, sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i, pixelBinary->getInput(in + i, 0).flat));
1387 else // Vertex varying is declared but not written to
1389 for(int i = 0; i < registers; i++)
1391 pixelBinary->setInput(in + i, components, sw::Shader::Semantic());
1402 // For openGL ES 3.0, we need to still add the vertex shader outputs for unmatched varyings, for transform feedback.
1403 for(const std::string &indexedTfVaryingName : transformFeedbackVaryings)
1405 std::string tfVaryingName = es2::ParseUniformName(indexedTfVaryingName, nullptr);
1407 if(tfVaryingName == output->name)
1409 int out = output->reg;
1410 int components = VariableRegisterSize(output->type);
1411 int registers = VariableRegisterCount(output->type) * output->size();
1415 if(out + registers > MAX_VARYING_VECTORS)
1417 appendToInfoLog("Too many varyings");
1421 for(int i = 0; i < registers; i++)
1423 vertexBinary->setOutput(out + i, components, sw::Shader::Semantic(sw::Shader::USAGE_COLOR));
1435 bool Program::linkTransformFeedback()
1437 size_t totalComponents = 0;
1438 totalLinkedVaryingsComponents = 0;
1440 std::set<std::string> uniqueNames;
1442 for(const std::string &indexedTfVaryingName : transformFeedbackVaryings)
1444 unsigned int subscript = GL_INVALID_INDEX;
1445 std::string tfVaryingName = es2::ParseUniformName(indexedTfVaryingName, &subscript);
1446 bool hasSubscript = (subscript != GL_INVALID_INDEX);
1448 if(tfVaryingName.find('[') != std::string::npos)
1450 appendToInfoLog("Capture of array sub-elements is undefined and not supported.");
1455 for(const glsl::Varying varying : vertexShader->varyings)
1457 if(tfVaryingName == varying.name)
1459 if(uniqueNames.count(indexedTfVaryingName) > 0)
1461 appendToInfoLog("Two transform feedback varyings specify the same output variable (%s)", indexedTfVaryingName.c_str());
1464 uniqueNames.insert(indexedTfVaryingName);
1466 if(hasSubscript && ((static_cast<int>(subscript)) >= varying.size()))
1468 appendToInfoLog("Specified transform feedback varying index out of bounds (%s)", indexedTfVaryingName.c_str());
1472 int size = hasSubscript ? 1 : varying.size();
1474 int rowCount = VariableRowCount(varying.type);
1475 int colCount = VariableColumnCount(varying.type);
1476 int componentCount = rowCount * colCount * size;
1477 if(transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
1478 componentCount > sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS)
1480 appendToInfoLog("Transform feedback varying's %s components (%d) exceed the maximum separate components (%d).",
1481 varying.name.c_str(), componentCount, sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
1485 totalComponents += componentCount;
1487 int reg = varying.reg;
1490 reg += rowCount > 1 ? colCount * subscript : subscript;
1492 int col = varying.col;
1493 if(tfVaryingName == "gl_PointSize")
1495 // Point size is stored in the y element of the vector, not the x element
1496 col = 1; // FIXME: varying.col could already contain this information
1498 transformFeedbackLinkedVaryings.push_back(LinkedVarying(varying.name, varying.type, size, reg, col));
1507 appendToInfoLog("Transform feedback varying %s does not exist in the vertex shader.", tfVaryingName.c_str());
1512 if(transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
1513 totalComponents > sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS)
1515 appendToInfoLog("Transform feedback varying total components (%d) exceed the maximum separate components (%d).",
1516 totalComponents, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
1520 totalLinkedVaryingsComponents = totalComponents;
1525 // Links the code of the vertex and pixel shader by matching up their varyings,
1526 // compiling them into binaries, determining the attribute mappings, and collecting
1527 // a list of uniforms
1528 void Program::link()
1532 resetUniformBlockBindings();
1534 if(!fragmentShader || !fragmentShader->isCompiled())
1539 if(!vertexShader || !vertexShader->isCompiled())
1544 vertexBinary = new sw::VertexShader(vertexShader->getVertexShader());
1545 pixelBinary = new sw::PixelShader(fragmentShader->getPixelShader());
1552 if(!linkAttributes())
1557 // Link uniform blocks before uniforms to make it easy to assign block indices to fields
1558 if(!linkUniformBlocks(vertexShader, fragmentShader))
1563 if(!linkUniforms(fragmentShader))
1568 if(!linkUniforms(vertexShader))
1573 if(!linkTransformFeedback())
1578 linked = true; // Success
1581 // Determines the mapping between GL attributes and vertex stream usage indices
1582 bool Program::linkAttributes()
1584 unsigned int usedLocations = 0;
1586 // Link attributes that have a binding location
1587 for(glsl::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); ++attribute)
1589 int location = getAttributeBinding(*attribute);
1591 if(location != -1) // Set by glBindAttribLocation
1593 int rows = VariableRegisterCount(attribute->type);
1595 if(rows + location > MAX_VERTEX_ATTRIBS)
1597 appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
1601 // In GLSL 3.00, attribute aliasing produces a link error
1602 // In GLSL 1.00, attribute aliasing is allowed
1603 if(egl::getClientVersion() >= 3)
1605 for(int i = 0; i < rows; i++)
1607 if(!linkedAttribute[location + i].name.empty())
1609 appendToInfoLog("Attribute '%s' aliases attribute '%s' at location %d", attribute->name.c_str(), linkedAttribute[location].name.c_str(), location);
1615 for(int i = 0; i < rows; i++)
1617 linkedAttribute[location + i] = *attribute;
1618 usedLocations |= 1 << (location + i);
1623 // Link attributes that don't have a binding location
1624 for(glsl::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); ++attribute)
1626 int location = getAttributeBinding(*attribute);
1628 if(location == -1) // Not set by glBindAttribLocation
1630 int rows = VariableRegisterCount(attribute->type);
1631 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
1633 if(availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
1635 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
1636 return false; // Fail to link
1639 for(int i = 0; i < rows; i++)
1641 linkedAttribute[availableIndex + i] = *attribute;
1646 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
1648 int index = vertexShader->getSemanticIndex(linkedAttribute[attributeIndex].name);
1649 int rows = std::max(VariableRegisterCount(linkedAttribute[attributeIndex].type), 1);
1651 for(int r = 0; r < rows; r++)
1653 attributeStream[attributeIndex++] = index++;
1660 int Program::getAttributeBinding(const glsl::Attribute &attribute)
1662 if(attribute.location != -1)
1664 return attribute.location;
1667 for(int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
1669 if(attributeBinding[location].find(attribute.name.c_str()) != attributeBinding[location].end())
1678 bool Program::linkUniforms(const Shader *shader)
1680 const glsl::ActiveUniforms &activeUniforms = shader->activeUniforms;
1682 for(unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
1684 const glsl::Uniform &uniform = activeUniforms[uniformIndex];
1686 unsigned int blockIndex = GL_INVALID_INDEX;
1687 if(uniform.blockId >= 0)
1689 const glsl::ActiveUniformBlocks &activeUniformBlocks = shader->activeUniformBlocks;
1690 ASSERT(static_cast<size_t>(uniform.blockId) < activeUniformBlocks.size());
1691 blockIndex = getUniformBlockIndex(activeUniformBlocks[uniform.blockId].name);
1692 ASSERT(blockIndex != GL_INVALID_INDEX);
1694 if(!defineUniform(shader->getType(), uniform.type, uniform.precision, uniform.name, uniform.arraySize, uniform.registerIndex, Uniform::BlockInfo(uniform, blockIndex)))
1703 bool Program::defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, int registerIndex, const Uniform::BlockInfo& blockInfo)
1705 if(IsSamplerUniform(type))
1707 int index = registerIndex;
1711 if(shader == GL_VERTEX_SHADER)
1713 if(index < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
1715 samplersVS[index].active = true;
1719 default: UNREACHABLE(type);
1720 case GL_INT_SAMPLER_2D:
1721 case GL_UNSIGNED_INT_SAMPLER_2D:
1722 case GL_SAMPLER_2D_SHADOW:
1723 case GL_SAMPLER_2D: samplersVS[index].textureType = TEXTURE_2D; break;
1724 case GL_INT_SAMPLER_CUBE:
1725 case GL_UNSIGNED_INT_SAMPLER_CUBE:
1726 case GL_SAMPLER_CUBE_SHADOW:
1727 case GL_SAMPLER_CUBE: samplersVS[index].textureType = TEXTURE_CUBE; break;
1728 case GL_INT_SAMPLER_3D:
1729 case GL_UNSIGNED_INT_SAMPLER_3D:
1730 case GL_SAMPLER_3D_OES: samplersVS[index].textureType = TEXTURE_3D; break;
1731 case GL_SAMPLER_EXTERNAL_OES: samplersVS[index].textureType = TEXTURE_EXTERNAL; break;
1732 case GL_INT_SAMPLER_2D_ARRAY:
1733 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
1734 case GL_SAMPLER_2D_ARRAY_SHADOW:
1735 case GL_SAMPLER_2D_ARRAY: samplersVS[index].textureType = TEXTURE_2D_ARRAY; break;
1738 samplersVS[index].logicalTextureUnit = 0;
1742 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", MAX_VERTEX_TEXTURE_IMAGE_UNITS);
1746 else if(shader == GL_FRAGMENT_SHADER)
1748 if(index < MAX_TEXTURE_IMAGE_UNITS)
1750 samplersPS[index].active = true;
1754 default: UNREACHABLE(type);
1755 case GL_INT_SAMPLER_2D:
1756 case GL_UNSIGNED_INT_SAMPLER_2D:
1757 case GL_SAMPLER_2D_SHADOW:
1758 case GL_SAMPLER_2D: samplersPS[index].textureType = TEXTURE_2D; break;
1759 case GL_INT_SAMPLER_CUBE:
1760 case GL_UNSIGNED_INT_SAMPLER_CUBE:
1761 case GL_SAMPLER_CUBE_SHADOW:
1762 case GL_SAMPLER_CUBE: samplersPS[index].textureType = TEXTURE_CUBE; break;
1763 case GL_INT_SAMPLER_3D:
1764 case GL_UNSIGNED_INT_SAMPLER_3D:
1765 case GL_SAMPLER_3D_OES: samplersPS[index].textureType = TEXTURE_3D; break;
1766 case GL_SAMPLER_EXTERNAL_OES: samplersPS[index].textureType = TEXTURE_EXTERNAL; break;
1767 case GL_INT_SAMPLER_2D_ARRAY:
1768 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
1769 case GL_SAMPLER_2D_ARRAY_SHADOW:
1770 case GL_SAMPLER_2D_ARRAY: samplersPS[index].textureType = TEXTURE_2D_ARRAY; break;
1773 samplersPS[index].logicalTextureUnit = 0;
1777 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1781 else UNREACHABLE(shader);
1785 while(index < registerIndex + static_cast<int>(arraySize));
1788 Uniform *uniform = 0;
1789 GLint location = getUniformLocation(name);
1791 if(location >= 0) // Previously defined, types must match
1793 uniform = uniforms[uniformIndex[location].index];
1795 if(uniform->type != type)
1797 appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
1801 if(uniform->precision != precision)
1803 appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
1809 uniform = new Uniform(type, precision, name, arraySize, blockInfo);
1817 if(shader == GL_VERTEX_SHADER)
1819 uniform->vsRegisterIndex = registerIndex;
1821 else if(shader == GL_FRAGMENT_SHADER)
1823 uniform->psRegisterIndex = registerIndex;
1825 else UNREACHABLE(shader);
1827 if(!isUniformDefined(name))
1829 uniforms.push_back(uniform);
1830 unsigned int index = (blockInfo.index == -1) ? static_cast<unsigned int>(uniforms.size() - 1) : GL_INVALID_INDEX;
1832 for(int i = 0; i < uniform->size(); i++)
1834 uniformIndex.push_back(UniformLocation(name, i, index));
1838 if(shader == GL_VERTEX_SHADER)
1840 if(registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)
1842 appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);
1846 else if(shader == GL_FRAGMENT_SHADER)
1848 if(registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)
1850 appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);
1854 else UNREACHABLE(shader);
1859 bool Program::areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2)
1861 // validate blocks for the same member types
1862 if(block1.fields.size() != block2.fields.size())
1866 if(block1.arraySize != block2.arraySize)
1870 if(block1.layout != block2.layout || block1.isRowMajorLayout != block2.isRowMajorLayout)
1874 const size_t numBlockMembers = block1.fields.size();
1875 for(size_t blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
1877 const glsl::Uniform& member1 = shader1->activeUniforms[block1.fields[blockMemberIndex]];
1878 const glsl::Uniform& member2 = shader2->activeUniforms[block2.fields[blockMemberIndex]];
1879 if(member1.name != member2.name ||
1880 member1.arraySize != member2.arraySize ||
1881 member1.precision != member2.precision ||
1882 member1.type != member2.type)
1890 bool Program::linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader)
1892 const glsl::ActiveUniformBlocks &vertexUniformBlocks = vertexShader->activeUniformBlocks;
1893 const glsl::ActiveUniformBlocks &fragmentUniformBlocks = fragmentShader->activeUniformBlocks;
1894 // Check that interface blocks defined in the vertex and fragment shaders are identical
1895 typedef std::map<std::string, const glsl::UniformBlock*> UniformBlockMap;
1896 UniformBlockMap linkedUniformBlocks;
1897 for(unsigned int blockIndex = 0; blockIndex < vertexUniformBlocks.size(); blockIndex++)
1899 const glsl::UniformBlock &vertexUniformBlock = vertexUniformBlocks[blockIndex];
1900 linkedUniformBlocks[vertexUniformBlock.name] = &vertexUniformBlock;
1902 for(unsigned int blockIndex = 0; blockIndex < fragmentUniformBlocks.size(); blockIndex++)
1904 const glsl::UniformBlock &fragmentUniformBlock = fragmentUniformBlocks[blockIndex];
1905 UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentUniformBlock.name);
1906 if(entry != linkedUniformBlocks.end())
1908 const glsl::UniformBlock &vertexUniformBlock = *entry->second;
1909 if(!areMatchingUniformBlocks(vertexUniformBlock, fragmentUniformBlock, vertexShader, fragmentShader))
1915 for(unsigned int blockIndex = 0; blockIndex < vertexUniformBlocks.size(); blockIndex++)
1917 const glsl::UniformBlock &uniformBlock = vertexUniformBlocks[blockIndex];
1918 if(!defineUniformBlock(vertexShader, uniformBlock))
1923 for(unsigned int blockIndex = 0; blockIndex < fragmentUniformBlocks.size(); blockIndex++)
1925 const glsl::UniformBlock &uniformBlock = fragmentUniformBlocks[blockIndex];
1926 if(!defineUniformBlock(fragmentShader, uniformBlock))
1934 bool Program::defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block)
1936 GLuint blockIndex = getUniformBlockIndex(block.name);
1938 if(blockIndex == GL_INVALID_INDEX)
1940 const std::vector<int>& fields = block.fields;
1941 std::vector<unsigned int> memberUniformIndexes;
1942 for(size_t i = 0; i < fields.size(); ++i)
1944 memberUniformIndexes.push_back(fields[i]);
1947 if(block.arraySize > 0)
1949 int regIndex = block.registerIndex;
1950 int regInc = block.dataSize / (glsl::BlockLayoutEncoder::BytesPerComponent * glsl::BlockLayoutEncoder::ComponentsPerRegister);
1951 for(unsigned int i = 0; i < block.arraySize; ++i, regIndex += regInc)
1953 uniformBlocks.push_back(new UniformBlock(block.name, i, block.dataSize, memberUniformIndexes));
1954 uniformBlocks[uniformBlocks.size() - 1]->setRegisterIndex(shader->getType(), regIndex);
1959 uniformBlocks.push_back(new UniformBlock(block.name, GL_INVALID_INDEX, block.dataSize, memberUniformIndexes));
1960 uniformBlocks[uniformBlocks.size() - 1]->setRegisterIndex(shader->getType(), block.registerIndex);
1965 int regIndex = block.registerIndex;
1966 int regInc = block.dataSize / (glsl::BlockLayoutEncoder::BytesPerComponent * glsl::BlockLayoutEncoder::ComponentsPerRegister);
1967 int nbBlocks = (block.arraySize > 0) ? block.arraySize : 1;
1968 for(int i = 0; i < nbBlocks; ++i, regIndex += regInc)
1970 uniformBlocks[blockIndex + i]->setRegisterIndex(shader->getType(), regIndex);
1977 bool Program::applyUniform(Device *device, GLint location, float* data)
1979 Uniform *targetUniform = uniforms[uniformIndex[location].index];
1981 if(targetUniform->psRegisterIndex != -1)
1983 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, data, targetUniform->registerCount());
1986 if(targetUniform->vsRegisterIndex != -1)
1988 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, data, targetUniform->registerCount());
1994 bool Program::applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
1996 int vector[MAX_UNIFORM_VECTORS][4];
1998 for(int i = 0; i < count; i++)
2000 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2008 return applyUniform(device, location, (float*)vector);
2011 bool Program::applyUniform2bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
2013 int vector[MAX_UNIFORM_VECTORS][4];
2015 for(int i = 0; i < count; i++)
2017 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2018 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2025 return applyUniform(device, location, (float*)vector);
2028 bool Program::applyUniform3bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
2030 int vector[MAX_UNIFORM_VECTORS][4];
2032 for(int i = 0; i < count; i++)
2034 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2035 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2036 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2042 return applyUniform(device, location, (float*)vector);
2045 bool Program::applyUniform4bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
2047 int vector[MAX_UNIFORM_VECTORS][4];
2049 for(int i = 0; i < count; i++)
2051 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2052 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2053 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2054 vector[i][3] = (v[3] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2059 return applyUniform(device, location, (float*)vector);
2062 bool Program::applyUniform1fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2064 float vector[MAX_UNIFORM_VECTORS][4];
2066 for(int i = 0; i < count; i++)
2068 vector[i][0] = v[0];
2076 return applyUniform(device, location, (float*)vector);
2079 bool Program::applyUniform2fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2081 float vector[MAX_UNIFORM_VECTORS][4];
2083 for(int i = 0; i < count; i++)
2085 vector[i][0] = v[0];
2086 vector[i][1] = v[1];
2093 return applyUniform(device, location, (float*)vector);
2096 bool Program::applyUniform3fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2098 float vector[MAX_UNIFORM_VECTORS][4];
2100 for(int i = 0; i < count; i++)
2102 vector[i][0] = v[0];
2103 vector[i][1] = v[1];
2104 vector[i][2] = v[2];
2110 return applyUniform(device, location, (float*)vector);
2113 bool Program::applyUniform4fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2115 return applyUniform(device, location, (float*)v);
2118 bool Program::applyUniformMatrix2fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2120 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
2122 for(int i = 0; i < count; i++)
2124 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0;
2125 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0;
2130 return applyUniform(device, location, (float*)matrix);
2133 bool Program::applyUniformMatrix2x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2135 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
2137 for(int i = 0; i < count; i++)
2139 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0;
2140 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0;
2145 return applyUniform(device, location, (float*)matrix);
2148 bool Program::applyUniformMatrix2x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2150 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
2152 for(int i = 0; i < count; i++)
2154 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = value[3];
2155 matrix[i][1][0] = value[4]; matrix[i][1][1] = value[5]; matrix[i][1][2] = value[6]; matrix[i][1][3] = value[7];
2160 return applyUniform(device, location, (float*)matrix);
2163 bool Program::applyUniformMatrix3fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2165 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
2167 for(int i = 0; i < count; i++)
2169 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0;
2170 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0;
2171 matrix[i][2][0] = value[6]; matrix[i][2][1] = value[7]; matrix[i][2][2] = value[8]; matrix[i][2][3] = 0;
2176 return applyUniform(device, location, (float*)matrix);
2179 bool Program::applyUniformMatrix3x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2181 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
2183 for(int i = 0; i < count; i++)
2185 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0;
2186 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0;
2187 matrix[i][2][0] = value[4]; matrix[i][2][1] = value[5]; matrix[i][2][2] = 0; matrix[i][2][3] = 0;
2192 return applyUniform(device, location, (float*)matrix);
2195 bool Program::applyUniformMatrix3x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2197 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
2199 for(int i = 0; i < count; i++)
2201 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = value[3];
2202 matrix[i][1][0] = value[4]; matrix[i][1][1] = value[5]; matrix[i][1][2] = value[6]; matrix[i][1][3] = value[7];
2203 matrix[i][2][0] = value[8]; matrix[i][2][1] = value[9]; matrix[i][2][2] = value[10]; matrix[i][2][3] = value[11];
2208 return applyUniform(device, location, (float*)matrix);
2211 bool Program::applyUniformMatrix4fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2213 return applyUniform(device, location, (float*)value);
2216 bool Program::applyUniformMatrix4x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2218 float matrix[(MAX_UNIFORM_VECTORS + 3) / 4][4][4];
2220 for(int i = 0; i < count; i++)
2222 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0;
2223 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0;
2224 matrix[i][2][0] = value[4]; matrix[i][2][1] = value[5]; matrix[i][2][2] = 0; matrix[i][2][3] = 0;
2225 matrix[i][3][0] = value[6]; matrix[i][3][1] = value[7]; matrix[i][3][2] = 0; matrix[i][3][3] = 0;
2230 return applyUniform(device, location, (float*)matrix);
2233 bool Program::applyUniformMatrix4x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2235 float matrix[(MAX_UNIFORM_VECTORS + 3) / 4][4][4];
2237 for(int i = 0; i < count; i++)
2239 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0;
2240 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0;
2241 matrix[i][2][0] = value[6]; matrix[i][2][1] = value[7]; matrix[i][2][2] = value[8]; matrix[i][2][3] = 0;
2242 matrix[i][3][0] = value[9]; matrix[i][3][1] = value[10]; matrix[i][3][2] = value[11]; matrix[i][3][3] = 0;
2247 return applyUniform(device, location, (float*)matrix);
2250 bool Program::applyUniform1iv(Device *device, GLint location, GLsizei count, const GLint *v)
2252 GLint vector[MAX_UNIFORM_VECTORS][4];
2254 for(int i = 0; i < count; i++)
2256 vector[i][0] = v[i];
2262 Uniform *targetUniform = uniforms[uniformIndex[location].index];
2263 if(IsSamplerUniform(targetUniform->type))
2265 if(targetUniform->psRegisterIndex != -1)
2267 for(int i = 0; i < count; i++)
2269 unsigned int samplerIndex = targetUniform->psRegisterIndex + i;
2271 if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
2273 ASSERT(samplersPS[samplerIndex].active);
2274 samplersPS[samplerIndex].logicalTextureUnit = v[i];
2279 if(targetUniform->vsRegisterIndex != -1)
2281 for(int i = 0; i < count; i++)
2283 unsigned int samplerIndex = targetUniform->vsRegisterIndex + i;
2285 if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
2287 ASSERT(samplersVS[samplerIndex].active);
2288 samplersVS[samplerIndex].logicalTextureUnit = v[i];
2295 return applyUniform(device, location, (float*)vector);
2301 bool Program::applyUniform2iv(Device *device, GLint location, GLsizei count, const GLint *v)
2303 GLint vector[MAX_UNIFORM_VECTORS][4];
2305 for(int i = 0; i < count; i++)
2307 vector[i][0] = v[0];
2308 vector[i][1] = v[1];
2315 return applyUniform(device, location, (float*)vector);
2318 bool Program::applyUniform3iv(Device *device, GLint location, GLsizei count, const GLint *v)
2320 GLint vector[MAX_UNIFORM_VECTORS][4];
2322 for(int i = 0; i < count; i++)
2324 vector[i][0] = v[0];
2325 vector[i][1] = v[1];
2326 vector[i][2] = v[2];
2332 return applyUniform(device, location, (float*)vector);
2335 bool Program::applyUniform4iv(Device *device, GLint location, GLsizei count, const GLint *v)
2337 GLint vector[MAX_UNIFORM_VECTORS][4];
2339 for(int i = 0; i < count; i++)
2341 vector[i][0] = v[0];
2342 vector[i][1] = v[1];
2343 vector[i][2] = v[2];
2344 vector[i][3] = v[3];
2349 return applyUniform(device, location, (float*)vector);
2352 bool Program::applyUniform1uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2354 GLuint vector[MAX_UNIFORM_VECTORS][4];
2356 for(int i = 0; i < count; i++)
2358 vector[i][0] = v[i];
2364 Uniform *targetUniform = uniforms[uniformIndex[location].index];
2365 if(IsSamplerUniform(targetUniform->type))
2367 if(targetUniform->psRegisterIndex != -1)
2369 for(int i = 0; i < count; i++)
2371 unsigned int samplerIndex = targetUniform->psRegisterIndex + i;
2373 if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
2375 ASSERT(samplersPS[samplerIndex].active);
2376 samplersPS[samplerIndex].logicalTextureUnit = v[i];
2381 if(targetUniform->vsRegisterIndex != -1)
2383 for(int i = 0; i < count; i++)
2385 unsigned int samplerIndex = targetUniform->vsRegisterIndex + i;
2387 if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
2389 ASSERT(samplersVS[samplerIndex].active);
2390 samplersVS[samplerIndex].logicalTextureUnit = v[i];
2397 return applyUniform(device, location, (float*)vector);
2403 bool Program::applyUniform2uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2405 GLuint vector[MAX_UNIFORM_VECTORS][4];
2407 for(int i = 0; i < count; i++)
2409 vector[i][0] = v[0];
2410 vector[i][1] = v[1];
2417 return applyUniform(device, location, (float*)vector);
2420 bool Program::applyUniform3uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2422 GLuint vector[MAX_UNIFORM_VECTORS][4];
2424 for(int i = 0; i < count; i++)
2426 vector[i][0] = v[0];
2427 vector[i][1] = v[1];
2428 vector[i][2] = v[2];
2434 return applyUniform(device, location, (float*)vector);
2437 bool Program::applyUniform4uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2439 GLuint vector[MAX_UNIFORM_VECTORS][4];
2441 for(int i = 0; i < count; i++)
2443 vector[i][0] = v[0];
2444 vector[i][1] = v[1];
2445 vector[i][2] = v[2];
2446 vector[i][3] = v[3];
2451 return applyUniform(device, location, (float*)vector);
2454 void Program::appendToInfoLog(const char *format, ...)
2464 va_start(vararg, format);
2465 vsnprintf(info, sizeof(info), format, vararg);
2468 size_t infoLength = strlen(info);
2472 infoLog = new char[infoLength + 2];
2473 strcpy(infoLog, info);
2474 strcpy(infoLog + infoLength, "\n");
2478 size_t logLength = strlen(infoLog);
2479 char *newLog = new char[logLength + infoLength + 2];
2480 strcpy(newLog, infoLog);
2481 strcpy(newLog + logLength, info);
2482 strcpy(newLog + logLength + infoLength, "\n");
2489 void Program::resetInfoLog()
2498 // Returns the program object to an unlinked state, before re-linking, or at destruction
2499 void Program::unlink()
2501 delete vertexBinary;
2506 for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
2508 linkedAttribute[index].name.clear();
2509 attributeStream[index] = -1;
2512 for(int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
2514 samplersPS[index].active = false;
2517 for(int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
2519 samplersVS[index].active = false;
2522 while(!uniforms.empty())
2524 delete uniforms.back();
2525 uniforms.pop_back();
2528 while(!uniformBlocks.empty())
2530 delete uniformBlocks.back();
2531 uniformBlocks.pop_back();
2534 uniformIndex.clear();
2535 transformFeedbackLinkedVaryings.clear();
2543 bool Program::isLinked() const
2548 bool Program::isValidated() const
2553 GLint Program::getBinaryLength() const
2559 void Program::release()
2563 if(referenceCount == 0 && orphaned)
2565 resourceManager->deleteProgram(handle);
2569 void Program::addRef()
2574 unsigned int Program::getRefCount() const
2576 return referenceCount;
2579 unsigned int Program::getSerial() const
2584 unsigned int Program::issueSerial()
2586 return currentSerial++;
2589 size_t Program::getInfoLogLength() const
2597 return strlen(infoLog) + 1;
2601 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *buffer)
2609 index = std::min(bufSize - 1, (int)strlen(infoLog));
2610 memcpy(buffer, infoLog, index);
2613 buffer[index] = '\0';
2622 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2626 if(vertexShader && (total < maxCount))
2628 shaders[total++] = vertexShader->getName();
2631 if(fragmentShader && (total < maxCount))
2633 shaders[total++] = fragmentShader->getName();
2642 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2644 // Skip over inactive attributes
2645 unsigned int activeAttribute = 0;
2646 unsigned int attribute;
2647 for(attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2649 if(linkedAttribute[attribute].name.empty())
2654 if(activeAttribute == index)
2664 const char *string = linkedAttribute[attribute].name.c_str();
2666 strncpy(name, string, bufsize);
2667 name[bufsize - 1] = '\0';
2671 *length = static_cast<GLsizei>(strlen(name));
2675 *size = 1; // Always a single 'type' instance
2677 *type = linkedAttribute[attribute].type;
2680 size_t Program::getActiveAttributeCount() const
2684 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2686 if(!linkedAttribute[attributeIndex].name.empty())
2695 GLint Program::getActiveAttributeMaxLength() const
2699 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2701 if(!linkedAttribute[attributeIndex].name.empty())
2703 maxLength = std::max((int)(linkedAttribute[attributeIndex].name.length() + 1), maxLength);
2710 void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2714 std::string string = uniforms[index]->name;
2716 if(uniforms[index]->isArray())
2721 strncpy(name, string.c_str(), bufsize);
2722 name[bufsize - 1] = '\0';
2726 *length = static_cast<GLsizei>(strlen(name));
2730 *size = uniforms[index]->size();
2732 *type = uniforms[index]->type;
2735 size_t Program::getActiveUniformCount() const
2737 return uniforms.size();
2740 GLint Program::getActiveUniformMaxLength() const
2744 size_t numUniforms = uniforms.size();
2745 for(size_t uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
2747 if(!uniforms[uniformIndex]->name.empty())
2749 int length = (int)(uniforms[uniformIndex]->name.length() + 1);
2750 if(uniforms[uniformIndex]->isArray())
2752 length += 3; // Counting in "[0]".
2754 maxLength = std::max(length, maxLength);
2761 GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
2763 const Uniform& uniform = *uniforms[index];
2766 case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
2767 case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.size());
2768 case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
2769 case GL_UNIFORM_BLOCK_INDEX: return uniform.blockInfo.index;
2770 case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset;
2771 case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
2772 case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
2773 case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
2781 void Program::getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const
2783 if(index >= getActiveUniformBlockCount())
2785 return error(GL_INVALID_VALUE);
2788 const UniformBlock &uniformBlock = *uniformBlocks[index];
2792 std::string string = uniformBlock.name;
2794 if(uniformBlock.isArrayElement())
2796 std::ostringstream elementIndex;
2797 elementIndex << uniformBlock.elementIndex;
2798 string += "[" + elementIndex.str() + "]";
2801 strncpy(name, string.c_str(), bufSize);
2802 name[bufSize - 1] = '\0';
2806 *length = static_cast<GLsizei>(strlen(name));
2811 size_t Program::getActiveUniformBlockCount() const
2813 return uniformBlocks.size();
2816 GLint Program::getActiveUniformBlockMaxLength() const
2818 GLint maxLength = 0;
2822 size_t numUniformBlocks = getActiveUniformBlockCount();
2823 for(size_t uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
2825 const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
2826 if(!uniformBlock.name.empty())
2828 GLint length = static_cast<GLint>(uniformBlock.name.length() + 1);
2830 // Counting in "[0]".
2831 const GLint arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
2833 maxLength = std::max(length + arrayLength, maxLength);
2841 void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
2843 transformFeedbackVaryings.resize(count);
2844 for(GLsizei i = 0; i < count; i++)
2846 transformFeedbackVaryings[i] = varyings[i];
2849 transformFeedbackBufferMode = bufferMode;
2852 void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
2856 ASSERT(index < transformFeedbackLinkedVaryings.size());
2857 const LinkedVarying &varying = transformFeedbackLinkedVaryings[index];
2858 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
2861 *length = lastNameIdx;
2865 *size = varying.size;
2869 *type = varying.type;
2873 memcpy(name, varying.name.c_str(), lastNameIdx);
2874 name[lastNameIdx] = '\0';
2879 GLsizei Program::getTransformFeedbackVaryingCount() const
2883 return static_cast<GLsizei>(transformFeedbackLinkedVaryings.size());
2891 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
2895 GLsizei maxSize = 0;
2896 for(size_t i = 0; i < transformFeedbackLinkedVaryings.size(); i++)
2898 const LinkedVarying &varying = transformFeedbackLinkedVaryings[i];
2899 maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
2910 GLenum Program::getTransformFeedbackBufferMode() const
2912 return transformFeedbackBufferMode;
2915 void Program::flagForDeletion()
2920 bool Program::isFlaggedForDeletion() const
2925 void Program::validate(Device* device)
2931 appendToInfoLog("Program has not been successfully linked.");
2936 applyUniforms(device);
2937 if(!validateSamplers(true))
2948 bool Program::validateSamplers(bool logErrors)
2950 // if any two active samplers in a program are of different types, but refer to the same
2951 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2952 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
2954 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
2956 for(unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++)
2958 textureUnitType[i] = TEXTURE_UNKNOWN;
2961 for(unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
2963 if(samplersPS[i].active)
2965 unsigned int unit = samplersPS[i].logicalTextureUnit;
2967 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
2971 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
2977 if(textureUnitType[unit] != TEXTURE_UNKNOWN)
2979 if(samplersPS[i].textureType != textureUnitType[unit])
2983 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2991 textureUnitType[unit] = samplersPS[i].textureType;
2996 for(unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
2998 if(samplersVS[i].active)
3000 unsigned int unit = samplersVS[i].logicalTextureUnit;
3002 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
3006 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
3012 if(textureUnitType[unit] != TEXTURE_UNKNOWN)
3014 if(samplersVS[i].textureType != textureUnitType[unit])
3018 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
3026 textureUnitType[unit] = samplersVS[i].textureType;