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