1 /* 2 ----------------------------------------------------------------------------- 3 This source file is part of OGRE 4 (Object-oriented Graphics Rendering Engine) 5 For the latest info, see http://www.ogre3d.org/ 6 7 Copyright (c) 2000-2013 Torus Knot Software Ltd 8 9 Permission is hereby granted, free of charge, to any person obtaining a copy 10 of this software and associated documentation files (the "Software"), to deal 11 in the Software without restriction, including without limitation the rights 12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 copies of the Software, and to permit persons to whom the Software is 14 furnished to do so, subject to the following conditions: 15 16 The above copyright notice and this permission notice shall be included in 17 all copies or substantial portions of the Software. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 THE SOFTWARE. 26 ----------------------------------------------------------------------------- 27 */ 28 29 #include "OgreGLSLESProgramPipeline.h" 30 #include "OgreStringConverter.h" 31 #include "OgreGLSLESGpuProgram.h" 32 #include "OgreGLSLESProgram.h" 33 #include "OgreGLSLESProgramPipelineManager.h" 34 #include "OgreGpuProgramManager.h" 35 #include "OgreGLES2RenderSystem.h" 36 #include "OgreGLES2UniformCache.h" 37 #include "OgreGLES2HardwareUniformBuffer.h" 38 #include "OgreHardwareBufferManager.h" 39 #include "OgreGLES2Util.h" 40 #include "OgreRoot.h" 41 42 namespace Ogre 43 { GLSLESProgramPipeline(GLSLESGpuProgram * vertexProgram,GLSLESGpuProgram * fragmentProgram)44 GLSLESProgramPipeline::GLSLESProgramPipeline(GLSLESGpuProgram* vertexProgram, GLSLESGpuProgram* fragmentProgram) : 45 GLSLESProgramCommon(vertexProgram, fragmentProgram) { } 46 ~GLSLESProgramPipeline()47 GLSLESProgramPipeline::~GLSLESProgramPipeline() 48 { 49 #if OGRE_PLATFORM != OGRE_PLATFORM_NACL 50 OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0) 51 OGRE_CHECK_GL_ERROR(glDeleteProgramPipelinesEXT(1, &mGLProgramPipelineHandle)); 52 #endif 53 } 54 compileAndLink()55 void GLSLESProgramPipeline::compileAndLink() 56 { 57 #if OGRE_PLATFORM != OGRE_PLATFORM_NACL 58 GLint linkStatus = 0; 59 60 OGRE_CHECK_GL_ERROR(glGenProgramPipelinesEXT(1, &mGLProgramPipelineHandle)); 61 OGRE_CHECK_GL_ERROR(glBindProgramPipelineEXT(mGLProgramPipelineHandle)); 62 63 // Compile and attach Vertex Program 64 if(mVertexProgram && !mVertexProgram->isLinked()) 65 { 66 try 67 { 68 mVertexProgram->getGLSLProgram()->compile(true); 69 } 70 catch (Exception& e) 71 { 72 LogManager::getSingleton().stream() << e.getDescription(); 73 mTriedToLinkAndFailed = true; 74 return; 75 } 76 GLuint programHandle = mVertexProgram->getGLSLProgram()->getGLProgramHandle(); 77 OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE)); 78 mVertexProgram->getGLSLProgram()->attachToProgramObject(programHandle); 79 OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); 80 OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); 81 82 if(linkStatus) 83 { 84 mVertexProgram->setLinked(linkStatus); 85 mLinked |= VERTEX_PROGRAM_LINKED; 86 } 87 88 mTriedToLinkAndFailed = !linkStatus; 89 90 logObjectInfo( getCombinedName() + String("GLSL vertex program result : "), programHandle ); 91 92 setSkeletalAnimationIncluded(mVertexProgram->isSkeletalAnimationIncluded()); 93 } 94 95 // Compile and attach Fragment Program 96 if(mFragmentProgram && !mFragmentProgram->isLinked()) 97 { 98 try 99 { 100 mFragmentProgram->getGLSLProgram()->compile(true); 101 } 102 catch (Exception& e) 103 { 104 LogManager::getSingleton().stream() << e.getDescription(); 105 mTriedToLinkAndFailed = true; 106 return; 107 } 108 109 GLuint programHandle = mFragmentProgram->getGLSLProgram()->getGLProgramHandle(); 110 OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE)); 111 mFragmentProgram->getGLSLProgram()->attachToProgramObject(programHandle); 112 OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); 113 OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); 114 115 if(linkStatus) 116 { 117 mFragmentProgram->setLinked(linkStatus); 118 mLinked |= FRAGMENT_PROGRAM_LINKED; 119 } 120 121 mTriedToLinkAndFailed = !linkStatus; 122 123 logObjectInfo( getCombinedName() + String("GLSL fragment program result : "), programHandle ); 124 } 125 126 if(mLinked) 127 { 128 if(mVertexProgram && mVertexProgram->isLinked()) 129 { 130 OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT_EXT, mVertexProgram->getGLSLProgram()->getGLProgramHandle())); 131 } 132 if(mFragmentProgram && mFragmentProgram->isLinked()) 133 { 134 OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT_EXT, mFragmentProgram->getGLSLProgram()->getGLProgramHandle())); 135 } 136 137 // Validate pipeline 138 logObjectInfo( getCombinedName() + String("GLSL program pipeline result : "), mGLProgramPipelineHandle ); 139 #if OGRE_PLATFORM != OGRE_PLATFORM_NACL 140 if(mVertexProgram && mFragmentProgram) 141 OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0) 142 glLabelObjectEXT(GL_PROGRAM_PIPELINE_OBJECT_EXT, mGLProgramPipelineHandle, 0, 143 (mVertexProgram->getName() + "/" + mFragmentProgram->getName()).c_str()); 144 #endif 145 } 146 #endif 147 } 148 _useProgram(void)149 void GLSLESProgramPipeline::_useProgram(void) 150 { 151 if (mLinked) 152 { 153 #if OGRE_PLATFORM != OGRE_PLATFORM_NACL 154 OGRE_CHECK_GL_ERROR(glBindProgramPipelineEXT(mGLProgramPipelineHandle)); 155 #endif 156 } 157 } 158 159 //----------------------------------------------------------------------- getAttributeIndex(VertexElementSemantic semantic,uint index)160 GLint GLSLESProgramPipeline::getAttributeIndex(VertexElementSemantic semantic, uint index) 161 { 162 GLint res = mCustomAttributesIndexes[semantic-1][index]; 163 if (res == NULL_CUSTOM_ATTRIBUTES_INDEX) 164 { 165 GLuint handle = mVertexProgram->getGLSLProgram()->getGLProgramHandle(); 166 const char * attString = getAttributeSemanticString(semantic); 167 GLint attrib; 168 OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(handle, attString)); 169 170 // Sadly position is a special case 171 if (attrib == NOT_FOUND_CUSTOM_ATTRIBUTES_INDEX && semantic == VES_POSITION) 172 { 173 OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(handle, "position")); 174 } 175 176 // For uv and other case the index is a part of the name 177 if (attrib == NOT_FOUND_CUSTOM_ATTRIBUTES_INDEX) 178 { 179 String attStringWithSemantic = String(attString) + StringConverter::toString(index); 180 OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(handle, attStringWithSemantic.c_str())); 181 } 182 183 // Update mCustomAttributesIndexes with the index we found (or didn't find) 184 mCustomAttributesIndexes[semantic-1][index] = attrib; 185 res = attrib; 186 } 187 188 return res; 189 } 190 191 //----------------------------------------------------------------------- activate(void)192 void GLSLESProgramPipeline::activate(void) 193 { 194 if (!mLinked && !mTriedToLinkAndFailed) 195 { 196 glGetError(); // Clean up the error. Otherwise will flood log. 197 198 #if !OGRE_NO_GLES2_GLSL_OPTIMISER 199 // Check CmdParams for each shader type to see if we should optimise 200 if(mVertexProgram) 201 { 202 String paramStr = mVertexProgram->getGLSLProgram()->getParameter("use_optimiser"); 203 if((paramStr == "true") || paramStr.empty()) 204 { 205 GLSLESProgramPipelineManager::getSingleton().optimiseShaderSource(mVertexProgram); 206 } 207 } 208 209 if(mFragmentProgram) 210 { 211 String paramStr = mFragmentProgram->getGLSLProgram()->getParameter("use_optimiser"); 212 if((paramStr == "true") || paramStr.empty()) 213 { 214 GLSLESProgramPipelineManager::getSingleton().optimiseShaderSource(mFragmentProgram); 215 } 216 } 217 #endif 218 compileAndLink(); 219 220 extractLayoutQualifiers(); 221 222 buildGLUniformReferences(); 223 } 224 225 _useProgram(); 226 } 227 228 //----------------------------------------------------------------------- buildGLUniformReferences(void)229 void GLSLESProgramPipeline::buildGLUniformReferences(void) 230 { 231 if (!mUniformRefsBuilt) 232 { 233 const GpuConstantDefinitionMap* vertParams = 0; 234 const GpuConstantDefinitionMap* fragParams = 0; 235 if (mVertexProgram) 236 { 237 vertParams = &(mVertexProgram->getGLSLProgram()->getConstantDefinitions().map); 238 GLSLESProgramPipelineManager::getSingleton().extractUniforms(mVertexProgram->getGLSLProgram()->getGLProgramHandle(), 239 vertParams, NULL, mGLUniformReferences, mGLUniformBufferReferences); 240 } 241 if (mFragmentProgram) 242 { 243 fragParams = &(mFragmentProgram->getGLSLProgram()->getConstantDefinitions().map); 244 GLSLESProgramPipelineManager::getSingleton().extractUniforms(mFragmentProgram->getGLSLProgram()->getGLProgramHandle(), 245 NULL, fragParams, mGLUniformReferences, mGLUniformBufferReferences); 246 } 247 248 mUniformRefsBuilt = true; 249 } 250 } 251 252 //----------------------------------------------------------------------- updateUniforms(GpuProgramParametersSharedPtr params,uint16 mask,GpuProgramType fromProgType)253 void GLSLESProgramPipeline::updateUniforms(GpuProgramParametersSharedPtr params, 254 uint16 mask, GpuProgramType fromProgType) 255 { 256 // Iterate through uniform reference list and update uniform values 257 GLUniformReferenceIterator currentUniform = mGLUniformReferences.begin(); 258 GLUniformReferenceIterator endUniform = mGLUniformReferences.end(); 259 #if OGRE_PLATFORM != OGRE_PLATFORM_NACL 260 GLuint progID = 0; 261 if(fromProgType == GPT_VERTEX_PROGRAM) 262 { 263 progID = mVertexProgram->getGLSLProgram()->getGLProgramHandle(); 264 } 265 else if(fromProgType == GPT_FRAGMENT_PROGRAM) 266 { 267 progID = mFragmentProgram->getGLSLProgram()->getGLProgramHandle(); 268 } 269 270 for (;currentUniform != endUniform; ++currentUniform) 271 { 272 // Only pull values from buffer it's supposed to be in (vertex or fragment) 273 // This method will be called twice, once for vertex program params, 274 // and once for fragment program params. 275 if (fromProgType == currentUniform->mSourceProgType) 276 { 277 const GpuConstantDefinition* def = currentUniform->mConstantDef; 278 if (def->variability & mask) 279 { 280 GLsizei glArraySize = (GLsizei)def->arraySize; 281 bool shouldUpdate = true; 282 switch (def->constType) 283 { 284 case GCT_INT1: 285 case GCT_INT2: 286 case GCT_INT3: 287 case GCT_INT4: 288 case GCT_SAMPLER1D: 289 case GCT_SAMPLER1DSHADOW: 290 case GCT_SAMPLER2D: 291 case GCT_SAMPLER2DSHADOW: 292 case GCT_SAMPLER3D: 293 case GCT_SAMPLERCUBE: 294 #if OGRE_NO_GLES3_SUPPORT == 0 295 case GCT_SAMPLER2DARRAY: 296 #endif 297 shouldUpdate = mUniformCache->updateUniform(currentUniform->mLocation, 298 params->getIntPointer(def->physicalIndex), 299 static_cast<GLsizei>(def->elementSize * def->arraySize * sizeof(int))); 300 break; 301 default: 302 shouldUpdate = mUniformCache->updateUniform(currentUniform->mLocation, 303 params->getFloatPointer(def->physicalIndex), 304 static_cast<GLsizei>(def->elementSize * def->arraySize * sizeof(float))); 305 break; 306 } 307 308 if(!shouldUpdate) 309 continue; 310 311 // Get the index in the parameter real list 312 switch (def->constType) 313 { 314 case GCT_FLOAT1: 315 OGRE_CHECK_GL_ERROR(glProgramUniform1fvEXT(progID, currentUniform->mLocation, glArraySize, 316 params->getFloatPointer(def->physicalIndex))); 317 break; 318 case GCT_FLOAT2: 319 OGRE_CHECK_GL_ERROR(glProgramUniform2fvEXT(progID, currentUniform->mLocation, glArraySize, 320 params->getFloatPointer(def->physicalIndex))); 321 break; 322 case GCT_FLOAT3: 323 OGRE_CHECK_GL_ERROR(glProgramUniform3fvEXT(progID, currentUniform->mLocation, glArraySize, 324 params->getFloatPointer(def->physicalIndex))); 325 break; 326 case GCT_FLOAT4: 327 OGRE_CHECK_GL_ERROR(glProgramUniform4fvEXT(progID, currentUniform->mLocation, glArraySize, 328 params->getFloatPointer(def->physicalIndex))); 329 break; 330 case GCT_MATRIX_2X2: 331 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2fvEXT(progID, currentUniform->mLocation, glArraySize, 332 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 333 break; 334 case GCT_MATRIX_3X3: 335 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3fvEXT(progID, currentUniform->mLocation, glArraySize, 336 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 337 break; 338 case GCT_MATRIX_4X4: 339 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4fvEXT(progID, currentUniform->mLocation, glArraySize, 340 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 341 break; 342 case GCT_INT1: 343 OGRE_CHECK_GL_ERROR(glProgramUniform1ivEXT(progID, currentUniform->mLocation, glArraySize, 344 params->getIntPointer(def->physicalIndex))); 345 break; 346 case GCT_INT2: 347 OGRE_CHECK_GL_ERROR(glProgramUniform2ivEXT(progID, currentUniform->mLocation, glArraySize, 348 params->getIntPointer(def->physicalIndex))); 349 break; 350 case GCT_INT3: 351 OGRE_CHECK_GL_ERROR(glProgramUniform3ivEXT(progID, currentUniform->mLocation, glArraySize, 352 params->getIntPointer(def->physicalIndex))); 353 break; 354 case GCT_INT4: 355 OGRE_CHECK_GL_ERROR(glProgramUniform4ivEXT(progID, currentUniform->mLocation, glArraySize, 356 params->getIntPointer(def->physicalIndex))); 357 break; 358 case GCT_SAMPLER1D: 359 case GCT_SAMPLER1DSHADOW: 360 case GCT_SAMPLER2D: 361 case GCT_SAMPLER2DSHADOW: 362 case GCT_SAMPLER3D: 363 case GCT_SAMPLERCUBE: 364 #if OGRE_NO_GLES3_SUPPORT == 0 365 case GCT_SAMPLER2DARRAY: 366 #endif 367 // Samplers handled like 1-element ints 368 OGRE_CHECK_GL_ERROR(glProgramUniform1ivEXT(progID, currentUniform->mLocation, 1, 369 params->getIntPointer(def->physicalIndex))); 370 break; 371 #if OGRE_NO_GLES3_SUPPORT == 0 372 case GCT_MATRIX_2X3: 373 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2x3fvEXT(progID, currentUniform->mLocation, glArraySize, 374 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 375 break; 376 case GCT_MATRIX_2X4: 377 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2x4fvEXT(progID, currentUniform->mLocation, glArraySize, 378 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 379 break; 380 case GCT_MATRIX_3X2: 381 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3x2fvEXT(progID, currentUniform->mLocation, glArraySize, 382 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 383 break; 384 case GCT_MATRIX_3X4: 385 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3x4fvEXT(progID, currentUniform->mLocation, glArraySize, 386 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 387 break; 388 case GCT_MATRIX_4X2: 389 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4x2fvEXT(progID, currentUniform->mLocation, glArraySize, 390 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 391 break; 392 case GCT_MATRIX_4X3: 393 OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4x3fvEXT(progID, currentUniform->mLocation, glArraySize, 394 GL_FALSE, params->getFloatPointer(def->physicalIndex))); 395 break; 396 #else 397 case GCT_MATRIX_2X3: 398 case GCT_MATRIX_2X4: 399 case GCT_MATRIX_3X2: 400 case GCT_MATRIX_3X4: 401 case GCT_MATRIX_4X2: 402 case GCT_MATRIX_4X3: 403 case GCT_SAMPLER2DARRAY: 404 #endif 405 case GCT_UNKNOWN: 406 case GCT_SUBROUTINE: 407 case GCT_DOUBLE1: 408 case GCT_DOUBLE2: 409 case GCT_DOUBLE3: 410 case GCT_DOUBLE4: 411 case GCT_SAMPLERRECT: 412 case GCT_MATRIX_DOUBLE_2X2: 413 case GCT_MATRIX_DOUBLE_2X3: 414 case GCT_MATRIX_DOUBLE_2X4: 415 case GCT_MATRIX_DOUBLE_3X2: 416 case GCT_MATRIX_DOUBLE_3X3: 417 case GCT_MATRIX_DOUBLE_3X4: 418 case GCT_MATRIX_DOUBLE_4X2: 419 case GCT_MATRIX_DOUBLE_4X3: 420 case GCT_MATRIX_DOUBLE_4X4: 421 break; 422 423 } // End switch 424 } // Variability & mask 425 } // fromProgType == currentUniform->mSourceProgType 426 427 } // End for 428 #endif 429 } 430 //----------------------------------------------------------------------- updateUniformBlocks(GpuProgramParametersSharedPtr params,uint16 mask,GpuProgramType fromProgType)431 void GLSLESProgramPipeline::updateUniformBlocks(GpuProgramParametersSharedPtr params, 432 uint16 mask, GpuProgramType fromProgType) 433 { 434 #if OGRE_NO_GLES3_SUPPORT == 0 435 // Iterate through the list of uniform buffers and update them as needed 436 GLUniformBufferIterator currentBuffer = mGLUniformBufferReferences.begin(); 437 GLUniformBufferIterator endBuffer = mGLUniformBufferReferences.end(); 438 439 const GpuProgramParameters::GpuSharedParamUsageList& sharedParams = params->getSharedParameters(); 440 441 GpuProgramParameters::GpuSharedParamUsageList::const_iterator it, end = sharedParams.end(); 442 for (it = sharedParams.begin(); it != end; ++it) 443 { 444 for (;currentBuffer != endBuffer; ++currentBuffer) 445 { 446 GLES2HardwareUniformBuffer* hwGlBuffer = static_cast<GLES2HardwareUniformBuffer*>(currentBuffer->get()); 447 GpuSharedParametersPtr paramsPtr = it->getSharedParams(); 448 449 // Block name is stored in mSharedParams->mName of GpuSharedParamUsageList items 450 GLint UniformTransform; 451 OGRE_CHECK_GL_ERROR(UniformTransform = glGetUniformBlockIndex(mGLProgramHandle, it->getName().c_str())); 452 OGRE_CHECK_GL_ERROR(glUniformBlockBinding(mGLProgramHandle, UniformTransform, hwGlBuffer->getGLBufferBinding())); 453 454 hwGlBuffer->writeData(0, hwGlBuffer->getSizeInBytes(), ¶msPtr->getFloatConstantList().front()); 455 } 456 } 457 #endif 458 } 459 //----------------------------------------------------------------------- updatePassIterationUniforms(GpuProgramParametersSharedPtr params)460 void GLSLESProgramPipeline::updatePassIterationUniforms(GpuProgramParametersSharedPtr params) 461 { 462 if (params->hasPassIterationNumber()) 463 { 464 size_t index = params->getPassIterationNumberIndex(); 465 466 GLUniformReferenceIterator currentUniform = mGLUniformReferences.begin(); 467 GLUniformReferenceIterator endUniform = mGLUniformReferences.end(); 468 469 // Need to find the uniform that matches the multi pass entry 470 for (;currentUniform != endUniform; ++currentUniform) 471 { 472 // Get the index in the parameter real list 473 if (index == currentUniform->mConstantDef->physicalIndex) 474 { 475 #if OGRE_PLATFORM != OGRE_PLATFORM_NACL 476 477 GLuint progID = 0; 478 if (mVertexProgram && currentUniform->mSourceProgType == GPT_VERTEX_PROGRAM) 479 { 480 if(!mUniformCache->updateUniform(currentUniform->mLocation, 481 params->getFloatPointer(index), 482 static_cast<GLsizei>(currentUniform->mConstantDef->elementSize * 483 currentUniform->mConstantDef->arraySize * 484 sizeof(float)))) 485 return; 486 487 progID = mVertexProgram->getGLSLProgram()->getGLProgramHandle(); 488 OGRE_CHECK_GL_ERROR(glProgramUniform1fvEXT(progID, currentUniform->mLocation, 1, params->getFloatPointer(index))); 489 } 490 491 if (mFragmentProgram && currentUniform->mSourceProgType == GPT_FRAGMENT_PROGRAM) 492 { 493 if(!mUniformCache->updateUniform(currentUniform->mLocation, 494 params->getFloatPointer(index), 495 static_cast<GLsizei>(currentUniform->mConstantDef->elementSize * 496 currentUniform->mConstantDef->arraySize * 497 sizeof(float)))) 498 return; 499 progID = mFragmentProgram->getGLSLProgram()->getGLProgramHandle(); 500 OGRE_CHECK_GL_ERROR(glProgramUniform1fvEXT(progID, currentUniform->mLocation, 1, params->getFloatPointer(index))); 501 } 502 #endif 503 // There will only be one multipass entry 504 return; 505 } 506 } 507 } 508 } 509 //----------------------------------------------------------------------- extractLayoutQualifiers(void)510 void GLSLESProgramPipeline::extractLayoutQualifiers(void) 511 { 512 // Format is: 513 // layout(location = 0) attribute vec4 vertex; 514 515 if(mVertexProgram) 516 { 517 String shaderSource = mVertexProgram->getGLSLProgram()->getSource(); 518 String::size_type currPos = shaderSource.find("layout"); 519 while (currPos != String::npos) 520 { 521 VertexElementSemantic semantic; 522 GLint index = 0; 523 524 String::size_type endPos = shaderSource.find(";", currPos); 525 if (endPos == String::npos) 526 { 527 // Problem, missing semicolon, abort 528 break; 529 } 530 531 String line = shaderSource.substr(currPos, endPos - currPos); 532 533 // Skip over 'layout' 534 currPos += 6; 535 536 // Skip until '=' 537 String::size_type eqPos = line.find("="); 538 String::size_type parenPos = line.find(")"); 539 540 // Skip past '=' up to a ')' which contains an integer(the position). This could be a definition, does the preprocessor do replacement? 541 String attrLocation = line.substr(eqPos + 1, parenPos - eqPos - 1); 542 StringUtil::trim(attrLocation); 543 GLint attrib = StringConverter::parseInt(attrLocation); 544 545 // The rest of the line is a standard attribute definition. 546 // Erase up to it then split the remainder by spaces. 547 line.erase (0, parenPos + 1); 548 StringUtil::trim(line); 549 StringVector parts = StringUtil::split(line, " "); 550 551 if(parts.size() < 3) 552 { 553 // This is a malformed attribute 554 // It should contain 3 parts, i.e. "attribute vec4 vertex" 555 break; 556 } 557 558 String attrName = parts[2]; 559 560 // Special case for attribute named position 561 if(attrName == "position") 562 semantic = getAttributeSemanticEnum("vertex"); 563 else 564 semantic = getAttributeSemanticEnum(attrName); 565 566 // Find the texture unit index 567 String::size_type uvPos = attrName.find("uv"); 568 if(uvPos != String::npos) 569 { 570 String uvIndex = attrName.substr(uvPos + 2, attrName.length() - 2); 571 index = StringConverter::parseInt(uvIndex); 572 } 573 574 mCustomAttributesIndexes[semantic-1][index] = attrib; 575 576 currPos = shaderSource.find("layout", currPos); 577 } 578 } 579 } 580 } 581