1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 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 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 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. 14 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. 17 18 #include "Program.h" 19 20 #include "main.h" 21 #include "Buffer.h" 22 #include "Shader.h" 23 #include "TransformFeedback.h" 24 #include "utilities.h" 25 #include "common/debug.h" 26 #include "Shader/PixelShader.hpp" 27 #include "Shader/VertexShader.hpp" 28 29 #include <algorithm> 30 #include <string> 31 #include <stdlib.h> 32 33 namespace es2 34 { 35 unsigned int Program::currentSerial = 1; 36 str(int i)37 std::string str(int i) 38 { 39 char buffer[20]; 40 sprintf(buffer, "%d", i); 41 return buffer; 42 } 43 BlockInfo(const glsl::Uniform & uniform,int blockIndex)44 Uniform::BlockInfo::BlockInfo(const glsl::Uniform& uniform, int blockIndex) 45 { 46 if(blockIndex >= 0) 47 { 48 index = blockIndex; 49 offset = uniform.blockInfo.offset; 50 arrayStride = uniform.blockInfo.arrayStride; 51 matrixStride = uniform.blockInfo.matrixStride; 52 isRowMajorMatrix = uniform.blockInfo.isRowMajorMatrix; 53 } 54 } 55 Uniform(const glsl::Uniform & uniform,const BlockInfo & blockInfo)56 Uniform::Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo) 57 : type(uniform.type), precision(uniform.precision), name(uniform.name), 58 arraySize(uniform.arraySize), blockInfo(blockInfo), fields(uniform.fields) 59 { 60 if((blockInfo.index == -1) && uniform.fields.empty()) 61 { 62 size_t bytes = UniformTypeSize(type) * size(); 63 data = new unsigned char[bytes]; 64 memset(data, 0, bytes); 65 } 66 } 67 ~Uniform()68 Uniform::~Uniform() 69 { 70 delete[] data; 71 } 72 isArray() const73 bool Uniform::isArray() const 74 { 75 return arraySize >= 1; 76 } 77 size() const78 int Uniform::size() const 79 { 80 return arraySize > 0 ? arraySize : 1; 81 } 82 registerCount() const83 int Uniform::registerCount() const 84 { 85 return size() * VariableRegisterCount(type); 86 } 87 UniformBlock(const std::string & name,unsigned int elementIndex,unsigned int dataSize,std::vector<unsigned int> memberUniformIndexes)88 UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize, std::vector<unsigned int> memberUniformIndexes) : 89 name(name), elementIndex(elementIndex), dataSize(dataSize), memberUniformIndexes(memberUniformIndexes), psRegisterIndex(GL_INVALID_INDEX), vsRegisterIndex(GL_INVALID_INDEX) 90 { 91 } 92 setRegisterIndex(GLenum shader,unsigned int registerIndex)93 void UniformBlock::setRegisterIndex(GLenum shader, unsigned int registerIndex) 94 { 95 switch(shader) 96 { 97 case GL_VERTEX_SHADER: 98 vsRegisterIndex = registerIndex; 99 break; 100 case GL_FRAGMENT_SHADER: 101 psRegisterIndex = registerIndex; 102 break; 103 default: 104 UNREACHABLE(shader); 105 } 106 } 107 isArrayElement() const108 bool UniformBlock::isArrayElement() const 109 { 110 return elementIndex != GL_INVALID_INDEX; 111 } 112 isReferencedByVertexShader() const113 bool UniformBlock::isReferencedByVertexShader() const 114 { 115 return vsRegisterIndex != GL_INVALID_INDEX; 116 } 117 isReferencedByFragmentShader() const118 bool UniformBlock::isReferencedByFragmentShader() const 119 { 120 return psRegisterIndex != GL_INVALID_INDEX; 121 } 122 UniformLocation(const std::string & name,unsigned int element,unsigned int index)123 UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index) 124 { 125 } 126 LinkedVarying()127 LinkedVarying::LinkedVarying() 128 { 129 } 130 LinkedVarying(const std::string & name,GLenum type,GLsizei size,int reg,int col)131 LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col) 132 : name(name), type(type), size(size), reg(reg), col(col) 133 { 134 } 135 Program(ResourceManager * manager,GLuint handle)136 Program::Program(ResourceManager *manager, GLuint handle) : serial(issueSerial()), resourceManager(manager), handle(handle) 137 { 138 fragmentShader = 0; 139 vertexShader = 0; 140 pixelBinary = 0; 141 vertexBinary = 0; 142 143 transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS; 144 totalLinkedVaryingsComponents = 0; 145 146 infoLog = 0; 147 validated = false; 148 149 resetUniformBlockBindings(); 150 unlink(); 151 152 orphaned = false; 153 retrievableBinary = false; 154 referenceCount = 0; 155 } 156 ~Program()157 Program::~Program() 158 { 159 unlink(); 160 161 if(vertexShader) 162 { 163 vertexShader->release(); 164 } 165 166 if(fragmentShader) 167 { 168 fragmentShader->release(); 169 } 170 } 171 attachShader(Shader * shader)172 bool Program::attachShader(Shader *shader) 173 { 174 if(shader->getType() == GL_VERTEX_SHADER) 175 { 176 if(vertexShader) 177 { 178 return false; 179 } 180 181 vertexShader = (VertexShader*)shader; 182 vertexShader->addRef(); 183 } 184 else if(shader->getType() == GL_FRAGMENT_SHADER) 185 { 186 if(fragmentShader) 187 { 188 return false; 189 } 190 191 fragmentShader = (FragmentShader*)shader; 192 fragmentShader->addRef(); 193 } 194 else UNREACHABLE(shader->getType()); 195 196 return true; 197 } 198 detachShader(Shader * shader)199 bool Program::detachShader(Shader *shader) 200 { 201 if(shader->getType() == GL_VERTEX_SHADER) 202 { 203 if(vertexShader != shader) 204 { 205 return false; 206 } 207 208 vertexShader->release(); 209 vertexShader = 0; 210 } 211 else if(shader->getType() == GL_FRAGMENT_SHADER) 212 { 213 if(fragmentShader != shader) 214 { 215 return false; 216 } 217 218 fragmentShader->release(); 219 fragmentShader = 0; 220 } 221 else UNREACHABLE(shader->getType()); 222 223 return true; 224 } 225 getAttachedShadersCount() const226 int Program::getAttachedShadersCount() const 227 { 228 return (vertexShader ? 1 : 0) + (fragmentShader ? 1 : 0); 229 } 230 getPixelShader()231 sw::PixelShader *Program::getPixelShader() 232 { 233 return pixelBinary; 234 } 235 getVertexShader()236 sw::VertexShader *Program::getVertexShader() 237 { 238 return vertexBinary; 239 } 240 getFragDataLocation(const GLchar * name)241 GLint Program::getFragDataLocation(const GLchar *name) 242 { 243 if(name && linked) 244 { 245 std::string baseName(name); 246 unsigned int subscript = GL_INVALID_INDEX; 247 baseName = ParseUniformName(baseName, &subscript); 248 for(auto const &varying : fragmentShader->varyings) 249 { 250 if(varying.qualifier == EvqFragmentOut) 251 { 252 if(varying.name == baseName) 253 { 254 ASSERT(varying.registerIndex >= 0); 255 256 if(subscript == GL_INVALID_INDEX) // No subscript 257 { 258 return varying.registerIndex; 259 } 260 261 int rowCount = VariableRowCount(varying.type); 262 int colCount = VariableColumnCount(varying.type); 263 264 return varying.registerIndex + (rowCount > 1 ? colCount * subscript : subscript); 265 } 266 } 267 } 268 } 269 270 return -1; 271 } 272 bindAttributeLocation(GLuint index,const char * name)273 void Program::bindAttributeLocation(GLuint index, const char *name) 274 { 275 attributeBinding[name] = index; 276 } 277 getAttributeLocation(const char * name)278 GLint Program::getAttributeLocation(const char *name) 279 { 280 return name ? getAttributeLocation(std::string(name)) : -1; 281 } 282 getAttributeStream(int attributeIndex)283 int Program::getAttributeStream(int attributeIndex) 284 { 285 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); 286 287 return attributeStream[attributeIndex]; 288 } 289 290 // 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) getSamplerMapping(sw::SamplerType type,unsigned int samplerIndex)291 GLint Program::getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex) 292 { 293 GLint logicalTextureUnit = -1; 294 295 switch(type) 296 { 297 case sw::SAMPLER_PIXEL: 298 ASSERT(samplerIndex < sizeof(samplersPS) / sizeof(samplersPS[0])); 299 300 if(samplersPS[samplerIndex].active) 301 { 302 logicalTextureUnit = samplersPS[samplerIndex].logicalTextureUnit; 303 } 304 break; 305 case sw::SAMPLER_VERTEX: 306 ASSERT(samplerIndex < sizeof(samplersVS) / sizeof(samplersVS[0])); 307 308 if(samplersVS[samplerIndex].active) 309 { 310 logicalTextureUnit = samplersVS[samplerIndex].logicalTextureUnit; 311 } 312 break; 313 default: UNREACHABLE(type); 314 } 315 316 if(logicalTextureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS) 317 { 318 return logicalTextureUnit; 319 } 320 321 return -1; 322 } 323 324 // Returns the texture type for a given sampler type and index (0-15 for the pixel shader and 0-3 for the vertex shader) getSamplerTextureType(sw::SamplerType type,unsigned int samplerIndex)325 TextureType Program::getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex) 326 { 327 switch(type) 328 { 329 case sw::SAMPLER_PIXEL: 330 ASSERT(samplerIndex < sizeof(samplersPS)/sizeof(samplersPS[0])); 331 ASSERT(samplersPS[samplerIndex].active); 332 return samplersPS[samplerIndex].textureType; 333 case sw::SAMPLER_VERTEX: 334 ASSERT(samplerIndex < sizeof(samplersVS)/sizeof(samplersVS[0])); 335 ASSERT(samplersVS[samplerIndex].active); 336 return samplersVS[samplerIndex].textureType; 337 default: UNREACHABLE(type); 338 } 339 340 return TEXTURE_2D; 341 } 342 getUniform(const std::string & name) const343 Uniform *Program::getUniform(const std::string &name) const 344 { 345 unsigned int subscript = GL_INVALID_INDEX; 346 std::string baseName = es2::ParseUniformName(name, &subscript); 347 348 for(size_t index = 0; index < uniforms.size(); index++) 349 { 350 if(uniforms[index]->name == baseName) 351 { 352 return uniforms[index]; 353 } 354 } 355 356 return nullptr; 357 } 358 getUniformLocation(const std::string & name) const359 GLint Program::getUniformLocation(const std::string &name) const 360 { 361 unsigned int subscript = GL_INVALID_INDEX; 362 std::string baseName = es2::ParseUniformName(name, &subscript); 363 364 for(size_t location = 0; location < uniformIndex.size(); location++) 365 { 366 if(uniformIndex[location].name == baseName) 367 { 368 const unsigned int index = uniformIndex[location].index; 369 370 if(index != GL_INVALID_INDEX) 371 { 372 if(subscript == GL_INVALID_INDEX) 373 { 374 return (GLint)location; 375 } 376 else if(uniforms[index]->isArray()) 377 { 378 if(uniformIndex[location].element == subscript) 379 { 380 return (GLint)location; 381 } 382 } 383 } 384 } 385 } 386 387 return -1; 388 } 389 getUniformIndex(const std::string & name) const390 GLuint Program::getUniformIndex(const std::string &name) const 391 { 392 unsigned int subscript = GL_INVALID_INDEX; 393 std::string baseName = es2::ParseUniformName(name, &subscript); 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 size_t numUniforms = uniforms.size(); 402 for(GLuint index = 0; index < numUniforms; index++) 403 { 404 if(uniforms[index]->name == baseName) 405 { 406 if(uniforms[index]->isArray() || subscript == GL_INVALID_INDEX) 407 { 408 return index; 409 } 410 } 411 } 412 413 return GL_INVALID_INDEX; 414 } 415 getActiveUniformBlockiv(GLuint uniformBlockIndex,GLenum pname,GLint * params) const416 void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const 417 { 418 ASSERT(uniformBlockIndex < getActiveUniformBlockCount()); 419 420 const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex]; 421 422 switch(pname) 423 { 424 case GL_UNIFORM_BLOCK_DATA_SIZE: 425 *params = static_cast<GLint>(uniformBlock.dataSize); 426 break; 427 case GL_UNIFORM_BLOCK_NAME_LENGTH: 428 *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0)); 429 break; 430 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: 431 *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size()); 432 break; 433 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: 434 { 435 for(unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) 436 { 437 params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]); 438 } 439 } 440 break; 441 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: 442 *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader()); 443 break; 444 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: 445 *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader()); 446 break; 447 default: UNREACHABLE(pname); 448 } 449 } 450 getUniformBlockIndex(const std::string & name) const451 GLuint Program::getUniformBlockIndex(const std::string &name) const 452 { 453 unsigned int subscript = GL_INVALID_INDEX; 454 std::string baseName = es2::ParseUniformName(name, &subscript); 455 456 size_t numUniformBlocks = getActiveUniformBlockCount(); 457 for(GLuint blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) 458 { 459 const UniformBlock &uniformBlock = *uniformBlocks[blockIndex]; 460 if(uniformBlock.name == baseName) 461 { 462 const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0); 463 if(subscript == uniformBlock.elementIndex || arrayElementZero) 464 { 465 return blockIndex; 466 } 467 } 468 } 469 470 return GL_INVALID_INDEX; 471 } 472 bindUniformBlock(GLuint uniformBlockIndex,GLuint uniformBlockBinding)473 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) 474 { 475 ASSERT(uniformBlockIndex < getActiveUniformBlockCount()); 476 477 uniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; 478 } 479 getUniformBlockBinding(GLuint uniformBlockIndex) const480 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const 481 { 482 ASSERT(uniformBlockIndex < getActiveUniformBlockCount()); 483 484 return uniformBlockBindings[uniformBlockIndex]; 485 } 486 resetUniformBlockBindings()487 void Program::resetUniformBlockBindings() 488 { 489 for(unsigned int blockId = 0; blockId < MAX_UNIFORM_BUFFER_BINDINGS; blockId++) 490 { 491 uniformBlockBindings[blockId] = 0; 492 } 493 } 494 setUniformfv(GLint location,GLsizei count,const GLfloat * v,int numElements)495 bool Program::setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements) 496 { 497 ASSERT(numElements >= 1 && numElements <= 4); 498 499 static GLenum floatType[] = { GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4 }; 500 static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 }; 501 502 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 503 { 504 return false; 505 } 506 507 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 508 targetUniform->dirty = true; 509 510 int size = targetUniform->size(); 511 512 if(size == 1 && count > 1) 513 { 514 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 515 } 516 517 count = std::min(size - (int)uniformIndex[location].element, count); 518 519 int index = numElements - 1; 520 if(targetUniform->type == floatType[index]) 521 { 522 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat)* numElements, 523 v, numElements * sizeof(GLfloat) * count); 524 } 525 else if(targetUniform->type == boolType[index]) 526 { 527 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * numElements; 528 529 for(int i = 0; i < count * numElements; i++) 530 { 531 boolParams[i] = (v[i] == 0.0f) ? GL_FALSE : GL_TRUE; 532 } 533 } 534 else 535 { 536 return false; 537 } 538 539 return true; 540 } 541 setUniform1fv(GLint location,GLsizei count,const GLfloat * v)542 bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) 543 { 544 return setUniformfv(location, count, v, 1); 545 } 546 setUniform2fv(GLint location,GLsizei count,const GLfloat * v)547 bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) 548 { 549 return setUniformfv(location, count, v, 2); 550 } 551 setUniform3fv(GLint location,GLsizei count,const GLfloat * v)552 bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) 553 { 554 return setUniformfv(location, count, v, 3); 555 } 556 setUniform4fv(GLint location,GLsizei count,const GLfloat * v)557 bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) 558 { 559 return setUniformfv(location, count, v, 4); 560 } 561 setUniformMatrixfv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value,GLenum type)562 bool Program::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum type) 563 { 564 int numElements; 565 switch(type) 566 { 567 case GL_FLOAT_MAT2: 568 numElements = 4; 569 break; 570 case GL_FLOAT_MAT2x3: 571 case GL_FLOAT_MAT3x2: 572 numElements = 6; 573 break; 574 case GL_FLOAT_MAT2x4: 575 case GL_FLOAT_MAT4x2: 576 numElements = 8; 577 break; 578 case GL_FLOAT_MAT3: 579 numElements = 9; 580 break; 581 case GL_FLOAT_MAT3x4: 582 case GL_FLOAT_MAT4x3: 583 numElements = 12; 584 break; 585 case GL_FLOAT_MAT4: 586 numElements = 16; 587 break; 588 default: 589 return false; 590 } 591 592 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 593 { 594 return false; 595 } 596 597 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 598 targetUniform->dirty = true; 599 600 if(targetUniform->type != type) 601 { 602 return false; 603 } 604 605 int size = targetUniform->size(); 606 607 if(size == 1 && count > 1) 608 { 609 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 610 } 611 612 count = std::min(size - (int)uniformIndex[location].element, count); 613 614 GLfloat* dst = reinterpret_cast<GLfloat*>(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * numElements); 615 616 if(transpose == GL_FALSE) 617 { 618 memcpy(dst, value, numElements * sizeof(GLfloat) * count); 619 } 620 else 621 { 622 const int rowSize = VariableRowCount(type); 623 const int colSize = VariableColumnCount(type); 624 for(int n = 0; n < count; ++n) 625 { 626 for(int i = 0; i < colSize; ++i) 627 { 628 for(int j = 0; j < rowSize; ++j) 629 { 630 dst[i * rowSize + j] = value[j * colSize + i]; 631 } 632 } 633 dst += numElements; 634 value += numElements; 635 } 636 } 637 638 639 return true; 640 } 641 setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)642 bool Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 643 { 644 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2); 645 } 646 setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)647 bool Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 648 { 649 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2x3); 650 } 651 setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)652 bool Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 653 { 654 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2x4); 655 } 656 setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)657 bool Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 658 { 659 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3); 660 } 661 setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)662 bool Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 663 { 664 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3x2); 665 } 666 setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)667 bool Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 668 { 669 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3x4); 670 } 671 setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)672 bool Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 673 { 674 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4); 675 } 676 setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)677 bool Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 678 { 679 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4x2); 680 } 681 setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)682 bool Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) 683 { 684 return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4x3); 685 } 686 setUniform1iv(GLint location,GLsizei count,const GLint * v)687 bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v) 688 { 689 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 690 { 691 return false; 692 } 693 694 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 695 targetUniform->dirty = true; 696 697 int size = targetUniform->size(); 698 699 if(size == 1 && count > 1) 700 { 701 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 702 } 703 704 count = std::min(size - (int)uniformIndex[location].element, count); 705 706 if(targetUniform->type == GL_INT || IsSamplerUniform(targetUniform->type)) 707 { 708 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint), 709 v, sizeof(GLint) * count); 710 } 711 else if(targetUniform->type == GL_BOOL) 712 { 713 GLboolean *boolParams = new GLboolean[count]; 714 715 for(int i = 0; i < count; i++) 716 { 717 if(v[i] == 0) 718 { 719 boolParams[i] = GL_FALSE; 720 } 721 else 722 { 723 boolParams[i] = GL_TRUE; 724 } 725 } 726 727 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean), 728 boolParams, sizeof(GLboolean) * count); 729 730 delete[] boolParams; 731 } 732 else 733 { 734 return false; 735 } 736 737 return true; 738 } 739 setUniformiv(GLint location,GLsizei count,const GLint * v,int numElements)740 bool Program::setUniformiv(GLint location, GLsizei count, const GLint *v, int numElements) 741 { 742 static GLenum intType[] = { GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4 }; 743 static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 }; 744 745 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 746 { 747 return false; 748 } 749 750 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 751 targetUniform->dirty = true; 752 753 int size = targetUniform->size(); 754 755 if(size == 1 && count > 1) 756 { 757 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 758 } 759 760 count = std::min(size - (int)uniformIndex[location].element, count); 761 762 int index = numElements - 1; 763 if(targetUniform->type == intType[index]) 764 { 765 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint)* numElements, 766 v, numElements * sizeof(GLint)* count); 767 } 768 else if(targetUniform->type == boolType[index]) 769 { 770 GLboolean *boolParams = new GLboolean[count * numElements]; 771 772 for(int i = 0; i < count * numElements; i++) 773 { 774 boolParams[i] = (v[i] == 0) ? GL_FALSE : GL_TRUE; 775 } 776 777 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean)* numElements, 778 boolParams, numElements * sizeof(GLboolean)* count); 779 780 delete[] boolParams; 781 } 782 else 783 { 784 return false; 785 } 786 787 return true; 788 } 789 setUniform2iv(GLint location,GLsizei count,const GLint * v)790 bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v) 791 { 792 return setUniformiv(location, count, v, 2); 793 } 794 setUniform3iv(GLint location,GLsizei count,const GLint * v)795 bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v) 796 { 797 return setUniformiv(location, count, v, 3); 798 } 799 setUniform4iv(GLint location,GLsizei count,const GLint * v)800 bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v) 801 { 802 return setUniformiv(location, count, v, 4); 803 } 804 setUniform1uiv(GLint location,GLsizei count,const GLuint * v)805 bool Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) 806 { 807 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 808 { 809 return false; 810 } 811 812 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 813 targetUniform->dirty = true; 814 815 int size = targetUniform->size(); 816 817 if(size == 1 && count > 1) 818 { 819 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 820 } 821 822 count = std::min(size - (int)uniformIndex[location].element, count); 823 824 if(targetUniform->type == GL_UNSIGNED_INT) 825 { 826 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLuint), 827 v, sizeof(GLuint)* count); 828 } 829 else if(targetUniform->type == GL_BOOL) 830 { 831 GLboolean *boolParams = new GLboolean[count]; 832 833 for(int i = 0; i < count; i++) 834 { 835 if(v[i] == 0) 836 { 837 boolParams[i] = GL_FALSE; 838 } 839 else 840 { 841 boolParams[i] = GL_TRUE; 842 } 843 } 844 845 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean), 846 boolParams, sizeof(GLboolean)* count); 847 848 delete[] boolParams; 849 } 850 else 851 { 852 return false; 853 } 854 855 return true; 856 } 857 setUniformuiv(GLint location,GLsizei count,const GLuint * v,int numElements)858 bool Program::setUniformuiv(GLint location, GLsizei count, const GLuint *v, int numElements) 859 { 860 static GLenum uintType[] = { GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3, GL_UNSIGNED_INT_VEC4 }; 861 static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 }; 862 863 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 864 { 865 return false; 866 } 867 868 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 869 targetUniform->dirty = true; 870 871 int size = targetUniform->size(); 872 873 if(size == 1 && count > 1) 874 { 875 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 876 } 877 878 count = std::min(size - (int)uniformIndex[location].element, count); 879 880 int index = numElements - 1; 881 if(targetUniform->type == uintType[index]) 882 { 883 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLuint)* numElements, 884 v, numElements * sizeof(GLuint)* count); 885 } 886 else if(targetUniform->type == boolType[index]) 887 { 888 GLboolean *boolParams = new GLboolean[count * numElements]; 889 890 for(int i = 0; i < count * numElements; i++) 891 { 892 boolParams[i] = (v[i] == 0) ? GL_FALSE : GL_TRUE; 893 } 894 895 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean)* numElements, 896 boolParams, numElements * sizeof(GLboolean)* count); 897 898 delete[] boolParams; 899 } 900 else 901 { 902 return false; 903 } 904 905 return true; 906 } 907 setUniform2uiv(GLint location,GLsizei count,const GLuint * v)908 bool Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) 909 { 910 return setUniformuiv(location, count, v, 2); 911 } 912 setUniform3uiv(GLint location,GLsizei count,const GLuint * v)913 bool Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) 914 { 915 return setUniformuiv(location, count, v, 3); 916 } 917 setUniform4uiv(GLint location,GLsizei count,const GLuint * v)918 bool Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) 919 { 920 return setUniformuiv(location, count, v, 4); 921 } 922 getUniformfv(GLint location,GLsizei * bufSize,GLfloat * params)923 bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) 924 { 925 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 926 { 927 return false; 928 } 929 930 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 931 unsigned int count = UniformComponentCount(targetUniform->type); 932 933 // Sized query - ensure the provided buffer is large enough 934 if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLfloat)) 935 { 936 return false; 937 } 938 939 switch(UniformComponentType(targetUniform->type)) 940 { 941 case GL_BOOL: 942 { 943 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * count; 944 945 for(unsigned int i = 0; i < count; i++) 946 { 947 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f; 948 } 949 } 950 break; 951 case GL_FLOAT: 952 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLfloat), 953 count * sizeof(GLfloat)); 954 break; 955 case GL_INT: 956 { 957 GLint *intParams = (GLint*)targetUniform->data + uniformIndex[location].element * count; 958 959 for(unsigned int i = 0; i < count; i++) 960 { 961 params[i] = (float)intParams[i]; 962 } 963 } 964 break; 965 case GL_UNSIGNED_INT: 966 { 967 GLuint *uintParams = (GLuint*)targetUniform->data + uniformIndex[location].element * count; 968 969 for(unsigned int i = 0; i < count; i++) 970 { 971 params[i] = (float)uintParams[i]; 972 } 973 } 974 break; 975 default: UNREACHABLE(targetUniform->type); 976 } 977 978 return true; 979 } 980 getUniformiv(GLint location,GLsizei * bufSize,GLint * params)981 bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) 982 { 983 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 984 { 985 return false; 986 } 987 988 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 989 unsigned int count = UniformComponentCount(targetUniform->type); 990 991 // Sized query - ensure the provided buffer is large enough 992 if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLint)) 993 { 994 return false; 995 } 996 997 switch(UniformComponentType(targetUniform->type)) 998 { 999 case GL_BOOL: 1000 { 1001 GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count; 1002 1003 for(unsigned int i = 0; i < count; i++) 1004 { 1005 params[i] = (GLint)boolParams[i]; 1006 } 1007 } 1008 break; 1009 case GL_FLOAT: 1010 { 1011 GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count; 1012 1013 for(unsigned int i = 0; i < count; i++) 1014 { 1015 params[i] = (GLint)floatParams[i]; 1016 } 1017 } 1018 break; 1019 case GL_INT: 1020 case GL_UNSIGNED_INT: 1021 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLint), 1022 count * sizeof(GLint)); 1023 break; 1024 default: UNREACHABLE(targetUniform->type); 1025 } 1026 1027 return true; 1028 } 1029 getUniformuiv(GLint location,GLsizei * bufSize,GLuint * params)1030 bool Program::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params) 1031 { 1032 if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX)) 1033 { 1034 return false; 1035 } 1036 1037 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1038 unsigned int count = UniformComponentCount(targetUniform->type); 1039 1040 // Sized query - ensure the provided buffer is large enough 1041 if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLuint)) 1042 { 1043 return false; 1044 } 1045 1046 switch(UniformComponentType(targetUniform->type)) 1047 { 1048 case GL_BOOL: 1049 { 1050 GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count; 1051 1052 for(unsigned int i = 0; i < count; i++) 1053 { 1054 params[i] = (GLuint)boolParams[i]; 1055 } 1056 } 1057 break; 1058 case GL_FLOAT: 1059 { 1060 GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count; 1061 1062 for(unsigned int i = 0; i < count; i++) 1063 { 1064 params[i] = (GLuint)floatParams[i]; 1065 } 1066 } 1067 break; 1068 case GL_INT: 1069 case GL_UNSIGNED_INT: 1070 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLuint), 1071 count * sizeof(GLuint)); 1072 break; 1073 default: UNREACHABLE(targetUniform->type); 1074 } 1075 1076 return true; 1077 } 1078 dirtyAllUniforms()1079 void Program::dirtyAllUniforms() 1080 { 1081 size_t numUniforms = uniforms.size(); 1082 for(size_t index = 0; index < numUniforms; index++) 1083 { 1084 uniforms[index]->dirty = true; 1085 } 1086 } 1087 1088 // Applies all the uniforms set for this program object to the device applyUniforms(Device * device)1089 void Program::applyUniforms(Device *device) 1090 { 1091 GLint numUniforms = static_cast<GLint>(uniformIndex.size()); 1092 for(GLint location = 0; location < numUniforms; location++) 1093 { 1094 if((uniformIndex[location].element != 0) || (uniformIndex[location].index == GL_INVALID_INDEX)) 1095 { 1096 continue; 1097 } 1098 1099 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1100 1101 if(targetUniform->dirty && (targetUniform->blockInfo.index == -1)) 1102 { 1103 GLsizei size = targetUniform->size(); 1104 GLfloat *f = (GLfloat*)targetUniform->data; 1105 GLint *i = (GLint*)targetUniform->data; 1106 GLuint *ui = (GLuint*)targetUniform->data; 1107 GLboolean *b = (GLboolean*)targetUniform->data; 1108 1109 switch(targetUniform->type) 1110 { 1111 case GL_BOOL: applyUniform1bv(device, location, size, b); break; 1112 case GL_BOOL_VEC2: applyUniform2bv(device, location, size, b); break; 1113 case GL_BOOL_VEC3: applyUniform3bv(device, location, size, b); break; 1114 case GL_BOOL_VEC4: applyUniform4bv(device, location, size, b); break; 1115 case GL_FLOAT: applyUniform1fv(device, location, size, f); break; 1116 case GL_FLOAT_VEC2: applyUniform2fv(device, location, size, f); break; 1117 case GL_FLOAT_VEC3: applyUniform3fv(device, location, size, f); break; 1118 case GL_FLOAT_VEC4: applyUniform4fv(device, location, size, f); break; 1119 case GL_FLOAT_MAT2: applyUniformMatrix2fv(device, location, size, f); break; 1120 case GL_FLOAT_MAT2x3: applyUniformMatrix2x3fv(device, location, size, f); break; 1121 case GL_FLOAT_MAT2x4: applyUniformMatrix2x4fv(device, location, size, f); break; 1122 case GL_FLOAT_MAT3x2: applyUniformMatrix3x2fv(device, location, size, f); break; 1123 case GL_FLOAT_MAT3: applyUniformMatrix3fv(device, location, size, f); break; 1124 case GL_FLOAT_MAT3x4: applyUniformMatrix3x4fv(device, location, size, f); break; 1125 case GL_FLOAT_MAT4x2: applyUniformMatrix4x2fv(device, location, size, f); break; 1126 case GL_FLOAT_MAT4x3: applyUniformMatrix4x3fv(device, location, size, f); break; 1127 case GL_FLOAT_MAT4: applyUniformMatrix4fv(device, location, size, f); break; 1128 case GL_SAMPLER_2D: 1129 case GL_SAMPLER_CUBE: 1130 case GL_SAMPLER_2D_RECT_ARB: 1131 case GL_SAMPLER_EXTERNAL_OES: 1132 case GL_SAMPLER_3D_OES: 1133 case GL_SAMPLER_2D_ARRAY: 1134 case GL_SAMPLER_2D_SHADOW: 1135 case GL_SAMPLER_CUBE_SHADOW: 1136 case GL_SAMPLER_2D_ARRAY_SHADOW: 1137 case GL_INT_SAMPLER_2D: 1138 case GL_UNSIGNED_INT_SAMPLER_2D: 1139 case GL_INT_SAMPLER_CUBE: 1140 case GL_UNSIGNED_INT_SAMPLER_CUBE: 1141 case GL_INT_SAMPLER_3D: 1142 case GL_UNSIGNED_INT_SAMPLER_3D: 1143 case GL_INT_SAMPLER_2D_ARRAY: 1144 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: 1145 case GL_INT: applyUniform1iv(device, location, size, i); break; 1146 case GL_INT_VEC2: applyUniform2iv(device, location, size, i); break; 1147 case GL_INT_VEC3: applyUniform3iv(device, location, size, i); break; 1148 case GL_INT_VEC4: applyUniform4iv(device, location, size, i); break; 1149 case GL_UNSIGNED_INT: applyUniform1uiv(device, location, size, ui); break; 1150 case GL_UNSIGNED_INT_VEC2: applyUniform2uiv(device, location, size, ui); break; 1151 case GL_UNSIGNED_INT_VEC3: applyUniform3uiv(device, location, size, ui); break; 1152 case GL_UNSIGNED_INT_VEC4: applyUniform4uiv(device, location, size, ui); break; 1153 default: 1154 UNREACHABLE(targetUniform->type); 1155 } 1156 1157 targetUniform->dirty = false; 1158 } 1159 } 1160 } 1161 applyUniformBuffers(Device * device,BufferBinding * uniformBuffers)1162 void Program::applyUniformBuffers(Device *device, BufferBinding* uniformBuffers) 1163 { 1164 GLint vertexUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS]; 1165 GLint fragmentUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS]; 1166 1167 for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++) 1168 { 1169 vertexUniformBuffers[bufferBindingIndex] = -1; 1170 } 1171 1172 for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++) 1173 { 1174 fragmentUniformBuffers[bufferBindingIndex] = -1; 1175 } 1176 1177 int vertexUniformBufferIndex = 0; 1178 int fragmentUniformBufferIndex = 0; 1179 for(unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size(); uniformBlockIndex++) 1180 { 1181 UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex]; 1182 1183 // Unnecessary to apply an unreferenced standard or shared UBO 1184 if(!uniformBlock.isReferencedByVertexShader() && !uniformBlock.isReferencedByFragmentShader()) 1185 { 1186 continue; 1187 } 1188 1189 GLuint blockBinding = uniformBlockBindings[uniformBlockIndex]; 1190 1191 if(uniformBlock.isReferencedByVertexShader()) 1192 { 1193 vertexUniformBuffers[vertexUniformBufferIndex++] = blockBinding; 1194 } 1195 1196 if(uniformBlock.isReferencedByFragmentShader()) 1197 { 1198 fragmentUniformBuffers[fragmentUniformBufferIndex++] = blockBinding; 1199 } 1200 } 1201 1202 for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++) 1203 { 1204 int index = vertexUniformBuffers[bufferBindingIndex]; 1205 Buffer* vsBuffer = (index != -1) ? (Buffer*)uniformBuffers[index].get() : nullptr; 1206 device->VertexProcessor::setUniformBuffer(bufferBindingIndex, 1207 vsBuffer ? vsBuffer->getResource() : nullptr, (index != -1) ? uniformBuffers[index].getOffset() : 0); 1208 index = fragmentUniformBuffers[bufferBindingIndex]; 1209 Buffer* psBuffer = (index != -1) ? (Buffer*)uniformBuffers[index].get() : nullptr; 1210 device->PixelProcessor::setUniformBuffer(bufferBindingIndex, 1211 psBuffer ? psBuffer->getResource() : nullptr, (index != -1) ? uniformBuffers[index].getOffset() : 0); 1212 } 1213 } 1214 applyTransformFeedback(Device * device,TransformFeedback * transformFeedback)1215 void Program::applyTransformFeedback(Device *device, TransformFeedback* transformFeedback) 1216 { 1217 // Make sure the flags will fit in a 64 bit unsigned int variable 1218 ASSERT(sw::max<int>(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS) <= 64); 1219 1220 BufferBinding* transformFeedbackBuffers = (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) ? transformFeedback->getBuffers() : nullptr; 1221 1222 uint64_t enableTransformFeedback = 0; 1223 if(!transformFeedbackBuffers) 1224 { 1225 for(unsigned int index = 0; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index) 1226 { 1227 device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0); 1228 } 1229 device->VertexProcessor::enableTransformFeedback(enableTransformFeedback); 1230 return; 1231 } 1232 1233 unsigned int maxVaryings = static_cast<unsigned int>(transformFeedbackLinkedVaryings.size()); 1234 switch(transformFeedbackBufferMode) 1235 { 1236 case GL_SEPARATE_ATTRIBS: 1237 { 1238 maxVaryings = sw::min(maxVaryings, (unsigned int)MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS); 1239 // Attribs go to separate buffers 1240 for(unsigned int index = 0; index < maxVaryings; ++index) 1241 { 1242 int size = transformFeedbackLinkedVaryings[index].size; 1243 int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type); 1244 int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type); 1245 int nbRegs = rowCount > 1 ? colCount * size : size; 1246 int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount; 1247 int componentStride = rowCount * colCount * size; 1248 int baseOffset = transformFeedback->vertexOffset() * componentStride * sizeof(float); 1249 device->VertexProcessor::setTransformFeedbackBuffer(index, 1250 transformFeedbackBuffers[index].get()->getResource(), 1251 transformFeedbackBuffers[index].getOffset() + baseOffset, 1252 transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col, 1253 nbRegs, nbComponentsPerReg, componentStride); 1254 enableTransformFeedback |= 1ULL << index; 1255 } 1256 } 1257 break; 1258 case GL_INTERLEAVED_ATTRIBS: 1259 { 1260 // OpenGL ES 3.0.4 spec, section 2.15.2: 1261 // In INTERLEAVED_ATTRIBS mode, the values of one or more output variables 1262 // written by a vertex shader are written, interleaved, into the buffer object 1263 // bound to the first transform feedback binding point (index = 0). 1264 sw::Resource* resource = transformFeedbackBuffers[0].get() ? 1265 transformFeedbackBuffers[0].get()->getResource() : 1266 nullptr; 1267 int componentStride = static_cast<int>(totalLinkedVaryingsComponents); 1268 int baseOffset = transformFeedbackBuffers[0].getOffset() + (transformFeedback->vertexOffset() * componentStride * sizeof(float)); 1269 maxVaryings = sw::min(maxVaryings, (unsigned int)sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS); 1270 ASSERT(resource || (maxVaryings == 0)); 1271 1272 int totalComponents = 0; 1273 for(unsigned int index = 0; index < maxVaryings; ++index) 1274 { 1275 int size = transformFeedbackLinkedVaryings[index].size; 1276 int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type); 1277 int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type); 1278 int nbRegs = rowCount > 1 ? colCount * size : size; 1279 int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount; 1280 device->VertexProcessor::setTransformFeedbackBuffer(index, resource, 1281 baseOffset + (totalComponents * sizeof(float)), 1282 transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col, 1283 nbRegs, nbComponentsPerReg, componentStride); 1284 totalComponents += rowCount * colCount * size; 1285 enableTransformFeedback |= 1ULL << index; 1286 } 1287 } 1288 break; 1289 default: 1290 UNREACHABLE(transformFeedbackBufferMode); 1291 break; 1292 } 1293 1294 // Unset all other transform feedback buffers 1295 for(unsigned int index = maxVaryings; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index) 1296 { 1297 device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0); 1298 } 1299 1300 device->VertexProcessor::enableTransformFeedback(enableTransformFeedback); 1301 } 1302 linkVaryings()1303 bool Program::linkVaryings() 1304 { 1305 glsl::VaryingList &psVaryings = fragmentShader->varyings; 1306 glsl::VaryingList &vsVaryings = vertexShader->varyings; 1307 1308 for(auto const &input : psVaryings) 1309 { 1310 bool matched = false; 1311 1312 for(auto const &output : vsVaryings) 1313 { 1314 if(output.name == input.name) 1315 { 1316 if(output.type != input.type || output.size() != input.size()) 1317 { 1318 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output.name.c_str()); 1319 1320 return false; 1321 } 1322 1323 if((output.qualifier == EvqFlatOut) ^ (input.qualifier == EvqFlatIn)) 1324 { 1325 appendToInfoLog("Interpolation qualifiers for %s differ between vertex and fragment shaders", output.name.c_str()); 1326 1327 return false; 1328 } 1329 1330 if(!areMatchingFields(input.fields, output.fields, input.name)) 1331 { 1332 return false; 1333 } 1334 1335 matched = true; 1336 break; 1337 } 1338 } 1339 1340 if(!matched) 1341 { 1342 // If a fragment varying is declared but not statically used, it's not an error to not have a matching vertex varying. 1343 if(input.registerIndex >= 0) 1344 { 1345 appendToInfoLog("Fragment varying %s does not match any vertex varying", input.name.c_str()); 1346 1347 return false; 1348 } 1349 } 1350 } 1351 1352 for(auto const &output : vsVaryings) 1353 { 1354 bool matched = false; 1355 1356 for(auto const &input : psVaryings) 1357 { 1358 if(output.name == input.name) 1359 { 1360 int in = input.registerIndex; 1361 int out = output.registerIndex; 1362 int components = VariableRegisterSize(output.type); 1363 int registers = VariableRegisterCount(output.type) * output.size(); 1364 1365 if(in < 0) // Fragment varying declared but not used 1366 { 1367 continue; 1368 } 1369 1370 if(in + registers >= MAX_VARYING_VECTORS) 1371 { 1372 appendToInfoLog("Too many varyings"); 1373 return false; 1374 } 1375 1376 if(out >= 0) 1377 { 1378 if(out + registers >= MAX_VARYING_VECTORS) 1379 { 1380 appendToInfoLog("Too many varyings"); 1381 return false; 1382 } 1383 1384 for(int i = 0; i < registers; i++) 1385 { 1386 vertexBinary->setOutput(out + i, components, sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i, pixelBinary->getInput(in + i, 0).flat)); 1387 } 1388 } 1389 else // Vertex varying is declared but not written to 1390 { 1391 for(int i = 0; i < registers; i++) 1392 { 1393 pixelBinary->setInput(in + i, components, sw::Shader::Semantic()); 1394 } 1395 } 1396 1397 matched = true; 1398 break; 1399 } 1400 } 1401 1402 if(!matched) 1403 { 1404 // For openGL ES 3.0, we need to still add the vertex shader outputs for unmatched varyings, for transform feedback. 1405 for(const std::string &indexedTfVaryingName : transformFeedbackVaryings) 1406 { 1407 std::string tfVaryingName = es2::ParseUniformName(indexedTfVaryingName, nullptr); 1408 1409 if(tfVaryingName == output.name) 1410 { 1411 int out = output.registerIndex; 1412 int components = VariableRegisterSize(output.type); 1413 int registers = VariableRegisterCount(output.type) * output.size(); 1414 1415 if(out >= 0) 1416 { 1417 if(out + registers >= MAX_VARYING_VECTORS) 1418 { 1419 appendToInfoLog("Too many varyings"); 1420 return false; 1421 } 1422 1423 for(int i = 0; i < registers; i++) 1424 { 1425 vertexBinary->setOutput(out + i, components, sw::Shader::Semantic(sw::Shader::USAGE_COLOR)); 1426 } 1427 } 1428 break; 1429 } 1430 } 1431 } 1432 } 1433 1434 return true; 1435 } 1436 linkTransformFeedback()1437 bool Program::linkTransformFeedback() 1438 { 1439 size_t totalComponents = 0; 1440 totalLinkedVaryingsComponents = 0; 1441 1442 std::set<std::string> uniqueNames; 1443 1444 for(const std::string &indexedTfVaryingName : transformFeedbackVaryings) 1445 { 1446 unsigned int subscript = GL_INVALID_INDEX; 1447 std::string tfVaryingName = es2::ParseUniformName(indexedTfVaryingName, &subscript); 1448 bool hasSubscript = (subscript != GL_INVALID_INDEX); 1449 1450 if(tfVaryingName.find('[') != std::string::npos) 1451 { 1452 appendToInfoLog("Capture of array sub-elements is undefined and not supported."); 1453 return false; 1454 } 1455 1456 bool found = false; 1457 for(const glsl::Varying varying : vertexShader->varyings) 1458 { 1459 if(tfVaryingName == varying.name) 1460 { 1461 if(uniqueNames.count(indexedTfVaryingName) > 0) 1462 { 1463 appendToInfoLog("Two transform feedback varyings specify the same output variable (%s)", indexedTfVaryingName.c_str()); 1464 return false; 1465 } 1466 uniqueNames.insert(indexedTfVaryingName); 1467 1468 if(hasSubscript && ((static_cast<int>(subscript)) >= varying.size())) 1469 { 1470 appendToInfoLog("Specified transform feedback varying index out of bounds (%s)", indexedTfVaryingName.c_str()); 1471 return false; 1472 } 1473 1474 int size = hasSubscript ? 1 : varying.size(); 1475 1476 int rowCount = VariableRowCount(varying.type); 1477 int colCount = VariableColumnCount(varying.type); 1478 int componentCount = rowCount * colCount * size; 1479 if(transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && 1480 componentCount > sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS) 1481 { 1482 appendToInfoLog("Transform feedback varying's %s components (%d) exceed the maximum separate components (%d).", 1483 varying.name.c_str(), componentCount, sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS); 1484 return false; 1485 } 1486 1487 totalComponents += componentCount; 1488 1489 int reg = varying.registerIndex; 1490 if(hasSubscript) 1491 { 1492 reg += rowCount > 1 ? colCount * subscript : subscript; 1493 } 1494 int col = varying.column; 1495 if(tfVaryingName == "gl_PointSize") 1496 { 1497 // Point size is stored in the y element of the vector, not the x element 1498 col = 1; // FIXME: varying.col could already contain this information 1499 } 1500 transformFeedbackLinkedVaryings.push_back(LinkedVarying(varying.name, varying.type, size, reg, col)); 1501 1502 found = true; 1503 break; 1504 } 1505 } 1506 1507 if(!found) 1508 { 1509 appendToInfoLog("Transform feedback varying %s does not exist in the vertex shader.", tfVaryingName.c_str()); 1510 return false; 1511 } 1512 } 1513 1514 if(transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && 1515 totalComponents > sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS) 1516 { 1517 appendToInfoLog("Transform feedback varying total components (%d) exceed the maximum separate components (%d).", 1518 totalComponents, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS); 1519 return false; 1520 } 1521 1522 totalLinkedVaryingsComponents = totalComponents; 1523 1524 return true; 1525 } 1526 1527 // Links the code of the vertex and pixel shader by matching up their varyings, 1528 // compiling them into binaries, determining the attribute mappings, and collecting 1529 // a list of uniforms link()1530 void Program::link() 1531 { 1532 unlink(); 1533 1534 resetUniformBlockBindings(); 1535 1536 if(!fragmentShader || !fragmentShader->isCompiled()) 1537 { 1538 return; 1539 } 1540 1541 if(!vertexShader || !vertexShader->isCompiled()) 1542 { 1543 return; 1544 } 1545 1546 vertexBinary = new sw::VertexShader(vertexShader->getVertexShader()); 1547 pixelBinary = new sw::PixelShader(fragmentShader->getPixelShader()); 1548 1549 if(!linkVaryings()) 1550 { 1551 return; 1552 } 1553 1554 if(!linkAttributes()) 1555 { 1556 return; 1557 } 1558 1559 // Link uniform blocks before uniforms to make it easy to assign block indices to fields 1560 if(!linkUniformBlocks(vertexShader, fragmentShader)) 1561 { 1562 return; 1563 } 1564 1565 if(!linkUniforms(fragmentShader)) 1566 { 1567 return; 1568 } 1569 1570 if(!linkUniforms(vertexShader)) 1571 { 1572 return; 1573 } 1574 1575 if(!linkTransformFeedback()) 1576 { 1577 return; 1578 } 1579 1580 linked = true; // Success 1581 } 1582 1583 // Determines the mapping between GL attributes and vertex stream usage indices linkAttributes()1584 bool Program::linkAttributes() 1585 { 1586 static_assert(MAX_VERTEX_ATTRIBS <= 32, "attribute count exceeds bitfield count"); 1587 unsigned int usedLocations = 0; 1588 1589 // Link attributes that have a GLSL layout location qualifier 1590 for(auto const &attribute : vertexShader->activeAttributes) 1591 { 1592 if(attribute.layoutLocation != -1) 1593 { 1594 if(!linkAttribute(attribute, attribute.layoutLocation, usedLocations)) 1595 { 1596 return false; 1597 } 1598 } 1599 } 1600 1601 // Link attributes that have an API provided binding location but no GLSL layout location 1602 for(auto const &attribute : vertexShader->activeAttributes) 1603 { 1604 int bindingLocation = (attributeBinding.find(attribute.name) != attributeBinding.end()) ? attributeBinding[attribute.name] : -1; 1605 1606 if(attribute.layoutLocation == -1 && bindingLocation != -1) 1607 { 1608 if(!linkAttribute(attribute, bindingLocation, usedLocations)) 1609 { 1610 return false; 1611 } 1612 } 1613 } 1614 1615 // Link attributes that don't have a binding location nor a layout location 1616 for(auto const &attribute : vertexShader->activeAttributes) 1617 { 1618 if(attribute.layoutLocation == -1 && attributeBinding.find(attribute.name) == attributeBinding.end()) 1619 { 1620 if(!linkAttribute(attribute, -1, usedLocations)) 1621 { 1622 return false; 1623 } 1624 } 1625 } 1626 1627 ASSERT(linkedAttribute.size() == vertexShader->activeAttributes.size()); 1628 1629 for(auto const &attribute : linkedAttribute) 1630 { 1631 int location = getAttributeLocation(attribute.name); 1632 ASSERT(location >= 0); 1633 int index = vertexShader->getSemanticIndex(attribute.name); 1634 int rows = VariableRegisterCount(attribute.type); 1635 1636 for(int r = 0; r < rows; r++) 1637 { 1638 attributeStream[r + location] = index++; 1639 } 1640 } 1641 1642 return true; 1643 } 1644 linkAttribute(const glsl::Attribute & attribute,int location,unsigned int & usedLocations)1645 bool Program::linkAttribute(const glsl::Attribute &attribute, int location, unsigned int &usedLocations) 1646 { 1647 int rows = VariableRegisterCount(attribute.type); 1648 1649 if(location == -1) 1650 { 1651 location = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); 1652 1653 if(location == -1 || location + rows > MAX_VERTEX_ATTRIBS) 1654 { 1655 appendToInfoLog("Too many active attributes (%s)", attribute.name.c_str()); 1656 return false; // Fail to link 1657 } 1658 } 1659 else 1660 { 1661 if(rows + location > MAX_VERTEX_ATTRIBS) 1662 { 1663 appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location); 1664 return false; 1665 } 1666 1667 // In GLSL 3.00, attribute aliasing produces a link error 1668 // In GLSL 1.00, attribute aliasing is allowed 1669 if(vertexShader->getShaderVersion() >= 300) 1670 { 1671 for(auto const &previousAttrib : linkedAttribute) 1672 { 1673 int previousLocation = getAttributeLocation(previousAttrib.name); 1674 int previousRows = VariableRegisterCount(previousAttrib.type); 1675 1676 if(location >= previousLocation && location < previousLocation + previousRows) 1677 { 1678 appendToInfoLog("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), previousAttrib.name.c_str(), location); 1679 return false; 1680 } 1681 1682 if(location <= previousLocation && location + rows > previousLocation) 1683 { 1684 appendToInfoLog("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), previousAttrib.name.c_str(), previousLocation); 1685 return false; 1686 } 1687 } 1688 } 1689 1690 for(int i = 0; i < rows; i++) 1691 { 1692 usedLocations |= 1 << (location + i); 1693 } 1694 } 1695 1696 linkedAttributeLocation[attribute.name] = location; 1697 linkedAttribute.push_back(attribute); 1698 1699 return true; 1700 } 1701 getAttributeLocation(const std::string & name)1702 int Program::getAttributeLocation(const std::string &name) 1703 { 1704 std::map<std::string, GLuint>::const_iterator attribute = linkedAttributeLocation.find(name); 1705 if(attribute != linkedAttributeLocation.end()) 1706 { 1707 return attribute->second; 1708 } 1709 1710 return -1; 1711 } 1712 linkUniforms(const Shader * shader)1713 bool Program::linkUniforms(const Shader *shader) 1714 { 1715 for(const auto &uniform : shader->activeUniforms) 1716 { 1717 unsigned int blockIndex = GL_INVALID_INDEX; 1718 if(uniform.blockId >= 0) 1719 { 1720 const glsl::ActiveUniformBlocks &activeUniformBlocks = shader->activeUniformBlocks; 1721 ASSERT(static_cast<size_t>(uniform.blockId) < activeUniformBlocks.size()); 1722 const std::string &uniformBlockName = activeUniformBlocks[uniform.blockId].name; 1723 blockIndex = getUniformBlockIndex(uniformBlockName); 1724 ASSERT(blockIndex != GL_INVALID_INDEX); 1725 1726 if(activeUniformBlocks[uniform.blockId].dataSize > MAX_UNIFORM_BLOCK_SIZE) 1727 { 1728 if(shader->getType() == GL_VERTEX_SHADER) 1729 { 1730 appendToInfoLog("Vertex shader active uniform block (%s) exceeds GL_MAX_UNIFORM_BLOCK_SIZE (%d)", uniformBlockName.c_str(), MAX_UNIFORM_BLOCK_SIZE); 1731 return false; 1732 } 1733 else if(shader->getType() == GL_FRAGMENT_SHADER) 1734 { 1735 appendToInfoLog("Fragment shader active uniform block (%s) exceeds GL_MAX_UNIFORM_BLOCK_SIZE (%d)", uniformBlockName.c_str(), MAX_UNIFORM_BLOCK_SIZE); 1736 return false; 1737 } 1738 else UNREACHABLE(shader->getType()); 1739 } 1740 } 1741 1742 if(!defineUniform(shader->getType(), uniform, Uniform::BlockInfo(uniform, blockIndex))) 1743 { 1744 return false; 1745 } 1746 } 1747 1748 for(const auto &uniformStruct : shader->activeUniformStructs) 1749 { 1750 if(!validateUniformStruct(shader->getType(), uniformStruct)) 1751 { 1752 return false; 1753 } 1754 } 1755 1756 return true; 1757 } 1758 defineUniform(GLenum shader,const glsl::Uniform & glslUniform,const Uniform::BlockInfo & blockInfo)1759 bool Program::defineUniform(GLenum shader, const glsl::Uniform &glslUniform, const Uniform::BlockInfo& blockInfo) 1760 { 1761 if(IsSamplerUniform(glslUniform.type)) 1762 { 1763 int index = glslUniform.registerIndex; 1764 1765 do 1766 { 1767 if(shader == GL_VERTEX_SHADER) 1768 { 1769 if(index < MAX_VERTEX_TEXTURE_IMAGE_UNITS) 1770 { 1771 samplersVS[index].active = true; 1772 1773 switch(glslUniform.type) 1774 { 1775 default: UNREACHABLE(glslUniform.type); 1776 case GL_INT_SAMPLER_2D: 1777 case GL_UNSIGNED_INT_SAMPLER_2D: 1778 case GL_SAMPLER_2D_SHADOW: 1779 case GL_SAMPLER_2D: samplersVS[index].textureType = TEXTURE_2D; break; 1780 case GL_INT_SAMPLER_CUBE: 1781 case GL_UNSIGNED_INT_SAMPLER_CUBE: 1782 case GL_SAMPLER_CUBE_SHADOW: 1783 case GL_SAMPLER_CUBE: samplersVS[index].textureType = TEXTURE_CUBE; break; 1784 case GL_INT_SAMPLER_3D: 1785 case GL_UNSIGNED_INT_SAMPLER_3D: 1786 case GL_SAMPLER_3D_OES: samplersVS[index].textureType = TEXTURE_3D; break; 1787 case GL_SAMPLER_2D_RECT_ARB: samplersVS[index].textureType = TEXTURE_2D_RECT; break; 1788 case GL_SAMPLER_EXTERNAL_OES: samplersVS[index].textureType = TEXTURE_EXTERNAL; break; 1789 case GL_INT_SAMPLER_2D_ARRAY: 1790 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: 1791 case GL_SAMPLER_2D_ARRAY_SHADOW: 1792 case GL_SAMPLER_2D_ARRAY: samplersVS[index].textureType = TEXTURE_2D_ARRAY; break; 1793 } 1794 1795 samplersVS[index].logicalTextureUnit = 0; 1796 } 1797 else 1798 { 1799 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", MAX_VERTEX_TEXTURE_IMAGE_UNITS); 1800 return false; 1801 } 1802 } 1803 else if(shader == GL_FRAGMENT_SHADER) 1804 { 1805 if(index < MAX_TEXTURE_IMAGE_UNITS) 1806 { 1807 samplersPS[index].active = true; 1808 1809 switch(glslUniform.type) 1810 { 1811 default: UNREACHABLE(glslUniform.type); 1812 case GL_INT_SAMPLER_2D: 1813 case GL_UNSIGNED_INT_SAMPLER_2D: 1814 case GL_SAMPLER_2D_SHADOW: 1815 case GL_SAMPLER_2D: samplersPS[index].textureType = TEXTURE_2D; break; 1816 case GL_INT_SAMPLER_CUBE: 1817 case GL_UNSIGNED_INT_SAMPLER_CUBE: 1818 case GL_SAMPLER_CUBE_SHADOW: 1819 case GL_SAMPLER_CUBE: samplersPS[index].textureType = TEXTURE_CUBE; break; 1820 case GL_INT_SAMPLER_3D: 1821 case GL_UNSIGNED_INT_SAMPLER_3D: 1822 case GL_SAMPLER_3D_OES: samplersPS[index].textureType = TEXTURE_3D; break; 1823 case GL_SAMPLER_2D_RECT_ARB: samplersPS[index].textureType = TEXTURE_2D_RECT; break; 1824 case GL_SAMPLER_EXTERNAL_OES: samplersPS[index].textureType = TEXTURE_EXTERNAL; break; 1825 case GL_INT_SAMPLER_2D_ARRAY: 1826 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: 1827 case GL_SAMPLER_2D_ARRAY_SHADOW: 1828 case GL_SAMPLER_2D_ARRAY: samplersPS[index].textureType = TEXTURE_2D_ARRAY; break; 1829 } 1830 1831 samplersPS[index].logicalTextureUnit = 0; 1832 } 1833 else 1834 { 1835 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); 1836 return false; 1837 } 1838 } 1839 else UNREACHABLE(shader); 1840 1841 index++; 1842 } 1843 while(index < glslUniform.registerIndex + static_cast<int>(glslUniform.arraySize)); 1844 } 1845 1846 Uniform *uniform = getUniform(glslUniform.name); 1847 1848 if(!uniform) 1849 { 1850 uniform = new Uniform(glslUniform, blockInfo); 1851 uniforms.push_back(uniform); 1852 1853 unsigned int index = (blockInfo.index == -1) ? static_cast<unsigned int>(uniforms.size() - 1) : GL_INVALID_INDEX; 1854 1855 for(int i = 0; i < uniform->size(); i++) 1856 { 1857 uniformIndex.push_back(UniformLocation(glslUniform.name, i, index)); 1858 } 1859 } 1860 else // Previously defined, types must match 1861 { 1862 if(uniform->type != glslUniform.type) 1863 { 1864 appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); 1865 return false; 1866 } 1867 1868 if(uniform->precision != glslUniform.precision) 1869 { 1870 appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); 1871 return false; 1872 } 1873 1874 if(!areMatchingFields(uniform->fields, glslUniform.fields, uniform->name)) 1875 { 1876 return false; 1877 } 1878 } 1879 1880 if(shader == GL_VERTEX_SHADER) 1881 { 1882 uniform->vsRegisterIndex = glslUniform.registerIndex; 1883 } 1884 else if(shader == GL_FRAGMENT_SHADER) 1885 { 1886 uniform->psRegisterIndex = glslUniform.registerIndex; 1887 } 1888 else UNREACHABLE(shader); 1889 1890 if(uniform->blockInfo.index < 0) 1891 { 1892 if(shader == GL_VERTEX_SHADER) 1893 { 1894 if(glslUniform.registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS) 1895 { 1896 appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS); 1897 return false; 1898 } 1899 } 1900 else if(shader == GL_FRAGMENT_SHADER) 1901 { 1902 if(glslUniform.registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS) 1903 { 1904 appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS); 1905 return false; 1906 } 1907 } 1908 else UNREACHABLE(shader); 1909 } 1910 1911 return true; 1912 } 1913 validateUniformStruct(GLenum shader,const glsl::Uniform & newUniformStruct)1914 bool Program::validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct) 1915 { 1916 for(const auto &uniformStruct : uniformStructs) 1917 { 1918 if(uniformStruct.name == newUniformStruct.name) 1919 { 1920 return areMatchingFields(uniformStruct.fields, newUniformStruct.fields, newUniformStruct.name); 1921 } 1922 } 1923 1924 uniformStructs.push_back(Uniform(newUniformStruct, Uniform::BlockInfo(newUniformStruct, -1))); 1925 1926 return true; 1927 } 1928 areMatchingUniformBlocks(const glsl::UniformBlock & block1,const glsl::UniformBlock & block2,const Shader * shader1,const Shader * shader2)1929 bool Program::areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2) 1930 { 1931 // validate blocks for the same member types 1932 if(block1.fields.size() != block2.fields.size()) 1933 { 1934 appendToInfoLog("Types for interface block '%s' differ between vertex and fragment shaders", block1.name.c_str()); 1935 return false; 1936 } 1937 if(block1.arraySize != block2.arraySize) 1938 { 1939 appendToInfoLog("Array sizes differ for interface block '%s' between vertex and fragment shaders", block1.name.c_str()); 1940 return false; 1941 } 1942 if(block1.layout != block2.layout || block1.isRowMajorLayout != block2.isRowMajorLayout) 1943 { 1944 appendToInfoLog("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", block1.name.c_str()); 1945 return false; 1946 } 1947 const size_t numBlockMembers = block1.fields.size(); 1948 for(size_t blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) 1949 { 1950 const glsl::Uniform& member1 = shader1->activeUniforms[block1.fields[blockMemberIndex]]; 1951 const glsl::Uniform& member2 = shader2->activeUniforms[block2.fields[blockMemberIndex]]; 1952 if(member1.name != member2.name) 1953 { 1954 appendToInfoLog("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", 1955 blockMemberIndex, block1.name.c_str(), member1.name.c_str(), member2.name.c_str()); 1956 return false; 1957 } 1958 if(member1.arraySize != member2.arraySize) 1959 { 1960 appendToInfoLog("Array sizes for %s differ between vertex and fragment shaders", member1.name.c_str()); 1961 return false; 1962 } 1963 if(member1.precision != member2.precision) 1964 { 1965 appendToInfoLog("Precisions for %s differ between vertex and fragment shaders", member1.name.c_str()); 1966 return false; 1967 } 1968 if(member1.type != member2.type) 1969 { 1970 appendToInfoLog("Types for %s differ between vertex and fragment shaders", member1.name.c_str()); 1971 return false; 1972 } 1973 if(member1.blockInfo.isRowMajorMatrix != member2.blockInfo.isRowMajorMatrix) 1974 { 1975 appendToInfoLog("Matrix packings for %s differ between vertex and fragment shaders", member1.name.c_str()); 1976 return false; 1977 } 1978 } 1979 return true; 1980 } 1981 areMatchingFields(const std::vector<glsl::ShaderVariable> & fields1,const std::vector<glsl::ShaderVariable> & fields2,const std::string & name)1982 bool Program::areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name) 1983 { 1984 if(fields1.size() != fields2.size()) 1985 { 1986 appendToInfoLog("Structure lengths for %s differ between vertex and fragment shaders", name.c_str()); 1987 return false; 1988 } 1989 1990 for(size_t i = 0; i < fields1.size(); ++i) 1991 { 1992 if(fields1[i].name != fields2[i].name) 1993 { 1994 appendToInfoLog("Name mismatch for field '%d' of %s: ('%s', '%s')", 1995 i, name.c_str(), fields1[i].name.c_str(), fields2[i].name.c_str()); 1996 return false; 1997 } 1998 if(fields1[i].type != fields2[i].type) 1999 { 2000 appendToInfoLog("Type for %s.%s differ between vertex and fragment shaders", name.c_str(), fields1[i].name.c_str()); 2001 return false; 2002 } 2003 if(fields1[i].arraySize != fields2[i].arraySize) 2004 { 2005 appendToInfoLog("Array size for %s.%s differ between vertex and fragment shaders", name.c_str(), fields1[i].name.c_str()); 2006 return false; 2007 } 2008 if(!areMatchingFields(fields1[i].fields, fields2[i].fields, fields1[i].name)) 2009 { 2010 return false; 2011 } 2012 } 2013 2014 return true; 2015 } 2016 linkUniformBlocks(const Shader * vertexShader,const Shader * fragmentShader)2017 bool Program::linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader) 2018 { 2019 const glsl::ActiveUniformBlocks &vertexUniformBlocks = vertexShader->activeUniformBlocks; 2020 const glsl::ActiveUniformBlocks &fragmentUniformBlocks = fragmentShader->activeUniformBlocks; 2021 // Check that interface blocks defined in the vertex and fragment shaders are identical 2022 typedef std::map<std::string, const glsl::UniformBlock*> UniformBlockMap; 2023 UniformBlockMap linkedUniformBlocks; 2024 for(unsigned int blockIndex = 0; blockIndex < vertexUniformBlocks.size(); blockIndex++) 2025 { 2026 const glsl::UniformBlock &vertexUniformBlock = vertexUniformBlocks[blockIndex]; 2027 linkedUniformBlocks[vertexUniformBlock.name] = &vertexUniformBlock; 2028 } 2029 for(unsigned int blockIndex = 0; blockIndex < fragmentUniformBlocks.size(); blockIndex++) 2030 { 2031 const glsl::UniformBlock &fragmentUniformBlock = fragmentUniformBlocks[blockIndex]; 2032 UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentUniformBlock.name); 2033 if(entry != linkedUniformBlocks.end()) 2034 { 2035 const glsl::UniformBlock &vertexUniformBlock = *entry->second; 2036 if(!areMatchingUniformBlocks(vertexUniformBlock, fragmentUniformBlock, vertexShader, fragmentShader)) 2037 { 2038 return false; 2039 } 2040 } 2041 } 2042 for(unsigned int blockIndex = 0; blockIndex < vertexUniformBlocks.size(); blockIndex++) 2043 { 2044 const glsl::UniformBlock &uniformBlock = vertexUniformBlocks[blockIndex]; 2045 if(!defineUniformBlock(vertexShader, uniformBlock)) 2046 { 2047 return false; 2048 } 2049 } 2050 for(unsigned int blockIndex = 0; blockIndex < fragmentUniformBlocks.size(); blockIndex++) 2051 { 2052 const glsl::UniformBlock &uniformBlock = fragmentUniformBlocks[blockIndex]; 2053 if(!defineUniformBlock(fragmentShader, uniformBlock)) 2054 { 2055 return false; 2056 } 2057 } 2058 return true; 2059 } 2060 defineUniformBlock(const Shader * shader,const glsl::UniformBlock & block)2061 bool Program::defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block) 2062 { 2063 GLuint blockIndex = getUniformBlockIndex(block.name); 2064 2065 if(blockIndex == GL_INVALID_INDEX) 2066 { 2067 const std::vector<int>& fields = block.fields; 2068 std::vector<unsigned int> memberUniformIndexes; 2069 for(size_t i = 0; i < fields.size(); ++i) 2070 { 2071 memberUniformIndexes.push_back(fields[i]); 2072 } 2073 2074 if(block.arraySize > 0) 2075 { 2076 int regIndex = block.registerIndex; 2077 int regInc = block.dataSize / (glsl::BlockLayoutEncoder::BytesPerComponent * glsl::BlockLayoutEncoder::ComponentsPerRegister); 2078 for(unsigned int i = 0; i < block.arraySize; ++i, regIndex += regInc) 2079 { 2080 uniformBlocks.push_back(new UniformBlock(block.name, i, block.dataSize, memberUniformIndexes)); 2081 uniformBlocks[uniformBlocks.size() - 1]->setRegisterIndex(shader->getType(), regIndex); 2082 } 2083 } 2084 else 2085 { 2086 uniformBlocks.push_back(new UniformBlock(block.name, GL_INVALID_INDEX, block.dataSize, memberUniformIndexes)); 2087 uniformBlocks[uniformBlocks.size() - 1]->setRegisterIndex(shader->getType(), block.registerIndex); 2088 } 2089 } 2090 else 2091 { 2092 int regIndex = block.registerIndex; 2093 int regInc = block.dataSize / (glsl::BlockLayoutEncoder::BytesPerComponent * glsl::BlockLayoutEncoder::ComponentsPerRegister); 2094 int nbBlocks = (block.arraySize > 0) ? block.arraySize : 1; 2095 for(int i = 0; i < nbBlocks; ++i, regIndex += regInc) 2096 { 2097 uniformBlocks[blockIndex + i]->setRegisterIndex(shader->getType(), regIndex); 2098 } 2099 } 2100 2101 return true; 2102 } 2103 applyUniform(Device * device,GLint location,float * data)2104 bool Program::applyUniform(Device *device, GLint location, float* data) 2105 { 2106 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 2107 2108 if(targetUniform->psRegisterIndex != -1) 2109 { 2110 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, data, targetUniform->registerCount()); 2111 } 2112 2113 if(targetUniform->vsRegisterIndex != -1) 2114 { 2115 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, data, targetUniform->registerCount()); 2116 } 2117 2118 return true; 2119 } 2120 applyUniform1bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2121 bool Program::applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v) 2122 { 2123 int vector[MAX_UNIFORM_VECTORS][4]; 2124 2125 for(int i = 0; i < count; i++) 2126 { 2127 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2128 vector[i][1] = 0; 2129 vector[i][2] = 0; 2130 vector[i][3] = 0; 2131 2132 v += 1; 2133 } 2134 2135 return applyUniform(device, location, (float*)vector); 2136 } 2137 applyUniform2bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2138 bool Program::applyUniform2bv(Device *device, GLint location, GLsizei count, const GLboolean *v) 2139 { 2140 int vector[MAX_UNIFORM_VECTORS][4]; 2141 2142 for(int i = 0; i < count; i++) 2143 { 2144 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2145 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2146 vector[i][2] = 0; 2147 vector[i][3] = 0; 2148 2149 v += 2; 2150 } 2151 2152 return applyUniform(device, location, (float*)vector); 2153 } 2154 applyUniform3bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2155 bool Program::applyUniform3bv(Device *device, GLint location, GLsizei count, const GLboolean *v) 2156 { 2157 int vector[MAX_UNIFORM_VECTORS][4]; 2158 2159 for(int i = 0; i < count; i++) 2160 { 2161 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2162 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2163 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2164 vector[i][3] = 0; 2165 2166 v += 3; 2167 } 2168 2169 return applyUniform(device, location, (float*)vector); 2170 } 2171 applyUniform4bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2172 bool Program::applyUniform4bv(Device *device, GLint location, GLsizei count, const GLboolean *v) 2173 { 2174 int vector[MAX_UNIFORM_VECTORS][4]; 2175 2176 for(int i = 0; i < count; i++) 2177 { 2178 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2179 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2180 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2181 vector[i][3] = (v[3] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 2182 2183 v += 4; 2184 } 2185 2186 return applyUniform(device, location, (float*)vector); 2187 } 2188 applyUniform1fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2189 bool Program::applyUniform1fv(Device *device, GLint location, GLsizei count, const GLfloat *v) 2190 { 2191 float vector[MAX_UNIFORM_VECTORS][4]; 2192 2193 for(int i = 0; i < count; i++) 2194 { 2195 vector[i][0] = v[0]; 2196 vector[i][1] = 0; 2197 vector[i][2] = 0; 2198 vector[i][3] = 0; 2199 2200 v += 1; 2201 } 2202 2203 return applyUniform(device, location, (float*)vector); 2204 } 2205 applyUniform2fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2206 bool Program::applyUniform2fv(Device *device, GLint location, GLsizei count, const GLfloat *v) 2207 { 2208 float vector[MAX_UNIFORM_VECTORS][4]; 2209 2210 for(int i = 0; i < count; i++) 2211 { 2212 vector[i][0] = v[0]; 2213 vector[i][1] = v[1]; 2214 vector[i][2] = 0; 2215 vector[i][3] = 0; 2216 2217 v += 2; 2218 } 2219 2220 return applyUniform(device, location, (float*)vector); 2221 } 2222 applyUniform3fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2223 bool Program::applyUniform3fv(Device *device, GLint location, GLsizei count, const GLfloat *v) 2224 { 2225 float vector[MAX_UNIFORM_VECTORS][4]; 2226 2227 for(int i = 0; i < count; i++) 2228 { 2229 vector[i][0] = v[0]; 2230 vector[i][1] = v[1]; 2231 vector[i][2] = v[2]; 2232 vector[i][3] = 0; 2233 2234 v += 3; 2235 } 2236 2237 return applyUniform(device, location, (float*)vector); 2238 } 2239 applyUniform4fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2240 bool Program::applyUniform4fv(Device *device, GLint location, GLsizei count, const GLfloat *v) 2241 { 2242 return applyUniform(device, location, (float*)v); 2243 } 2244 applyUniformMatrix2fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2245 bool Program::applyUniformMatrix2fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2246 { 2247 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4]; 2248 2249 for(int i = 0; i < count; i++) 2250 { 2251 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0; 2252 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0; 2253 2254 value += 4; 2255 } 2256 2257 return applyUniform(device, location, (float*)matrix); 2258 } 2259 applyUniformMatrix2x3fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2260 bool Program::applyUniformMatrix2x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2261 { 2262 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4]; 2263 2264 for(int i = 0; i < count; i++) 2265 { 2266 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0; 2267 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0; 2268 2269 value += 6; 2270 } 2271 2272 return applyUniform(device, location, (float*)matrix); 2273 } 2274 applyUniformMatrix2x4fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2275 bool Program::applyUniformMatrix2x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2276 { 2277 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4]; 2278 2279 for(int i = 0; i < count; i++) 2280 { 2281 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = value[3]; 2282 matrix[i][1][0] = value[4]; matrix[i][1][1] = value[5]; matrix[i][1][2] = value[6]; matrix[i][1][3] = value[7]; 2283 2284 value += 8; 2285 } 2286 2287 return applyUniform(device, location, (float*)matrix); 2288 } 2289 applyUniformMatrix3fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2290 bool Program::applyUniformMatrix3fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2291 { 2292 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4]; 2293 2294 for(int i = 0; i < count; i++) 2295 { 2296 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0; 2297 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0; 2298 matrix[i][2][0] = value[6]; matrix[i][2][1] = value[7]; matrix[i][2][2] = value[8]; matrix[i][2][3] = 0; 2299 2300 value += 9; 2301 } 2302 2303 return applyUniform(device, location, (float*)matrix); 2304 } 2305 applyUniformMatrix3x2fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2306 bool Program::applyUniformMatrix3x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2307 { 2308 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4]; 2309 2310 for(int i = 0; i < count; i++) 2311 { 2312 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0; 2313 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0; 2314 matrix[i][2][0] = value[4]; matrix[i][2][1] = value[5]; matrix[i][2][2] = 0; matrix[i][2][3] = 0; 2315 2316 value += 6; 2317 } 2318 2319 return applyUniform(device, location, (float*)matrix); 2320 } 2321 applyUniformMatrix3x4fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2322 bool Program::applyUniformMatrix3x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2323 { 2324 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4]; 2325 2326 for(int i = 0; i < count; i++) 2327 { 2328 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = value[3]; 2329 matrix[i][1][0] = value[4]; matrix[i][1][1] = value[5]; matrix[i][1][2] = value[6]; matrix[i][1][3] = value[7]; 2330 matrix[i][2][0] = value[8]; matrix[i][2][1] = value[9]; matrix[i][2][2] = value[10]; matrix[i][2][3] = value[11]; 2331 2332 value += 12; 2333 } 2334 2335 return applyUniform(device, location, (float*)matrix); 2336 } 2337 applyUniformMatrix4fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2338 bool Program::applyUniformMatrix4fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2339 { 2340 return applyUniform(device, location, (float*)value); 2341 } 2342 applyUniformMatrix4x2fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2343 bool Program::applyUniformMatrix4x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2344 { 2345 float matrix[(MAX_UNIFORM_VECTORS + 3) / 4][4][4]; 2346 2347 for(int i = 0; i < count; i++) 2348 { 2349 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0; 2350 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0; 2351 matrix[i][2][0] = value[4]; matrix[i][2][1] = value[5]; matrix[i][2][2] = 0; matrix[i][2][3] = 0; 2352 matrix[i][3][0] = value[6]; matrix[i][3][1] = value[7]; matrix[i][3][2] = 0; matrix[i][3][3] = 0; 2353 2354 value += 8; 2355 } 2356 2357 return applyUniform(device, location, (float*)matrix); 2358 } 2359 applyUniformMatrix4x3fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2360 bool Program::applyUniformMatrix4x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value) 2361 { 2362 float matrix[(MAX_UNIFORM_VECTORS + 3) / 4][4][4]; 2363 2364 for(int i = 0; i < count; i++) 2365 { 2366 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0; 2367 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0; 2368 matrix[i][2][0] = value[6]; matrix[i][2][1] = value[7]; matrix[i][2][2] = value[8]; matrix[i][2][3] = 0; 2369 matrix[i][3][0] = value[9]; matrix[i][3][1] = value[10]; matrix[i][3][2] = value[11]; matrix[i][3][3] = 0; 2370 2371 value += 12; 2372 } 2373 2374 return applyUniform(device, location, (float*)matrix); 2375 } 2376 applyUniform1iv(Device * device,GLint location,GLsizei count,const GLint * v)2377 bool Program::applyUniform1iv(Device *device, GLint location, GLsizei count, const GLint *v) 2378 { 2379 GLint vector[MAX_UNIFORM_VECTORS][4]; 2380 2381 for(int i = 0; i < count; i++) 2382 { 2383 vector[i][0] = v[i]; 2384 vector[i][1] = 0; 2385 vector[i][2] = 0; 2386 vector[i][3] = 0; 2387 } 2388 2389 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 2390 if(IsSamplerUniform(targetUniform->type)) 2391 { 2392 if(targetUniform->psRegisterIndex != -1) 2393 { 2394 for(int i = 0; i < count; i++) 2395 { 2396 unsigned int samplerIndex = targetUniform->psRegisterIndex + i; 2397 2398 if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS) 2399 { 2400 ASSERT(samplersPS[samplerIndex].active); 2401 samplersPS[samplerIndex].logicalTextureUnit = v[i]; 2402 } 2403 } 2404 } 2405 2406 if(targetUniform->vsRegisterIndex != -1) 2407 { 2408 for(int i = 0; i < count; i++) 2409 { 2410 unsigned int samplerIndex = targetUniform->vsRegisterIndex + i; 2411 2412 if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS) 2413 { 2414 ASSERT(samplersVS[samplerIndex].active); 2415 samplersVS[samplerIndex].logicalTextureUnit = v[i]; 2416 } 2417 } 2418 } 2419 } 2420 else 2421 { 2422 return applyUniform(device, location, (float*)vector); 2423 } 2424 2425 return true; 2426 } 2427 applyUniform2iv(Device * device,GLint location,GLsizei count,const GLint * v)2428 bool Program::applyUniform2iv(Device *device, GLint location, GLsizei count, const GLint *v) 2429 { 2430 GLint vector[MAX_UNIFORM_VECTORS][4]; 2431 2432 for(int i = 0; i < count; i++) 2433 { 2434 vector[i][0] = v[0]; 2435 vector[i][1] = v[1]; 2436 vector[i][2] = 0; 2437 vector[i][3] = 0; 2438 2439 v += 2; 2440 } 2441 2442 return applyUniform(device, location, (float*)vector); 2443 } 2444 applyUniform3iv(Device * device,GLint location,GLsizei count,const GLint * v)2445 bool Program::applyUniform3iv(Device *device, GLint location, GLsizei count, const GLint *v) 2446 { 2447 GLint vector[MAX_UNIFORM_VECTORS][4]; 2448 2449 for(int i = 0; i < count; i++) 2450 { 2451 vector[i][0] = v[0]; 2452 vector[i][1] = v[1]; 2453 vector[i][2] = v[2]; 2454 vector[i][3] = 0; 2455 2456 v += 3; 2457 } 2458 2459 return applyUniform(device, location, (float*)vector); 2460 } 2461 applyUniform4iv(Device * device,GLint location,GLsizei count,const GLint * v)2462 bool Program::applyUniform4iv(Device *device, GLint location, GLsizei count, const GLint *v) 2463 { 2464 GLint vector[MAX_UNIFORM_VECTORS][4]; 2465 2466 for(int i = 0; i < count; i++) 2467 { 2468 vector[i][0] = v[0]; 2469 vector[i][1] = v[1]; 2470 vector[i][2] = v[2]; 2471 vector[i][3] = v[3]; 2472 2473 v += 4; 2474 } 2475 2476 return applyUniform(device, location, (float*)vector); 2477 } 2478 applyUniform1uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2479 bool Program::applyUniform1uiv(Device *device, GLint location, GLsizei count, const GLuint *v) 2480 { 2481 GLuint vector[MAX_UNIFORM_VECTORS][4]; 2482 2483 for(int i = 0; i < count; i++) 2484 { 2485 vector[i][0] = v[i]; 2486 vector[i][1] = 0; 2487 vector[i][2] = 0; 2488 vector[i][3] = 0; 2489 } 2490 2491 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 2492 if(IsSamplerUniform(targetUniform->type)) 2493 { 2494 if(targetUniform->psRegisterIndex != -1) 2495 { 2496 for(int i = 0; i < count; i++) 2497 { 2498 unsigned int samplerIndex = targetUniform->psRegisterIndex + i; 2499 2500 if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS) 2501 { 2502 ASSERT(samplersPS[samplerIndex].active); 2503 samplersPS[samplerIndex].logicalTextureUnit = v[i]; 2504 } 2505 } 2506 } 2507 2508 if(targetUniform->vsRegisterIndex != -1) 2509 { 2510 for(int i = 0; i < count; i++) 2511 { 2512 unsigned int samplerIndex = targetUniform->vsRegisterIndex + i; 2513 2514 if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS) 2515 { 2516 ASSERT(samplersVS[samplerIndex].active); 2517 samplersVS[samplerIndex].logicalTextureUnit = v[i]; 2518 } 2519 } 2520 } 2521 } 2522 else 2523 { 2524 return applyUniform(device, location, (float*)vector); 2525 } 2526 2527 return true; 2528 } 2529 applyUniform2uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2530 bool Program::applyUniform2uiv(Device *device, GLint location, GLsizei count, const GLuint *v) 2531 { 2532 GLuint vector[MAX_UNIFORM_VECTORS][4]; 2533 2534 for(int i = 0; i < count; i++) 2535 { 2536 vector[i][0] = v[0]; 2537 vector[i][1] = v[1]; 2538 vector[i][2] = 0; 2539 vector[i][3] = 0; 2540 2541 v += 2; 2542 } 2543 2544 return applyUniform(device, location, (float*)vector); 2545 } 2546 applyUniform3uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2547 bool Program::applyUniform3uiv(Device *device, GLint location, GLsizei count, const GLuint *v) 2548 { 2549 GLuint vector[MAX_UNIFORM_VECTORS][4]; 2550 2551 for(int i = 0; i < count; i++) 2552 { 2553 vector[i][0] = v[0]; 2554 vector[i][1] = v[1]; 2555 vector[i][2] = v[2]; 2556 vector[i][3] = 0; 2557 2558 v += 3; 2559 } 2560 2561 return applyUniform(device, location, (float*)vector); 2562 } 2563 applyUniform4uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2564 bool Program::applyUniform4uiv(Device *device, GLint location, GLsizei count, const GLuint *v) 2565 { 2566 GLuint vector[MAX_UNIFORM_VECTORS][4]; 2567 2568 for(int i = 0; i < count; i++) 2569 { 2570 vector[i][0] = v[0]; 2571 vector[i][1] = v[1]; 2572 vector[i][2] = v[2]; 2573 vector[i][3] = v[3]; 2574 2575 v += 4; 2576 } 2577 2578 return applyUniform(device, location, (float*)vector); 2579 } 2580 appendToInfoLog(const char * format,...)2581 void Program::appendToInfoLog(const char *format, ...) 2582 { 2583 if(!format) 2584 { 2585 return; 2586 } 2587 2588 char info[1024]; 2589 2590 va_list vararg; 2591 va_start(vararg, format); 2592 vsnprintf(info, sizeof(info), format, vararg); 2593 va_end(vararg); 2594 2595 size_t infoLength = strlen(info); 2596 2597 if(!infoLog) 2598 { 2599 infoLog = new char[infoLength + 2]; 2600 strcpy(infoLog, info); 2601 strcpy(infoLog + infoLength, "\n"); 2602 } 2603 else 2604 { 2605 size_t logLength = strlen(infoLog); 2606 char *newLog = new char[logLength + infoLength + 2]; 2607 strcpy(newLog, infoLog); 2608 strcpy(newLog + logLength, info); 2609 strcpy(newLog + logLength + infoLength, "\n"); 2610 2611 delete[] infoLog; 2612 infoLog = newLog; 2613 } 2614 } 2615 resetInfoLog()2616 void Program::resetInfoLog() 2617 { 2618 if(infoLog) 2619 { 2620 delete[] infoLog; 2621 infoLog = 0; 2622 } 2623 } 2624 2625 // Returns the program object to an unlinked state, before re-linking, or at destruction unlink()2626 void Program::unlink() 2627 { 2628 delete vertexBinary; 2629 vertexBinary = 0; 2630 delete pixelBinary; 2631 pixelBinary = 0; 2632 2633 linkedAttribute.clear(); 2634 linkedAttributeLocation.clear(); 2635 2636 for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++) 2637 { 2638 attributeStream[index] = -1; 2639 } 2640 2641 for(int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++) 2642 { 2643 samplersPS[index].active = false; 2644 } 2645 2646 for(int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) 2647 { 2648 samplersVS[index].active = false; 2649 } 2650 2651 while(!uniforms.empty()) 2652 { 2653 delete uniforms.back(); 2654 uniforms.pop_back(); 2655 } 2656 2657 while(!uniformBlocks.empty()) 2658 { 2659 delete uniformBlocks.back(); 2660 uniformBlocks.pop_back(); 2661 } 2662 2663 uniformIndex.clear(); 2664 transformFeedbackLinkedVaryings.clear(); 2665 2666 delete[] infoLog; 2667 infoLog = 0; 2668 2669 linked = false; 2670 } 2671 isLinked() const2672 bool Program::isLinked() const 2673 { 2674 return linked; 2675 } 2676 isValidated() const2677 bool Program::isValidated() const 2678 { 2679 return validated; 2680 } 2681 getBinaryLength() const2682 GLint Program::getBinaryLength() const 2683 { 2684 UNIMPLEMENTED(); 2685 return 0; 2686 } 2687 release()2688 void Program::release() 2689 { 2690 referenceCount--; 2691 2692 if(referenceCount == 0 && orphaned) 2693 { 2694 resourceManager->deleteProgram(handle); 2695 } 2696 } 2697 addRef()2698 void Program::addRef() 2699 { 2700 referenceCount++; 2701 } 2702 getRefCount() const2703 unsigned int Program::getRefCount() const 2704 { 2705 return referenceCount; 2706 } 2707 getSerial() const2708 unsigned int Program::getSerial() const 2709 { 2710 return serial; 2711 } 2712 issueSerial()2713 unsigned int Program::issueSerial() 2714 { 2715 return currentSerial++; 2716 } 2717 getInfoLogLength() const2718 size_t Program::getInfoLogLength() const 2719 { 2720 if(!infoLog) 2721 { 2722 return 0; 2723 } 2724 else 2725 { 2726 return strlen(infoLog) + 1; 2727 } 2728 } 2729 getInfoLog(GLsizei bufSize,GLsizei * length,char * buffer)2730 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *buffer) 2731 { 2732 int index = 0; 2733 2734 if(bufSize > 0) 2735 { 2736 if(infoLog) 2737 { 2738 index = std::min(bufSize - 1, (int)strlen(infoLog)); 2739 memcpy(buffer, infoLog, index); 2740 } 2741 2742 buffer[index] = '\0'; 2743 } 2744 2745 if(length) 2746 { 2747 *length = index; 2748 } 2749 } 2750 getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders)2751 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) 2752 { 2753 int total = 0; 2754 2755 if(vertexShader && (total < maxCount)) 2756 { 2757 shaders[total++] = vertexShader->getName(); 2758 } 2759 2760 if(fragmentShader && (total < maxCount)) 2761 { 2762 shaders[total++] = fragmentShader->getName(); 2763 } 2764 2765 if(count) 2766 { 2767 *count = total; 2768 } 2769 } 2770 getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2771 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const 2772 { 2773 ASSERT(index < linkedAttribute.size()); 2774 2775 std::vector<glsl::Attribute>::const_iterator it = linkedAttribute.begin() + index; 2776 2777 if(bufsize > 0) 2778 { 2779 const char *string = it->name.c_str(); 2780 2781 strncpy(name, string, bufsize); 2782 name[bufsize - 1] = '\0'; 2783 2784 if(length) 2785 { 2786 *length = static_cast<GLsizei>(strlen(name)); 2787 } 2788 } 2789 2790 *size = 1; // Always a single 'type' instance 2791 2792 *type = it->type; 2793 } 2794 getActiveAttributeCount() const2795 size_t Program::getActiveAttributeCount() const 2796 { 2797 return linkedAttribute.size(); 2798 } 2799 getActiveAttributeMaxLength() const2800 GLint Program::getActiveAttributeMaxLength() const 2801 { 2802 int maxLength = 0; 2803 2804 std::vector<glsl::Attribute>::const_iterator it = linkedAttribute.begin(); 2805 std::vector<glsl::Attribute>::const_iterator itEnd = linkedAttribute.end(); 2806 for(; it != itEnd; ++it) 2807 { 2808 maxLength = std::max((int)(it->name.length() + 1), maxLength); 2809 } 2810 2811 return maxLength; 2812 } 2813 getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2814 void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const 2815 { 2816 if(bufsize > 0) 2817 { 2818 std::string string = uniforms[index]->name; 2819 2820 if(uniforms[index]->isArray()) 2821 { 2822 string += "[0]"; 2823 } 2824 2825 strncpy(name, string.c_str(), bufsize); 2826 name[bufsize - 1] = '\0'; 2827 2828 if(length) 2829 { 2830 *length = static_cast<GLsizei>(strlen(name)); 2831 } 2832 } 2833 2834 *size = uniforms[index]->size(); 2835 2836 *type = uniforms[index]->type; 2837 } 2838 getActiveUniformCount() const2839 size_t Program::getActiveUniformCount() const 2840 { 2841 return uniforms.size(); 2842 } 2843 getActiveUniformMaxLength() const2844 GLint Program::getActiveUniformMaxLength() const 2845 { 2846 int maxLength = 0; 2847 2848 size_t numUniforms = uniforms.size(); 2849 for(size_t uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) 2850 { 2851 if(!uniforms[uniformIndex]->name.empty()) 2852 { 2853 int length = (int)(uniforms[uniformIndex]->name.length() + 1); 2854 if(uniforms[uniformIndex]->isArray()) 2855 { 2856 length += 3; // Counting in "[0]". 2857 } 2858 maxLength = std::max(length, maxLength); 2859 } 2860 } 2861 2862 return maxLength; 2863 } 2864 getActiveUniformi(GLuint index,GLenum pname) const2865 GLint Program::getActiveUniformi(GLuint index, GLenum pname) const 2866 { 2867 const Uniform& uniform = *uniforms[index]; 2868 switch(pname) 2869 { 2870 case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type); 2871 case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.size()); 2872 case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0)); 2873 case GL_UNIFORM_BLOCK_INDEX: return uniform.blockInfo.index; 2874 case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset; 2875 case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride; 2876 case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride; 2877 case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix); 2878 default: 2879 UNREACHABLE(pname); 2880 break; 2881 } 2882 return 0; 2883 } 2884 getActiveUniformBlockName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2885 void Program::getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const 2886 { 2887 ASSERT(index < getActiveUniformBlockCount()); 2888 2889 const UniformBlock &uniformBlock = *uniformBlocks[index]; 2890 2891 if(bufSize > 0) 2892 { 2893 std::string string = uniformBlock.name; 2894 2895 if(uniformBlock.isArrayElement()) 2896 { 2897 std::ostringstream elementIndex; 2898 elementIndex << uniformBlock.elementIndex; 2899 string += "[" + elementIndex.str() + "]"; 2900 } 2901 2902 strncpy(name, string.c_str(), bufSize); 2903 name[bufSize - 1] = '\0'; 2904 2905 if(length) 2906 { 2907 *length = static_cast<GLsizei>(strlen(name)); 2908 } 2909 } 2910 } 2911 getActiveUniformBlockCount() const2912 size_t Program::getActiveUniformBlockCount() const 2913 { 2914 return uniformBlocks.size(); 2915 } 2916 getActiveUniformBlockMaxLength() const2917 GLint Program::getActiveUniformBlockMaxLength() const 2918 { 2919 GLint maxLength = 0; 2920 2921 if(isLinked()) 2922 { 2923 size_t numUniformBlocks = getActiveUniformBlockCount(); 2924 for(size_t uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) 2925 { 2926 const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex]; 2927 if(!uniformBlock.name.empty()) 2928 { 2929 GLint length = static_cast<GLint>(uniformBlock.name.length() + 1); 2930 2931 // Counting in "[0]". 2932 const GLint arrayLength = (uniformBlock.isArrayElement() ? 3 : 0); 2933 2934 maxLength = std::max(length + arrayLength, maxLength); 2935 } 2936 } 2937 } 2938 2939 return maxLength; 2940 } 2941 setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2942 void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) 2943 { 2944 transformFeedbackVaryings.resize(count); 2945 for(GLsizei i = 0; i < count; i++) 2946 { 2947 transformFeedbackVaryings[i] = varyings[i]; 2948 } 2949 2950 transformFeedbackBufferMode = bufferMode; 2951 } 2952 getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2953 void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const 2954 { 2955 if(linked) 2956 { 2957 ASSERT(index < transformFeedbackLinkedVaryings.size()); 2958 const LinkedVarying &varying = transformFeedbackLinkedVaryings[index]; 2959 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length())); 2960 if(length) 2961 { 2962 *length = lastNameIdx; 2963 } 2964 if(size) 2965 { 2966 *size = varying.size; 2967 } 2968 if(type) 2969 { 2970 *type = varying.type; 2971 } 2972 if(name) 2973 { 2974 memcpy(name, varying.name.c_str(), lastNameIdx); 2975 name[lastNameIdx] = '\0'; 2976 } 2977 } 2978 } 2979 getTransformFeedbackVaryingCount() const2980 GLsizei Program::getTransformFeedbackVaryingCount() const 2981 { 2982 if(linked) 2983 { 2984 return static_cast<GLsizei>(transformFeedbackLinkedVaryings.size()); 2985 } 2986 else 2987 { 2988 return 0; 2989 } 2990 } 2991 getTransformFeedbackVaryingMaxLength() const2992 GLsizei Program::getTransformFeedbackVaryingMaxLength() const 2993 { 2994 if(linked) 2995 { 2996 GLsizei maxSize = 0; 2997 for(size_t i = 0; i < transformFeedbackLinkedVaryings.size(); i++) 2998 { 2999 const LinkedVarying &varying = transformFeedbackLinkedVaryings[i]; 3000 maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1)); 3001 } 3002 3003 return maxSize; 3004 } 3005 else 3006 { 3007 return 0; 3008 } 3009 } 3010 getTransformFeedbackBufferMode() const3011 GLenum Program::getTransformFeedbackBufferMode() const 3012 { 3013 return transformFeedbackBufferMode; 3014 } 3015 flagForDeletion()3016 void Program::flagForDeletion() 3017 { 3018 orphaned = true; 3019 } 3020 isFlaggedForDeletion() const3021 bool Program::isFlaggedForDeletion() const 3022 { 3023 return orphaned; 3024 } 3025 validate(Device * device)3026 void Program::validate(Device* device) 3027 { 3028 resetInfoLog(); 3029 3030 if(!isLinked()) 3031 { 3032 appendToInfoLog("Program has not been successfully linked."); 3033 validated = false; 3034 } 3035 else 3036 { 3037 applyUniforms(device); 3038 if(!validateSamplers(true)) 3039 { 3040 validated = false; 3041 } 3042 else 3043 { 3044 validated = true; 3045 } 3046 } 3047 } 3048 validateSamplers(bool logErrors)3049 bool Program::validateSamplers(bool logErrors) 3050 { 3051 // if any two active samplers in a program are of different types, but refer to the same 3052 // texture image unit, and this is the current program, then ValidateProgram will fail, and 3053 // DrawArrays and DrawElements will issue the INVALID_OPERATION error. 3054 3055 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; 3056 3057 for(unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++) 3058 { 3059 textureUnitType[i] = TEXTURE_UNKNOWN; 3060 } 3061 3062 for(unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) 3063 { 3064 if(samplersPS[i].active) 3065 { 3066 unsigned int unit = samplersPS[i].logicalTextureUnit; 3067 3068 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS) 3069 { 3070 if(logErrors) 3071 { 3072 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS); 3073 } 3074 3075 return false; 3076 } 3077 3078 if(textureUnitType[unit] != TEXTURE_UNKNOWN) 3079 { 3080 if(samplersPS[i].textureType != textureUnitType[unit]) 3081 { 3082 if(logErrors) 3083 { 3084 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit); 3085 } 3086 3087 return false; 3088 } 3089 } 3090 else 3091 { 3092 textureUnitType[unit] = samplersPS[i].textureType; 3093 } 3094 } 3095 } 3096 3097 for(unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) 3098 { 3099 if(samplersVS[i].active) 3100 { 3101 unsigned int unit = samplersVS[i].logicalTextureUnit; 3102 3103 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS) 3104 { 3105 if(logErrors) 3106 { 3107 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS); 3108 } 3109 3110 return false; 3111 } 3112 3113 if(textureUnitType[unit] != TEXTURE_UNKNOWN) 3114 { 3115 if(samplersVS[i].textureType != textureUnitType[unit]) 3116 { 3117 if(logErrors) 3118 { 3119 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit); 3120 } 3121 3122 return false; 3123 } 3124 } 3125 else 3126 { 3127 textureUnitType[unit] = samplersVS[i].textureType; 3128 } 3129 } 3130 } 3131 3132 return true; 3133 } 3134 } 3135