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