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. 17 18 #include "Program.h" 19 20 #include "main.h" 21 #include "Shader.h" 22 #include "utilities.h" 23 #include "common/debug.h" 24 #include "Shader/PixelShader.hpp" 25 #include "Shader/VertexShader.hpp" 26 27 #include <string> 28 #include <stdlib.h> 29 30 namespace gl 31 { 32 unsigned int Program::currentSerial = 1; 33 str(int i)34 std::string str(int i) 35 { 36 char buffer[20]; 37 sprintf(buffer, "%d", i); 38 return buffer; 39 } 40 Uniform(GLenum type,GLenum precision,const std::string & name,unsigned int arraySize)41 Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize) : type(type), precision(precision), name(name), arraySize(arraySize) 42 { 43 int bytes = UniformTypeSize(type) * size(); 44 data = new unsigned char[bytes]; 45 memset(data, 0, bytes); 46 dirty = true; 47 48 psRegisterIndex = -1; 49 vsRegisterIndex = -1; 50 } 51 ~Uniform()52 Uniform::~Uniform() 53 { 54 delete[] data; 55 } 56 isArray() const57 bool Uniform::isArray() const 58 { 59 return arraySize >= 1; 60 } 61 size() const62 int Uniform::size() const 63 { 64 return arraySize > 0 ? arraySize : 1; 65 } 66 registerCount() const67 int Uniform::registerCount() const 68 { 69 return size() * VariableRowCount(type); 70 } 71 UniformLocation(const std::string & name,unsigned int element,unsigned int index)72 UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index) 73 { 74 } 75 Program(ResourceManager * manager,GLuint handle)76 Program::Program(ResourceManager *manager, GLuint handle) : resourceManager(manager), handle(handle), serial(issueSerial()) 77 { 78 device = getDevice(); 79 80 fragmentShader = 0; 81 vertexShader = 0; 82 pixelBinary = 0; 83 vertexBinary = 0; 84 85 infoLog = 0; 86 validated = false; 87 88 unlink(); 89 90 orphaned = false; 91 referenceCount = 0; 92 } 93 ~Program()94 Program::~Program() 95 { 96 unlink(); 97 98 if(vertexShader) 99 { 100 vertexShader->release(); 101 } 102 103 if(fragmentShader) 104 { 105 fragmentShader->release(); 106 } 107 } 108 attachShader(Shader * shader)109 bool Program::attachShader(Shader *shader) 110 { 111 if(shader->getType() == GL_VERTEX_SHADER) 112 { 113 if(vertexShader) 114 { 115 return false; 116 } 117 118 vertexShader = (VertexShader*)shader; 119 vertexShader->addRef(); 120 } 121 else if(shader->getType() == GL_FRAGMENT_SHADER) 122 { 123 if(fragmentShader) 124 { 125 return false; 126 } 127 128 fragmentShader = (FragmentShader*)shader; 129 fragmentShader->addRef(); 130 } 131 else UNREACHABLE(shader->getType()); 132 133 return true; 134 } 135 detachShader(Shader * shader)136 bool Program::detachShader(Shader *shader) 137 { 138 if(shader->getType() == GL_VERTEX_SHADER) 139 { 140 if(vertexShader != shader) 141 { 142 return false; 143 } 144 145 vertexShader->release(); 146 vertexShader = 0; 147 } 148 else if(shader->getType() == GL_FRAGMENT_SHADER) 149 { 150 if(fragmentShader != shader) 151 { 152 return false; 153 } 154 155 fragmentShader->release(); 156 fragmentShader = 0; 157 } 158 else UNREACHABLE(shader->getType()); 159 160 return true; 161 } 162 getAttachedShadersCount() const163 int Program::getAttachedShadersCount() const 164 { 165 return (vertexShader ? 1 : 0) + (fragmentShader ? 1 : 0); 166 } 167 getPixelShader()168 sw::PixelShader *Program::getPixelShader() 169 { 170 return pixelBinary; 171 } 172 getVertexShader()173 sw::VertexShader *Program::getVertexShader() 174 { 175 return vertexBinary; 176 } 177 bindAttributeLocation(GLuint index,const char * name)178 void Program::bindAttributeLocation(GLuint index, const char *name) 179 { 180 if(index < MAX_VERTEX_ATTRIBS) 181 { 182 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++) 183 { 184 attributeBinding[i].erase(name); 185 } 186 187 attributeBinding[index].insert(name); 188 } 189 } 190 getAttributeLocation(const char * name)191 GLuint Program::getAttributeLocation(const char *name) 192 { 193 if(name) 194 { 195 for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++) 196 { 197 if(linkedAttribute[index].name == std::string(name)) 198 { 199 return index; 200 } 201 } 202 } 203 204 return -1; 205 } 206 getAttributeStream(int attributeIndex)207 int Program::getAttributeStream(int attributeIndex) 208 { 209 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); 210 211 return attributeStream[attributeIndex]; 212 } 213 214 // 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)215 GLint Program::getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex) 216 { 217 GLuint logicalTextureUnit = -1; 218 219 switch(type) 220 { 221 case sw::SAMPLER_PIXEL: 222 ASSERT(samplerIndex < sizeof(samplersPS) / sizeof(samplersPS[0])); 223 224 if(samplersPS[samplerIndex].active) 225 { 226 logicalTextureUnit = samplersPS[samplerIndex].logicalTextureUnit; 227 } 228 break; 229 case sw::SAMPLER_VERTEX: 230 ASSERT(samplerIndex < sizeof(samplersVS) / sizeof(samplersVS[0])); 231 232 if(samplersVS[samplerIndex].active) 233 { 234 logicalTextureUnit = samplersVS[samplerIndex].logicalTextureUnit; 235 } 236 break; 237 default: UNREACHABLE(type); 238 } 239 240 if(logicalTextureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS) 241 { 242 return logicalTextureUnit; 243 } 244 245 return -1; 246 } 247 248 // 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)249 TextureType Program::getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex) 250 { 251 switch(type) 252 { 253 case sw::SAMPLER_PIXEL: 254 ASSERT(samplerIndex < sizeof(samplersPS)/sizeof(samplersPS[0])); 255 ASSERT(samplersPS[samplerIndex].active); 256 return samplersPS[samplerIndex].textureType; 257 case sw::SAMPLER_VERTEX: 258 ASSERT(samplerIndex < sizeof(samplersVS)/sizeof(samplersVS[0])); 259 ASSERT(samplersVS[samplerIndex].active); 260 return samplersVS[samplerIndex].textureType; 261 default: UNREACHABLE(type); 262 } 263 264 return TEXTURE_2D; 265 } 266 getUniformLocation(std::string name)267 GLint Program::getUniformLocation(std::string name) 268 { 269 int subscript = 0; 270 271 // Strip any trailing array operator and retrieve the subscript 272 size_t open = name.find_last_of('['); 273 size_t close = name.find_last_of(']'); 274 if(open != std::string::npos && close == name.length() - 1) 275 { 276 subscript = atoi(name.substr(open + 1).c_str()); 277 name.erase(open); 278 } 279 280 unsigned int numUniforms = uniformIndex.size(); 281 for(unsigned int location = 0; location < numUniforms; location++) 282 { 283 if(uniformIndex[location].name == name && 284 uniformIndex[location].element == subscript) 285 { 286 return location; 287 } 288 } 289 290 return -1; 291 } 292 setUniform1fv(GLint location,GLsizei count,const GLfloat * v)293 bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) 294 { 295 if(location < 0 || location >= (int)uniformIndex.size()) 296 { 297 return false; 298 } 299 300 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 301 targetUniform->dirty = true; 302 303 int size = targetUniform->size(); 304 305 if(size == 1 && count > 1) 306 { 307 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 308 } 309 310 count = std::min(size - (int)uniformIndex[location].element, count); 311 312 if(targetUniform->type == GL_FLOAT) 313 { 314 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat), 315 v, sizeof(GLfloat) * count); 316 } 317 else if(targetUniform->type == GL_BOOL) 318 { 319 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element; 320 321 for(int i = 0; i < count; i++) 322 { 323 if(v[i] == 0.0f) 324 { 325 boolParams[i] = GL_FALSE; 326 } 327 else 328 { 329 boolParams[i] = GL_TRUE; 330 } 331 } 332 } 333 else 334 { 335 return false; 336 } 337 338 return true; 339 } 340 setUniform2fv(GLint location,GLsizei count,const GLfloat * v)341 bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) 342 { 343 if(location < 0 || location >= (int)uniformIndex.size()) 344 { 345 return false; 346 } 347 348 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 349 targetUniform->dirty = true; 350 351 int size = targetUniform->size(); 352 353 if(size == 1 && count > 1) 354 { 355 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 356 } 357 358 count = std::min(size - (int)uniformIndex[location].element, count); 359 360 if(targetUniform->type == GL_FLOAT_VEC2) 361 { 362 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 2, 363 v, 2 * sizeof(GLfloat) * count); 364 } 365 else if(targetUniform->type == GL_BOOL_VEC2) 366 { 367 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 2; 368 369 for(int i = 0; i < count * 2; i++) 370 { 371 if(v[i] == 0.0f) 372 { 373 boolParams[i] = GL_FALSE; 374 } 375 else 376 { 377 boolParams[i] = GL_TRUE; 378 } 379 } 380 } 381 else 382 { 383 return false; 384 } 385 386 return true; 387 } 388 setUniform3fv(GLint location,GLsizei count,const GLfloat * v)389 bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) 390 { 391 if(location < 0 || location >= (int)uniformIndex.size()) 392 { 393 return false; 394 } 395 396 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 397 targetUniform->dirty = true; 398 399 int size = targetUniform->size(); 400 401 if(size == 1 && count > 1) 402 { 403 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 404 } 405 406 count = std::min(size - (int)uniformIndex[location].element, count); 407 408 if(targetUniform->type == GL_FLOAT_VEC3) 409 { 410 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 3, 411 v, 3 * sizeof(GLfloat) * count); 412 } 413 else if(targetUniform->type == GL_BOOL_VEC3) 414 { 415 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 3; 416 417 for(int i = 0; i < count * 3; i++) 418 { 419 if(v[i] == 0.0f) 420 { 421 boolParams[i] = GL_FALSE; 422 } 423 else 424 { 425 boolParams[i] = GL_TRUE; 426 } 427 } 428 } 429 else 430 { 431 return false; 432 } 433 434 return true; 435 } 436 setUniform4fv(GLint location,GLsizei count,const GLfloat * v)437 bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) 438 { 439 if(location < 0 || location >= (int)uniformIndex.size()) 440 { 441 return false; 442 } 443 444 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 445 targetUniform->dirty = true; 446 447 int size = targetUniform->size(); 448 449 if(size == 1 && count > 1) 450 { 451 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 452 } 453 454 count = std::min(size - (int)uniformIndex[location].element, count); 455 456 if(targetUniform->type == GL_FLOAT_VEC4) 457 { 458 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4, 459 v, 4 * sizeof(GLfloat) * count); 460 } 461 else if(targetUniform->type == GL_BOOL_VEC4) 462 { 463 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 4; 464 465 for(int i = 0; i < count * 4; i++) 466 { 467 if(v[i] == 0.0f) 468 { 469 boolParams[i] = GL_FALSE; 470 } 471 else 472 { 473 boolParams[i] = GL_TRUE; 474 } 475 } 476 } 477 else 478 { 479 return false; 480 } 481 482 return true; 483 } 484 setUniformMatrix2fv(GLint location,GLsizei count,const GLfloat * value)485 bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value) 486 { 487 if(location < 0 || location >= (int)uniformIndex.size()) 488 { 489 return false; 490 } 491 492 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 493 targetUniform->dirty = true; 494 495 if(targetUniform->type != GL_FLOAT_MAT2) 496 { 497 return false; 498 } 499 500 int size = targetUniform->size(); 501 502 if(size == 1 && count > 1) 503 { 504 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 505 } 506 507 count = std::min(size - (int)uniformIndex[location].element, count); 508 509 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4, 510 value, 4 * sizeof(GLfloat) * count); 511 512 return true; 513 } 514 setUniformMatrix3fv(GLint location,GLsizei count,const GLfloat * value)515 bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value) 516 { 517 if(location < 0 || location >= (int)uniformIndex.size()) 518 { 519 return false; 520 } 521 522 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 523 targetUniform->dirty = true; 524 525 if(targetUniform->type != GL_FLOAT_MAT3) 526 { 527 return false; 528 } 529 530 int size = targetUniform->size(); 531 532 if(size == 1 && count > 1) 533 { 534 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 535 } 536 537 count = std::min(size - (int)uniformIndex[location].element, count); 538 539 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 9, 540 value, 9 * sizeof(GLfloat) * count); 541 542 return true; 543 } 544 setUniformMatrix4fv(GLint location,GLsizei count,const GLfloat * value)545 bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value) 546 { 547 if(location < 0 || location >= (int)uniformIndex.size()) 548 { 549 return false; 550 } 551 552 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 553 targetUniform->dirty = true; 554 555 if(targetUniform->type != GL_FLOAT_MAT4) 556 { 557 return false; 558 } 559 560 int size = targetUniform->size(); 561 562 if(size == 1 && count > 1) 563 { 564 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 565 } 566 567 count = std::min(size - (int)uniformIndex[location].element, count); 568 569 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 16, 570 value, 16 * sizeof(GLfloat) * count); 571 572 return true; 573 } 574 setUniform1iv(GLint location,GLsizei count,const GLint * v)575 bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v) 576 { 577 if(location < 0 || location >= (int)uniformIndex.size()) 578 { 579 return false; 580 } 581 582 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 583 targetUniform->dirty = true; 584 585 int size = targetUniform->size(); 586 587 if(size == 1 && count > 1) 588 { 589 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 590 } 591 592 count = std::min(size - (int)uniformIndex[location].element, count); 593 594 if(targetUniform->type == GL_INT || 595 targetUniform->type == GL_SAMPLER_2D || 596 targetUniform->type == GL_SAMPLER_CUBE) 597 { 598 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint), 599 v, sizeof(GLint) * count); 600 } 601 else if(targetUniform->type == GL_BOOL) 602 { 603 GLboolean *boolParams = new GLboolean[count]; 604 605 for(int i = 0; i < count; i++) 606 { 607 if(v[i] == 0) 608 { 609 boolParams[i] = GL_FALSE; 610 } 611 else 612 { 613 boolParams[i] = GL_TRUE; 614 } 615 } 616 617 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean), 618 boolParams, sizeof(GLboolean) * count); 619 620 delete[] boolParams; 621 } 622 else 623 { 624 return false; 625 } 626 627 return true; 628 } 629 setUniform2iv(GLint location,GLsizei count,const GLint * v)630 bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v) 631 { 632 if(location < 0 || location >= (int)uniformIndex.size()) 633 { 634 return false; 635 } 636 637 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 638 targetUniform->dirty = true; 639 640 int size = targetUniform->size(); 641 642 if(size == 1 && count > 1) 643 { 644 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 645 } 646 647 count = std::min(size - (int)uniformIndex[location].element, count); 648 649 if(targetUniform->type == GL_INT_VEC2) 650 { 651 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 2, 652 v, 2 * sizeof(GLint) * count); 653 } 654 else if(targetUniform->type == GL_BOOL_VEC2) 655 { 656 GLboolean *boolParams = new GLboolean[count * 2]; 657 658 for(int i = 0; i < count * 2; i++) 659 { 660 if(v[i] == 0) 661 { 662 boolParams[i] = GL_FALSE; 663 } 664 else 665 { 666 boolParams[i] = GL_TRUE; 667 } 668 } 669 670 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 2, 671 boolParams, 2 * sizeof(GLboolean) * count); 672 673 delete[] boolParams; 674 } 675 else 676 { 677 return false; 678 } 679 680 return true; 681 } 682 setUniform3iv(GLint location,GLsizei count,const GLint * v)683 bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v) 684 { 685 if(location < 0 || location >= (int)uniformIndex.size()) 686 { 687 return false; 688 } 689 690 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 691 targetUniform->dirty = true; 692 693 int size = targetUniform->size(); 694 695 if(size == 1 && count > 1) 696 { 697 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 698 } 699 700 count = std::min(size - (int)uniformIndex[location].element, count); 701 702 if(targetUniform->type == GL_INT_VEC3) 703 { 704 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 3, 705 v, 3 * sizeof(GLint) * count); 706 } 707 else if(targetUniform->type == GL_BOOL_VEC3) 708 { 709 GLboolean *boolParams = new GLboolean[count * 3]; 710 711 for(int i = 0; i < count * 3; i++) 712 { 713 if(v[i] == 0) 714 { 715 boolParams[i] = GL_FALSE; 716 } 717 else 718 { 719 boolParams[i] = GL_TRUE; 720 } 721 } 722 723 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 3, 724 boolParams, 3 * sizeof(GLboolean) * count); 725 726 delete[] boolParams; 727 } 728 else 729 { 730 return false; 731 } 732 733 return true; 734 } 735 setUniform4iv(GLint location,GLsizei count,const GLint * v)736 bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v) 737 { 738 if(location < 0 || location >= (int)uniformIndex.size()) 739 { 740 return false; 741 } 742 743 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 744 targetUniform->dirty = true; 745 746 int size = targetUniform->size(); 747 748 if(size == 1 && count > 1) 749 { 750 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION 751 } 752 753 count = std::min(size - (int)uniformIndex[location].element, count); 754 755 if(targetUniform->type == GL_INT_VEC4) 756 { 757 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 4, 758 v, 4 * sizeof(GLint) * count); 759 } 760 else if(targetUniform->type == GL_BOOL_VEC4) 761 { 762 GLboolean *boolParams = new GLboolean[count * 4]; 763 764 for(int i = 0; i < count * 4; i++) 765 { 766 if(v[i] == 0) 767 { 768 boolParams[i] = GL_FALSE; 769 } 770 else 771 { 772 boolParams[i] = GL_TRUE; 773 } 774 } 775 776 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 4, 777 boolParams, 4 * sizeof(GLboolean) * count); 778 779 delete[] boolParams; 780 } 781 else 782 { 783 return false; 784 } 785 786 return true; 787 } 788 getUniformfv(GLint location,GLsizei * bufSize,GLfloat * params)789 bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) 790 { 791 if(location < 0 || location >= (int)uniformIndex.size()) 792 { 793 return false; 794 } 795 796 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 797 unsigned int count = UniformComponentCount(targetUniform->type); 798 799 // Sized query - ensure the provided buffer is large enough 800 if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLfloat)) 801 { 802 return false; 803 } 804 805 switch(UniformComponentType(targetUniform->type)) 806 { 807 case GL_BOOL: 808 { 809 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * count; 810 811 for(unsigned int i = 0; i < count; i++) 812 { 813 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f; 814 } 815 } 816 break; 817 case GL_FLOAT: 818 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLfloat), 819 count * sizeof(GLfloat)); 820 break; 821 case GL_INT: 822 { 823 GLint *intParams = (GLint*)targetUniform->data + uniformIndex[location].element * count; 824 825 for(unsigned int i = 0; i < count; i++) 826 { 827 params[i] = (float)intParams[i]; 828 } 829 } 830 break; 831 default: UNREACHABLE(targetUniform->type); 832 } 833 834 return true; 835 } 836 getUniformiv(GLint location,GLsizei * bufSize,GLint * params)837 bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) 838 { 839 if(location < 0 || location >= (int)uniformIndex.size()) 840 { 841 return false; 842 } 843 844 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 845 unsigned int count = UniformComponentCount(targetUniform->type); 846 847 // Sized query - ensure the provided buffer is large enough 848 if(bufSize && static_cast<unsigned int>(*bufSize) < count *sizeof(GLint)) 849 { 850 return false; 851 } 852 853 switch(UniformComponentType(targetUniform->type)) 854 { 855 case GL_BOOL: 856 { 857 GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count; 858 859 for(unsigned int i = 0; i < count; i++) 860 { 861 params[i] = (GLint)boolParams[i]; 862 } 863 } 864 break; 865 case GL_FLOAT: 866 { 867 GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count; 868 869 for(unsigned int i = 0; i < count; i++) 870 { 871 params[i] = (GLint)floatParams[i]; 872 } 873 } 874 break; 875 case GL_INT: 876 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLint), 877 count * sizeof(GLint)); 878 break; 879 default: UNREACHABLE(targetUniform->type); 880 } 881 882 return true; 883 } 884 dirtyAllUniforms()885 void Program::dirtyAllUniforms() 886 { 887 unsigned int numUniforms = uniforms.size(); 888 for(unsigned int index = 0; index < numUniforms; index++) 889 { 890 uniforms[index]->dirty = true; 891 } 892 } 893 894 // Applies all the uniforms set for this program object to the device applyUniforms()895 void Program::applyUniforms() 896 { 897 unsigned int numUniforms = uniformIndex.size(); 898 for(unsigned int location = 0; location < numUniforms; location++) 899 { 900 if(uniformIndex[location].element != 0) 901 { 902 continue; 903 } 904 905 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 906 907 if(targetUniform->dirty) 908 { 909 int size = targetUniform->size(); 910 GLfloat *f = (GLfloat*)targetUniform->data; 911 GLint *i = (GLint*)targetUniform->data; 912 GLboolean *b = (GLboolean*)targetUniform->data; 913 914 switch(targetUniform->type) 915 { 916 case GL_BOOL: applyUniform1bv(location, size, b); break; 917 case GL_BOOL_VEC2: applyUniform2bv(location, size, b); break; 918 case GL_BOOL_VEC3: applyUniform3bv(location, size, b); break; 919 case GL_BOOL_VEC4: applyUniform4bv(location, size, b); break; 920 case GL_FLOAT: applyUniform1fv(location, size, f); break; 921 case GL_FLOAT_VEC2: applyUniform2fv(location, size, f); break; 922 case GL_FLOAT_VEC3: applyUniform3fv(location, size, f); break; 923 case GL_FLOAT_VEC4: applyUniform4fv(location, size, f); break; 924 case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, size, f); break; 925 case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, size, f); break; 926 case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, size, f); break; 927 case GL_SAMPLER_2D: 928 case GL_SAMPLER_CUBE: 929 case GL_INT: applyUniform1iv(location, size, i); break; 930 case GL_INT_VEC2: applyUniform2iv(location, size, i); break; 931 case GL_INT_VEC3: applyUniform3iv(location, size, i); break; 932 case GL_INT_VEC4: applyUniform4iv(location, size, i); break; 933 default: 934 UNREACHABLE(targetUniform->type); 935 } 936 937 targetUniform->dirty = false; 938 } 939 } 940 } 941 942 // Packs varyings into generic varying registers. 943 // Returns the number of used varying registers, or -1 if unsuccesful packVaryings(const glsl::Varying * packing[][4])944 int Program::packVaryings(const glsl::Varying *packing[][4]) 945 { 946 for(glsl::VaryingList::iterator varying = fragmentShader->varyings.begin(); varying != fragmentShader->varyings.end(); varying++) 947 { 948 int n = VariableRowCount(varying->type) * varying->size(); 949 int m = VariableColumnCount(varying->type); 950 bool success = false; 951 952 if(m == 2 || m == 3 || m == 4) 953 { 954 for(int r = 0; r <= MAX_VARYING_VECTORS - n && !success; r++) 955 { 956 bool available = true; 957 958 for(int y = 0; y < n && available; y++) 959 { 960 for(int x = 0; x < m && available; x++) 961 { 962 if(packing[r + y][x]) 963 { 964 available = false; 965 } 966 } 967 } 968 969 if(available) 970 { 971 varying->reg = r; 972 varying->col = 0; 973 974 for(int y = 0; y < n; y++) 975 { 976 for(int x = 0; x < m; x++) 977 { 978 packing[r + y][x] = &*varying; 979 } 980 } 981 982 success = true; 983 } 984 } 985 986 if(!success && m == 2) 987 { 988 for(int r = MAX_VARYING_VECTORS - n; r >= 0 && !success; r--) 989 { 990 bool available = true; 991 992 for(int y = 0; y < n && available; y++) 993 { 994 for(int x = 2; x < 4 && available; x++) 995 { 996 if(packing[r + y][x]) 997 { 998 available = false; 999 } 1000 } 1001 } 1002 1003 if(available) 1004 { 1005 varying->reg = r; 1006 varying->col = 2; 1007 1008 for(int y = 0; y < n; y++) 1009 { 1010 for(int x = 2; x < 4; x++) 1011 { 1012 packing[r + y][x] = &*varying; 1013 } 1014 } 1015 1016 success = true; 1017 } 1018 } 1019 } 1020 } 1021 else if(m == 1) 1022 { 1023 int space[4] = {0}; 1024 1025 for(int y = 0; y < MAX_VARYING_VECTORS; y++) 1026 { 1027 for(int x = 0; x < 4; x++) 1028 { 1029 space[x] += packing[y][x] ? 0 : 1; 1030 } 1031 } 1032 1033 int column = 0; 1034 1035 for(int x = 0; x < 4; x++) 1036 { 1037 if(space[x] >= n && space[x] < space[column]) 1038 { 1039 column = x; 1040 } 1041 } 1042 1043 if(space[column] >= n) 1044 { 1045 for(int r = 0; r < MAX_VARYING_VECTORS; r++) 1046 { 1047 if(!packing[r][column]) 1048 { 1049 varying->reg = r; 1050 1051 for(int y = r; y < r + n; y++) 1052 { 1053 packing[y][column] = &*varying; 1054 } 1055 1056 break; 1057 } 1058 } 1059 1060 varying->col = column; 1061 1062 success = true; 1063 } 1064 } 1065 else UNREACHABLE(m); 1066 1067 if(!success) 1068 { 1069 appendToInfoLog("Could not pack varying %s", varying->name.c_str()); 1070 1071 return -1; 1072 } 1073 } 1074 1075 // Return the number of used registers 1076 int registers = 0; 1077 1078 for(int r = 0; r < MAX_VARYING_VECTORS; r++) 1079 { 1080 if(packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) 1081 { 1082 registers++; 1083 } 1084 } 1085 1086 return registers; 1087 } 1088 linkVaryings()1089 bool Program::linkVaryings() 1090 { 1091 for(glsl::VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); input++) 1092 { 1093 bool matched = false; 1094 1095 for(glsl::VaryingList::iterator output = vertexShader->varyings.begin(); output != vertexShader->varyings.end(); output++) 1096 { 1097 if(output->name == input->name) 1098 { 1099 if(output->type != input->type || output->size() != input->size()) 1100 { 1101 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str()); 1102 1103 return false; 1104 } 1105 1106 matched = true; 1107 break; 1108 } 1109 } 1110 1111 if(!matched) 1112 { 1113 appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str()); 1114 1115 return false; 1116 } 1117 } 1118 1119 glsl::VaryingList &psVaryings = fragmentShader->varyings; 1120 glsl::VaryingList &vsVaryings = vertexShader->varyings; 1121 1122 for(glsl::VaryingList::iterator output = vsVaryings.begin(); output != vsVaryings.end(); output++) 1123 { 1124 for(glsl::VaryingList::iterator input = psVaryings.begin(); input != psVaryings.end(); input++) 1125 { 1126 if(output->name == input->name) 1127 { 1128 int in = input->reg; 1129 int out = output->reg; 1130 int components = VariableColumnCount(output->type); 1131 int registers = VariableRowCount(output->type) * output->size(); 1132 1133 ASSERT(in >= 0); 1134 1135 if(in + registers > MAX_VARYING_VECTORS) 1136 { 1137 appendToInfoLog("Too many varyings"); 1138 return false; 1139 } 1140 1141 if(out >= 0) 1142 { 1143 if(out + registers > MAX_VARYING_VECTORS) 1144 { 1145 appendToInfoLog("Too many varyings"); 1146 return false; 1147 } 1148 1149 for(int i = 0; i < registers; i++) 1150 { 1151 if(components >= 1) vertexBinary->output[out + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i); 1152 if(components >= 2) vertexBinary->output[out + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i); 1153 if(components >= 3) vertexBinary->output[out + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i); 1154 if(components >= 4) vertexBinary->output[out + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i); 1155 } 1156 } 1157 else // Vertex varying is declared but not written to 1158 { 1159 for(int i = 0; i < registers; i++) 1160 { 1161 if(components >= 1) pixelBinary->semantic[in + i][0] = sw::Shader::Semantic(); 1162 if(components >= 2) pixelBinary->semantic[in + i][1] = sw::Shader::Semantic(); 1163 if(components >= 3) pixelBinary->semantic[in + i][2] = sw::Shader::Semantic(); 1164 if(components >= 4) pixelBinary->semantic[in + i][3] = sw::Shader::Semantic(); 1165 } 1166 } 1167 1168 break; 1169 } 1170 } 1171 } 1172 1173 return true; 1174 } 1175 1176 // Links the code of the vertex and pixel shader by matching up their varyings, 1177 // compiling them into binaries, determining the attribute mappings, and collecting 1178 // a list of uniforms link()1179 void Program::link() 1180 { 1181 unlink(); 1182 1183 if(!fragmentShader || !fragmentShader->isCompiled()) 1184 { 1185 return; 1186 } 1187 1188 if(!vertexShader || !vertexShader->isCompiled()) 1189 { 1190 return; 1191 } 1192 1193 vertexBinary = new sw::VertexShader(vertexShader->getVertexShader()); 1194 pixelBinary = new sw::PixelShader(fragmentShader->getPixelShader()); 1195 1196 if(!linkVaryings()) 1197 { 1198 return; 1199 } 1200 1201 if(!linkAttributes()) 1202 { 1203 return; 1204 } 1205 1206 if(!linkUniforms(fragmentShader)) 1207 { 1208 return; 1209 } 1210 1211 if(!linkUniforms(vertexShader)) 1212 { 1213 return; 1214 } 1215 1216 linked = true; // Success 1217 } 1218 1219 // Determines the mapping between GL attributes and vertex stream usage indices linkAttributes()1220 bool Program::linkAttributes() 1221 { 1222 unsigned int usedLocations = 0; 1223 1224 // Link attributes that have a binding location 1225 for(glsl::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++) 1226 { 1227 int location = getAttributeBinding(attribute->name); 1228 1229 if(location != -1) // Set by glBindAttribLocation 1230 { 1231 if(!linkedAttribute[location].name.empty()) 1232 { 1233 // Multiple active attributes bound to the same location; not an error 1234 } 1235 1236 linkedAttribute[location] = *attribute; 1237 1238 int rows = VariableRowCount(attribute->type); 1239 1240 if(rows + location > MAX_VERTEX_ATTRIBS) 1241 { 1242 appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location); 1243 return false; 1244 } 1245 1246 for(int i = 0; i < rows; i++) 1247 { 1248 usedLocations |= 1 << (location + i); 1249 } 1250 } 1251 } 1252 1253 // Link attributes that don't have a binding location 1254 for(glsl::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++) 1255 { 1256 int location = getAttributeBinding(attribute->name); 1257 1258 if(location == -1) // Not set by glBindAttribLocation 1259 { 1260 int rows = VariableRowCount(attribute->type); 1261 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); 1262 1263 if(availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) 1264 { 1265 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str()); 1266 return false; // Fail to link 1267 } 1268 1269 linkedAttribute[availableIndex] = *attribute; 1270 } 1271 } 1272 1273 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) 1274 { 1275 int index = vertexShader->getSemanticIndex(linkedAttribute[attributeIndex].name); 1276 int rows = std::max(VariableRowCount(linkedAttribute[attributeIndex].type), 1); 1277 1278 for(int r = 0; r < rows; r++) 1279 { 1280 attributeStream[attributeIndex++] = index++; 1281 } 1282 } 1283 1284 return true; 1285 } 1286 getAttributeBinding(const std::string & name)1287 int Program::getAttributeBinding(const std::string &name) 1288 { 1289 for(int location = 0; location < MAX_VERTEX_ATTRIBS; location++) 1290 { 1291 if(attributeBinding[location].find(name) != attributeBinding[location].end()) 1292 { 1293 return location; 1294 } 1295 } 1296 1297 return -1; 1298 } 1299 linkUniforms(Shader * shader)1300 bool Program::linkUniforms(Shader *shader) 1301 { 1302 const glsl::ActiveUniforms &activeUniforms = shader->activeUniforms; 1303 1304 for(unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++) 1305 { 1306 const glsl::Uniform &uniform = activeUniforms[uniformIndex]; 1307 1308 if(!defineUniform(shader->getType(), uniform.type, uniform.precision, uniform.name, uniform.arraySize, uniform.registerIndex)) 1309 { 1310 return false; 1311 } 1312 } 1313 1314 return true; 1315 } 1316 defineUniform(GLenum shader,GLenum type,GLenum precision,const std::string & name,unsigned int arraySize,int registerIndex)1317 bool Program::defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, int registerIndex) 1318 { 1319 if(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE) 1320 { 1321 int index = registerIndex; 1322 1323 do 1324 { 1325 if(shader == GL_VERTEX_SHADER) 1326 { 1327 if(index < MAX_VERTEX_TEXTURE_IMAGE_UNITS) 1328 { 1329 samplersVS[index].active = true; 1330 samplersVS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; 1331 samplersVS[index].logicalTextureUnit = 0; 1332 } 1333 else 1334 { 1335 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", MAX_VERTEX_TEXTURE_IMAGE_UNITS); 1336 return false; 1337 } 1338 } 1339 else if(shader == GL_FRAGMENT_SHADER) 1340 { 1341 if(index < MAX_TEXTURE_IMAGE_UNITS) 1342 { 1343 samplersPS[index].active = true; 1344 samplersPS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; 1345 samplersPS[index].logicalTextureUnit = 0; 1346 } 1347 else 1348 { 1349 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); 1350 return false; 1351 } 1352 } 1353 else UNREACHABLE(shader); 1354 1355 index++; 1356 } 1357 while(index < registerIndex + static_cast<int>(arraySize)); 1358 } 1359 1360 Uniform *uniform = 0; 1361 GLint location = getUniformLocation(name); 1362 1363 if(location >= 0) // Previously defined, types must match 1364 { 1365 uniform = uniforms[uniformIndex[location].index]; 1366 1367 if(uniform->type != type) 1368 { 1369 appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); 1370 return false; 1371 } 1372 1373 if(uniform->precision != precision) 1374 { 1375 appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); 1376 return false; 1377 } 1378 } 1379 else 1380 { 1381 uniform = new Uniform(type, precision, name, arraySize); 1382 } 1383 1384 if(!uniform) 1385 { 1386 return false; 1387 } 1388 1389 if(shader == GL_VERTEX_SHADER) 1390 { 1391 uniform->vsRegisterIndex = registerIndex; 1392 } 1393 else if(shader == GL_FRAGMENT_SHADER) 1394 { 1395 uniform->psRegisterIndex = registerIndex; 1396 } 1397 else UNREACHABLE(shader); 1398 1399 if(location == -1) // Not previously defined 1400 { 1401 uniforms.push_back(uniform); 1402 unsigned int index = uniforms.size() - 1; 1403 1404 for(int i = 0; i < uniform->size(); i++) 1405 { 1406 uniformIndex.push_back(UniformLocation(name, i, index)); 1407 } 1408 } 1409 1410 if(shader == GL_VERTEX_SHADER) 1411 { 1412 if(registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS) 1413 { 1414 appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS); 1415 return false; 1416 } 1417 } 1418 else if(shader == GL_FRAGMENT_SHADER) 1419 { 1420 if(registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS) 1421 { 1422 appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS); 1423 return false; 1424 } 1425 } 1426 else UNREACHABLE(shader); 1427 1428 return true; 1429 } 1430 applyUniform1bv(GLint location,GLsizei count,const GLboolean * v)1431 bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v) 1432 { 1433 int vector[MAX_UNIFORM_VECTORS][4]; 1434 1435 for(int i = 0; i < count; i++) 1436 { 1437 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1438 vector[i][1] = 0; 1439 vector[i][2] = 0; 1440 vector[i][3] = 0; 1441 1442 v += 1; 1443 } 1444 1445 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1446 1447 if(targetUniform->psRegisterIndex != -1) 1448 { 1449 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1450 } 1451 1452 if(targetUniform->vsRegisterIndex != -1) 1453 { 1454 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1455 } 1456 1457 return true; 1458 } 1459 applyUniform2bv(GLint location,GLsizei count,const GLboolean * v)1460 bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v) 1461 { 1462 int vector[MAX_UNIFORM_VECTORS][4]; 1463 1464 for(int i = 0; i < count; i++) 1465 { 1466 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1467 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1468 vector[i][2] = 0; 1469 vector[i][3] = 0; 1470 1471 v += 2; 1472 } 1473 1474 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1475 1476 if(targetUniform->psRegisterIndex != -1) 1477 { 1478 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1479 } 1480 1481 if(targetUniform->vsRegisterIndex != -1) 1482 { 1483 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1484 } 1485 1486 return true; 1487 } 1488 applyUniform3bv(GLint location,GLsizei count,const GLboolean * v)1489 bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v) 1490 { 1491 int vector[MAX_UNIFORM_VECTORS][4]; 1492 1493 for(int i = 0; i < count; i++) 1494 { 1495 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1496 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1497 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1498 vector[i][3] = 0; 1499 1500 v += 3; 1501 } 1502 1503 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1504 1505 if(targetUniform->psRegisterIndex != -1) 1506 { 1507 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1508 } 1509 1510 if(targetUniform->vsRegisterIndex != -1) 1511 { 1512 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1513 } 1514 1515 return true; 1516 } 1517 applyUniform4bv(GLint location,GLsizei count,const GLboolean * v)1518 bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v) 1519 { 1520 int vector[MAX_UNIFORM_VECTORS][4]; 1521 1522 for(int i = 0; i < count; i++) 1523 { 1524 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1525 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1526 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1527 vector[i][3] = (v[3] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF); 1528 1529 v += 4; 1530 } 1531 1532 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1533 1534 if(targetUniform->psRegisterIndex != -1) 1535 { 1536 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1537 } 1538 1539 if(targetUniform->vsRegisterIndex != -1) 1540 { 1541 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1542 } 1543 1544 return true; 1545 } 1546 applyUniform1fv(GLint location,GLsizei count,const GLfloat * v)1547 bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v) 1548 { 1549 float vector[MAX_UNIFORM_VECTORS][4]; 1550 1551 for(int i = 0; i < count; i++) 1552 { 1553 vector[i][0] = v[0]; 1554 vector[i][1] = 0; 1555 vector[i][2] = 0; 1556 vector[i][3] = 0; 1557 1558 v += 1; 1559 } 1560 1561 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1562 1563 if(targetUniform->psRegisterIndex != -1) 1564 { 1565 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1566 } 1567 1568 if(targetUniform->vsRegisterIndex != -1) 1569 { 1570 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1571 } 1572 1573 return true; 1574 } 1575 applyUniform2fv(GLint location,GLsizei count,const GLfloat * v)1576 bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v) 1577 { 1578 float vector[MAX_UNIFORM_VECTORS][4]; 1579 1580 for(int i = 0; i < count; i++) 1581 { 1582 vector[i][0] = v[0]; 1583 vector[i][1] = v[1]; 1584 vector[i][2] = 0; 1585 vector[i][3] = 0; 1586 1587 v += 2; 1588 } 1589 1590 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1591 1592 if(targetUniform->psRegisterIndex != -1) 1593 { 1594 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1595 } 1596 1597 if(targetUniform->vsRegisterIndex != -1) 1598 { 1599 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1600 } 1601 1602 return true; 1603 } 1604 applyUniform3fv(GLint location,GLsizei count,const GLfloat * v)1605 bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v) 1606 { 1607 float vector[MAX_UNIFORM_VECTORS][4]; 1608 1609 for(int i = 0; i < count; i++) 1610 { 1611 vector[i][0] = v[0]; 1612 vector[i][1] = v[1]; 1613 vector[i][2] = v[2]; 1614 vector[i][3] = 0; 1615 1616 v += 3; 1617 } 1618 1619 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1620 1621 if(targetUniform->psRegisterIndex != -1) 1622 { 1623 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1624 } 1625 1626 if(targetUniform->vsRegisterIndex != -1) 1627 { 1628 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1629 } 1630 1631 return true; 1632 } 1633 applyUniform4fv(GLint location,GLsizei count,const GLfloat * v)1634 bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v) 1635 { 1636 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1637 1638 if(targetUniform->psRegisterIndex != -1) 1639 { 1640 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)v, targetUniform->registerCount()); 1641 } 1642 1643 if(targetUniform->vsRegisterIndex != -1) 1644 { 1645 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)v, targetUniform->registerCount()); 1646 } 1647 1648 return true; 1649 } 1650 applyUniformMatrix2fv(GLint location,GLsizei count,const GLfloat * value)1651 bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value) 1652 { 1653 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4]; 1654 1655 for(int i = 0; i < count; i++) 1656 { 1657 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0; 1658 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0; 1659 1660 value += 4; 1661 } 1662 1663 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1664 1665 if(targetUniform->psRegisterIndex != -1) 1666 { 1667 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount()); 1668 } 1669 1670 if(targetUniform->vsRegisterIndex != -1) 1671 { 1672 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount()); 1673 } 1674 1675 return true; 1676 } 1677 applyUniformMatrix3fv(GLint location,GLsizei count,const GLfloat * value)1678 bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value) 1679 { 1680 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4]; 1681 1682 for(int i = 0; i < count; i++) 1683 { 1684 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0; 1685 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0; 1686 matrix[i][2][0] = value[6]; matrix[i][2][1] = value[7]; matrix[i][2][2] = value[8]; matrix[i][2][3] = 0; 1687 1688 value += 9; 1689 } 1690 1691 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1692 1693 if(targetUniform->psRegisterIndex != -1) 1694 { 1695 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount()); 1696 } 1697 1698 if(targetUniform->vsRegisterIndex != -1) 1699 { 1700 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount()); 1701 } 1702 1703 return true; 1704 } 1705 applyUniformMatrix4fv(GLint location,GLsizei count,const GLfloat * value)1706 bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value) 1707 { 1708 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1709 1710 if(targetUniform->psRegisterIndex != -1) 1711 { 1712 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)value, targetUniform->registerCount()); 1713 } 1714 1715 if(targetUniform->vsRegisterIndex != -1) 1716 { 1717 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)value, targetUniform->registerCount()); 1718 } 1719 1720 return true; 1721 } 1722 applyUniform1iv(GLint location,GLsizei count,const GLint * v)1723 bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v) 1724 { 1725 float vector[MAX_UNIFORM_VECTORS][4]; 1726 1727 for(int i = 0; i < count; i++) 1728 { 1729 vector[i][0] = (float)v[i]; 1730 vector[i][1] = 0; 1731 vector[i][2] = 0; 1732 vector[i][3] = 0; 1733 } 1734 1735 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1736 1737 if(targetUniform->psRegisterIndex != -1) 1738 { 1739 if(targetUniform->type == GL_SAMPLER_2D || 1740 targetUniform->type == GL_SAMPLER_CUBE) 1741 { 1742 for(int i = 0; i < count; i++) 1743 { 1744 unsigned int samplerIndex = targetUniform->psRegisterIndex + i; 1745 1746 if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS) 1747 { 1748 ASSERT(samplersPS[samplerIndex].active); 1749 samplersPS[samplerIndex].logicalTextureUnit = v[i]; 1750 } 1751 } 1752 } 1753 else 1754 { 1755 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1756 } 1757 } 1758 1759 if(targetUniform->vsRegisterIndex != -1) 1760 { 1761 if(targetUniform->type == GL_SAMPLER_2D || 1762 targetUniform->type == GL_SAMPLER_CUBE) 1763 { 1764 for(int i = 0; i < count; i++) 1765 { 1766 unsigned int samplerIndex = targetUniform->vsRegisterIndex + i; 1767 1768 if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS) 1769 { 1770 ASSERT(samplersVS[samplerIndex].active); 1771 samplersVS[samplerIndex].logicalTextureUnit = v[i]; 1772 } 1773 } 1774 } 1775 else 1776 { 1777 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1778 } 1779 } 1780 1781 return true; 1782 } 1783 applyUniform2iv(GLint location,GLsizei count,const GLint * v)1784 bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v) 1785 { 1786 float vector[MAX_UNIFORM_VECTORS][4]; 1787 1788 for(int i = 0; i < count; i++) 1789 { 1790 vector[i][0] = (float)v[0]; 1791 vector[i][1] = (float)v[1]; 1792 vector[i][2] = 0; 1793 vector[i][3] = 0; 1794 1795 v += 2; 1796 } 1797 1798 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1799 1800 if(targetUniform->psRegisterIndex != -1) 1801 { 1802 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1803 } 1804 1805 if(targetUniform->vsRegisterIndex != -1) 1806 { 1807 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1808 } 1809 1810 return true; 1811 } 1812 applyUniform3iv(GLint location,GLsizei count,const GLint * v)1813 bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v) 1814 { 1815 float vector[MAX_UNIFORM_VECTORS][4]; 1816 1817 for(int i = 0; i < count; i++) 1818 { 1819 vector[i][0] = (float)v[0]; 1820 vector[i][1] = (float)v[1]; 1821 vector[i][2] = (float)v[2]; 1822 vector[i][3] = 0; 1823 1824 v += 3; 1825 } 1826 1827 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1828 1829 if(targetUniform->psRegisterIndex != -1) 1830 { 1831 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1832 } 1833 1834 if(targetUniform->vsRegisterIndex != -1) 1835 { 1836 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1837 } 1838 1839 return true; 1840 } 1841 applyUniform4iv(GLint location,GLsizei count,const GLint * v)1842 bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v) 1843 { 1844 float vector[MAX_UNIFORM_VECTORS][4]; 1845 1846 for(int i = 0; i < count; i++) 1847 { 1848 vector[i][0] = (float)v[0]; 1849 vector[i][1] = (float)v[1]; 1850 vector[i][2] = (float)v[2]; 1851 vector[i][3] = (float)v[3]; 1852 1853 v += 4; 1854 } 1855 1856 Uniform *targetUniform = uniforms[uniformIndex[location].index]; 1857 1858 if(targetUniform->psRegisterIndex != -1) 1859 { 1860 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount()); 1861 } 1862 1863 if(targetUniform->vsRegisterIndex != -1) 1864 { 1865 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount()); 1866 } 1867 1868 return true; 1869 } 1870 appendToInfoLog(const char * format,...)1871 void Program::appendToInfoLog(const char *format, ...) 1872 { 1873 if(!format) 1874 { 1875 return; 1876 } 1877 1878 char info[1024]; 1879 1880 va_list vararg; 1881 va_start(vararg, format); 1882 vsnprintf(info, sizeof(info), format, vararg); 1883 va_end(vararg); 1884 1885 size_t infoLength = strlen(info); 1886 1887 if(!infoLog) 1888 { 1889 infoLog = new char[infoLength + 2]; 1890 strcpy(infoLog, info); 1891 strcpy(infoLog + infoLength, "\n"); 1892 } 1893 else 1894 { 1895 size_t logLength = strlen(infoLog); 1896 char *newLog = new char[logLength + infoLength + 2]; 1897 strcpy(newLog, infoLog); 1898 strcpy(newLog + logLength, info); 1899 strcpy(newLog + logLength + infoLength, "\n"); 1900 1901 delete[] infoLog; 1902 infoLog = newLog; 1903 } 1904 } 1905 resetInfoLog()1906 void Program::resetInfoLog() 1907 { 1908 if(infoLog) 1909 { 1910 delete[] infoLog; 1911 infoLog = 0; 1912 } 1913 } 1914 1915 // Returns the program object to an unlinked state, before re-linking, or at destruction unlink()1916 void Program::unlink() 1917 { 1918 delete vertexBinary; 1919 vertexBinary = 0; 1920 delete pixelBinary; 1921 pixelBinary = 0; 1922 1923 for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++) 1924 { 1925 linkedAttribute[index].name.clear(); 1926 attributeStream[index] = -1; 1927 } 1928 1929 for(int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++) 1930 { 1931 samplersPS[index].active = false; 1932 } 1933 1934 for(int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) 1935 { 1936 samplersVS[index].active = false; 1937 } 1938 1939 while(!uniforms.empty()) 1940 { 1941 delete uniforms.back(); 1942 uniforms.pop_back(); 1943 } 1944 1945 uniformIndex.clear(); 1946 1947 delete[] infoLog; 1948 infoLog = 0; 1949 1950 linked = false; 1951 } 1952 isLinked()1953 bool Program::isLinked() 1954 { 1955 return linked; 1956 } 1957 isValidated() const1958 bool Program::isValidated() const 1959 { 1960 return validated; 1961 } 1962 release()1963 void Program::release() 1964 { 1965 referenceCount--; 1966 1967 if(referenceCount == 0 && orphaned) 1968 { 1969 resourceManager->deleteProgram(handle); 1970 } 1971 } 1972 addRef()1973 void Program::addRef() 1974 { 1975 referenceCount++; 1976 } 1977 getRefCount() const1978 unsigned int Program::getRefCount() const 1979 { 1980 return referenceCount; 1981 } 1982 getSerial() const1983 unsigned int Program::getSerial() const 1984 { 1985 return serial; 1986 } 1987 issueSerial()1988 unsigned int Program::issueSerial() 1989 { 1990 return currentSerial++; 1991 } 1992 getInfoLogLength() const1993 int Program::getInfoLogLength() const 1994 { 1995 if(!infoLog) 1996 { 1997 return 0; 1998 } 1999 else 2000 { 2001 return strlen(infoLog) + 1; 2002 } 2003 } 2004 getInfoLog(GLsizei bufSize,GLsizei * length,char * buffer)2005 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *buffer) 2006 { 2007 int index = 0; 2008 2009 if(bufSize > 0) 2010 { 2011 if(infoLog) 2012 { 2013 index = std::min(bufSize - 1, (int)strlen(infoLog)); 2014 memcpy(buffer, infoLog, index); 2015 } 2016 2017 buffer[index] = '\0'; 2018 } 2019 2020 if(length) 2021 { 2022 *length = index; 2023 } 2024 } 2025 getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders)2026 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) 2027 { 2028 int total = 0; 2029 2030 if(vertexShader) 2031 { 2032 if(total < maxCount) 2033 { 2034 shaders[total] = vertexShader->getName(); 2035 } 2036 2037 total++; 2038 } 2039 2040 if(fragmentShader) 2041 { 2042 if(total < maxCount) 2043 { 2044 shaders[total] = fragmentShader->getName(); 2045 } 2046 2047 total++; 2048 } 2049 2050 if(count) 2051 { 2052 *count = total; 2053 } 2054 } 2055 getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2056 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const 2057 { 2058 // Skip over inactive attributes 2059 unsigned int activeAttribute = 0; 2060 unsigned int attribute; 2061 for(attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) 2062 { 2063 if(linkedAttribute[attribute].name.empty()) 2064 { 2065 continue; 2066 } 2067 2068 if(activeAttribute == index) 2069 { 2070 break; 2071 } 2072 2073 activeAttribute++; 2074 } 2075 2076 if(bufsize > 0) 2077 { 2078 const char *string = linkedAttribute[attribute].name.c_str(); 2079 2080 strncpy(name, string, bufsize); 2081 name[bufsize - 1] = '\0'; 2082 2083 if(length) 2084 { 2085 *length = strlen(name); 2086 } 2087 } 2088 2089 *size = 1; // Always a single 'type' instance 2090 2091 *type = linkedAttribute[attribute].type; 2092 } 2093 getActiveAttributeCount() const2094 size_t Program::getActiveAttributeCount() const 2095 { 2096 size_t count = 0; 2097 2098 for(size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ++attributeIndex) 2099 { 2100 if(!linkedAttribute[attributeIndex].name.empty()) 2101 { 2102 count++; 2103 } 2104 } 2105 2106 return count; 2107 } 2108 getActiveAttributeMaxLength() const2109 GLint Program::getActiveAttributeMaxLength() const 2110 { 2111 int maxLength = 0; 2112 2113 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) 2114 { 2115 if(!linkedAttribute[attributeIndex].name.empty()) 2116 { 2117 maxLength = std::max((int)(linkedAttribute[attributeIndex].name.length() + 1), maxLength); 2118 } 2119 } 2120 2121 return maxLength; 2122 } 2123 getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2124 void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const 2125 { 2126 if(bufsize > 0) 2127 { 2128 std::string string = uniforms[index]->name; 2129 2130 if(uniforms[index]->isArray()) 2131 { 2132 string += "[0]"; 2133 } 2134 2135 strncpy(name, string.c_str(), bufsize); 2136 name[bufsize - 1] = '\0'; 2137 2138 if(length) 2139 { 2140 *length = strlen(name); 2141 } 2142 } 2143 2144 *size = uniforms[index]->size(); 2145 2146 *type = uniforms[index]->type; 2147 } 2148 getActiveUniformCount() const2149 size_t Program::getActiveUniformCount() const 2150 { 2151 return uniforms.size(); 2152 } 2153 getActiveUniformMaxLength() const2154 GLint Program::getActiveUniformMaxLength() const 2155 { 2156 int maxLength = 0; 2157 2158 unsigned int numUniforms = uniforms.size(); 2159 for(unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) 2160 { 2161 if(!uniforms[uniformIndex]->name.empty()) 2162 { 2163 int length = (int)(uniforms[uniformIndex]->name.length() + 1); 2164 if(uniforms[uniformIndex]->isArray()) 2165 { 2166 length += 3; // Counting in "[0]". 2167 } 2168 maxLength = std::max(length, maxLength); 2169 } 2170 } 2171 2172 return maxLength; 2173 } 2174 flagForDeletion()2175 void Program::flagForDeletion() 2176 { 2177 orphaned = true; 2178 } 2179 isFlaggedForDeletion() const2180 bool Program::isFlaggedForDeletion() const 2181 { 2182 return orphaned; 2183 } 2184 validate()2185 void Program::validate() 2186 { 2187 resetInfoLog(); 2188 2189 if(!isLinked()) 2190 { 2191 appendToInfoLog("Program has not been successfully linked."); 2192 validated = false; 2193 } 2194 else 2195 { 2196 applyUniforms(); 2197 if(!validateSamplers(true)) 2198 { 2199 validated = false; 2200 } 2201 else 2202 { 2203 validated = true; 2204 } 2205 } 2206 } 2207 validateSamplers(bool logErrors)2208 bool Program::validateSamplers(bool logErrors) 2209 { 2210 // if any two active samplers in a program are of different types, but refer to the same 2211 // texture image unit, and this is the current program, then ValidateProgram will fail, and 2212 // DrawArrays and DrawElements will issue the INVALID_OPERATION error. 2213 2214 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; 2215 2216 for(unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++) 2217 { 2218 textureUnitType[i] = TEXTURE_UNKNOWN; 2219 } 2220 2221 for(unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) 2222 { 2223 if(samplersPS[i].active) 2224 { 2225 unsigned int unit = samplersPS[i].logicalTextureUnit; 2226 2227 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS) 2228 { 2229 if(logErrors) 2230 { 2231 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS); 2232 } 2233 2234 return false; 2235 } 2236 2237 if(textureUnitType[unit] != TEXTURE_UNKNOWN) 2238 { 2239 if(samplersPS[i].textureType != textureUnitType[unit]) 2240 { 2241 if(logErrors) 2242 { 2243 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit); 2244 } 2245 2246 return false; 2247 } 2248 } 2249 else 2250 { 2251 textureUnitType[unit] = samplersPS[i].textureType; 2252 } 2253 } 2254 } 2255 2256 for(unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) 2257 { 2258 if(samplersVS[i].active) 2259 { 2260 unsigned int unit = samplersVS[i].logicalTextureUnit; 2261 2262 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS) 2263 { 2264 if(logErrors) 2265 { 2266 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS); 2267 } 2268 2269 return false; 2270 } 2271 2272 if(textureUnitType[unit] != TEXTURE_UNKNOWN) 2273 { 2274 if(samplersVS[i].textureType != textureUnitType[unit]) 2275 { 2276 if(logErrors) 2277 { 2278 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit); 2279 } 2280 2281 return false; 2282 } 2283 } 2284 else 2285 { 2286 textureUnitType[unit] = samplersVS[i].textureType; 2287 } 2288 } 2289 } 2290 2291 return true; 2292 } 2293 } 2294