//----------------------------------------------------------------------- GLSLLinkProgram::GLSLLinkProgram(GLSLGpuProgram* vertexProgram, GLSLGpuProgram* geometryProgram, GLSLGpuProgram* fragmentProgram) : mVertexProgram(vertexProgram) , mGeometryProgram(geometryProgram) , mFragmentProgram(fragmentProgram) , mUniformRefsBuilt(false) , mLinked(false) { //checkForGLSLError( "GLSLLinkProgram::GLSLLinkProgram", "Error prior to Creating GLSL Program Object", 0); glGetError(); //Clean up the error. Otherwise will flood log. mGLHandle = glCreateProgramObjectARB(); checkForGLSLError( "GLSLLinkProgram::GLSLLinkProgram", "Error Creating GLSL Program Object", 0 ); // tell shaders to attach themselves to the LinkProgram // let the shaders do the attaching since they may have several children to attach if (mVertexProgram) { mVertexProgram->getGLSLProgram()->attachToProgramObject(mGLHandle); setSkeletalAnimationIncluded(mVertexProgram->isSkeletalAnimationIncluded()); } if (mGeometryProgram) { mGeometryProgram->getGLSLProgram()->attachToProgramObject(mGLHandle); //Don't set adjacency flag. We handle it internally and expose "false" } if (mFragmentProgram) { mFragmentProgram->getGLSLProgram()->attachToProgramObject(mGLHandle); } }
void GLSLProgramPipeline::compileIndividualProgram(GLSLGpuProgram *program) { GLint linkStatus = 0; // Compile and attach program if(program && !program->isLinked()) { try { program->getGLSLProgram()->compile(true); } catch (Exception& e) { LogManager::getSingleton().stream() << e.getDescription(); mTriedToLinkAndFailed = true; return; } GLuint programHandle = program->getGLSLProgram()->getGLProgramHandle(); OGRE_CHECK_GL_ERROR(glProgramParameteri(programHandle, GL_PROGRAM_SEPARABLE, GL_TRUE)); program->getGLSLProgram()->attachToProgramObject(programHandle); OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); program->setLinked(linkStatus); mLinked = linkStatus; mTriedToLinkAndFailed = !linkStatus; logObjectInfo( getCombinedName() + String("GLSL program result : "), programHandle ); if(program->getType() == GPT_VERTEX_PROGRAM) setSkeletalAnimationIncluded(program->isSkeletalAnimationIncluded()); } }
void GLSLESProgramPipeline::compileAndLink() { #if OGRE_PLATFORM != OGRE_PLATFORM_NACL GLint linkStatus = 0; OGRE_CHECK_GL_ERROR(glGenProgramPipelinesEXT(1, &mGLProgramPipelineHandle)); OGRE_CHECK_GL_ERROR(glBindProgramPipelineEXT(mGLProgramPipelineHandle)); // Compile and attach Vertex Program if(getVertexProgram()) { if(getVertexProgram()->isLinked()) { mLinked |= VERTEX_PROGRAM_LINKED; } else if(getMicrocodeFromCache( getVertexProgram()->getName(), getVertexProgram()->createGLProgramHandle())) { getVertexProgram()->setLinked(true); mLinked |= VERTEX_PROGRAM_LINKED; mTriedToLinkAndFailed = false; } else { if(!getVertexProgram()->compile(true)) { LogManager::getSingleton().stream(LML_CRITICAL) << "Vertex Program " << getVertexProgram()->getName() << " failed to compile. See compile log above for details."; mTriedToLinkAndFailed = true; return; } GLuint programHandle = getVertexProgram()->getGLProgramHandle(); bindFixedAttributes( programHandle ); OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE)); getVertexProgram()->attachToProgramObject(programHandle); OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); if(linkStatus) { getVertexProgram()->setLinked(linkStatus); mLinked |= VERTEX_PROGRAM_LINKED; } mTriedToLinkAndFailed = !linkStatus; GLSLES::logObjectInfo( getCombinedName() + String("GLSL vertex program result : "), programHandle ); setSkeletalAnimationIncluded(getVertexProgram()->isSkeletalAnimationIncluded()); } } // Compile and attach Fragment Program if(mFragmentProgram) { if(mFragmentProgram->isLinked()) { mLinked |= FRAGMENT_PROGRAM_LINKED; } else if(getMicrocodeFromCache( mFragmentProgram->getName(), mFragmentProgram->createGLProgramHandle())) { mFragmentProgram->setLinked(true); mLinked |= FRAGMENT_PROGRAM_LINKED; mTriedToLinkAndFailed = false; } else { if(!mFragmentProgram->compile(true)) { LogManager::getSingleton().stream(LML_CRITICAL) << "Fragment Program " << mFragmentProgram->getName() << " failed to compile. See compile log above for details."; mTriedToLinkAndFailed = true; return; } GLuint programHandle = mFragmentProgram->getGLProgramHandle(); OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE)); mFragmentProgram->attachToProgramObject(programHandle); OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); if(linkStatus) { mFragmentProgram->setLinked(linkStatus); mLinked |= FRAGMENT_PROGRAM_LINKED; } mTriedToLinkAndFailed = !linkStatus; GLSLES::logObjectInfo( getCombinedName() + String("GLSL fragment program result : "), programHandle ); } } if(mLinked) { if(getVertexProgram() && getVertexProgram()->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT_EXT, getVertexProgram()->getGLProgramHandle())); _writeToCache(getVertexProgram()->getName(), getVertexProgram()->getGLProgramHandle()); } if(mFragmentProgram && mFragmentProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT_EXT, mFragmentProgram->getGLProgramHandle())); _writeToCache(mFragmentProgram->getName(), mFragmentProgram->getGLProgramHandle()); } // Validate pipeline GLSLES::logObjectInfo( getCombinedName() + String("GLSL program pipeline result : "), mGLProgramPipelineHandle ); if(getVertexProgram() && mFragmentProgram && Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_DEBUG)) { glLabelObjectEXT(GL_PROGRAM_PIPELINE_OBJECT_EXT, mGLProgramPipelineHandle, 0, (getVertexProgram()->getName() + "/" + mFragmentProgram->getName()).c_str()); } } #endif }
void GLSLSeparableProgram::loadIndividualProgram(GLSLShader *program) { if (program && !program->isLinked()) { GLint linkStatus = 0; String programName = program->getName(); GLuint programHandle = program->getGLProgramHandle(); OGRE_CHECK_GL_ERROR(glProgramParameteri(programHandle, GL_PROGRAM_SEPARABLE, GL_TRUE)); //if (GpuProgramManager::getSingleton().getSaveMicrocodesToCache()) OGRE_CHECK_GL_ERROR(glProgramParameteri(programHandle, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE)); // Use precompiled program if possible. bool microcodeAvailableInCache = GpuProgramManager::getSingleton().isMicrocodeAvailableInCache(programName); if (microcodeAvailableInCache) { GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(programName); cacheMicrocode->seek(0); GLenum binaryFormat = 0; cacheMicrocode->read(&binaryFormat, sizeof(GLenum)); GLint binaryLength = cacheMicrocode->size() - sizeof(GLenum); OGRE_CHECK_GL_ERROR(glProgramBinary(programHandle, binaryFormat, cacheMicrocode->getPtr() + sizeof(GLenum), binaryLength)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); if (!linkStatus) logObjectInfo("Could not use cached binary " + programName, programHandle); } // Compilation needed if precompiled program is // unavailable or failed to link. if (!linkStatus) { try { program->compile(true); } catch (Exception& e) { LogManager::getSingleton().stream() << e.getDescription(); mTriedToLinkAndFailed = true; return; } program->attachToProgramObject(programHandle); OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); // Binary cache needs an update. microcodeAvailableInCache = false; } program->setLinked(linkStatus); mLinked = linkStatus; mTriedToLinkAndFailed = !linkStatus; logObjectInfo( getCombinedName() + String("GLSL program result : "), programHandle ); if (program->getType() == GPT_VERTEX_PROGRAM) setSkeletalAnimationIncluded(program->isSkeletalAnimationIncluded()); // Add the microcode to the cache. if (!microcodeAvailableInCache && mLinked && GpuProgramManager::getSingleton().getSaveMicrocodesToCache() ) { // Get buffer size. GLint binaryLength = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); // Create microcode. GpuProgramManager::Microcode newMicrocode = GpuProgramManager::getSingleton().createMicrocode((unsigned long)binaryLength + sizeof(GLenum)); // Get binary. OGRE_CHECK_GL_ERROR(glGetProgramBinary(programHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(), newMicrocode->getPtr() + sizeof(GLenum))); // std::vector<uchar> buffer(binaryLength); // GLenum format(0); // OGRE_CHECK_GL_ERROR(glGetProgramBinary(programHandle, binaryLength, NULL, &format, &buffer[0])); // GLenum binaryFormat = 0; // std::vector<uchar> binaryData(binaryLength); // newMicrocode->read(&binaryFormat, sizeof(GLenum)); // newMicrocode->read(&binaryData[0], binaryLength); GpuProgramManager::getSingleton().addMicrocodeToCache(programName, newMicrocode); } } }
void GLSLESProgramPipeline::compileAndLink() { #if GL_EXT_separate_shader_objects GLint linkStatus = 0; glGenProgramPipelinesEXT(1, &mGLProgramPipelineHandle); GL_CHECK_ERROR glBindProgramPipelineEXT(mGLProgramPipelineHandle); GL_CHECK_ERROR // Compile and attach Vertex Program if(mVertexProgram && !mVertexProgram->isLinked()) { if (!mVertexProgram->getGLSLProgram()->compile(true)) { mTriedToLinkAndFailed = true; return; } GLuint programHandle = mVertexProgram->getGLSLProgram()->getGLProgramHandle(); glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE); GL_CHECK_ERROR mVertexProgram->getGLSLProgram()->attachToProgramObject(programHandle); glLinkProgram(programHandle); GL_CHECK_ERROR glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus); GL_CHECK_ERROR if(linkStatus) { mVertexProgram->setLinked(linkStatus); mLinked |= VERTEX_PROGRAM_LINKED; } GL_CHECK_ERROR // TODO: Just fail out here if the program doesn't link? mTriedToLinkAndFailed = !linkStatus; logObjectInfo( getCombinedName() + String("GLSL vertex program result : "), programHandle ); setSkeletalAnimationIncluded(mVertexProgram->isSkeletalAnimationIncluded()); } // Compile and attach Fragment Program if(mFragmentProgram && !mFragmentProgram->isLinked()) { if (!mFragmentProgram->getGLSLProgram()->compile(true)) { mTriedToLinkAndFailed = true; return; } GLuint programHandle = mFragmentProgram->getGLSLProgram()->getGLProgramHandle(); glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE); GL_CHECK_ERROR mFragmentProgram->getGLSLProgram()->attachToProgramObject(programHandle); glLinkProgram(programHandle); GL_CHECK_ERROR glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus); GL_CHECK_ERROR if(linkStatus) { mFragmentProgram->setLinked(linkStatus); mLinked |= FRAGMENT_PROGRAM_LINKED; } mTriedToLinkAndFailed = !linkStatus; logObjectInfo( getCombinedName() + String("GLSL fragment program result : "), programHandle ); } if(mLinked) { if ( GpuProgramManager::getSingleton().getSaveMicrocodesToCache() ) { // Add to the microcode to the cache String name; name = getCombinedName(); // Get buffer size GLint binaryLength = 0; #if GL_OES_get_program_binary glGetProgramiv(mGLHandle, GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength); GL_CHECK_ERROR; #endif // Create microcode GpuProgramManager::Microcode newMicrocode = GpuProgramManager::getSingleton().createMicrocode((unsigned long)binaryLength + sizeof(GLenum)); #if GL_OES_get_program_binary // Get binary glGetProgramBinaryOES(mGLHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(), newMicrocode->getPtr() + sizeof(GLenum)); GL_CHECK_ERROR; #endif // Add to the microcode to the cache GpuProgramManager::getSingleton().addMicrocodeToCache(name, newMicrocode); } if(mVertexProgram && mVertexProgram->isLinked()) { glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT_EXT, mVertexProgram->getGLSLProgram()->getGLProgramHandle()); GL_CHECK_ERROR } if(mFragmentProgram && mFragmentProgram->isLinked()) { glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT_EXT, mFragmentProgram->getGLSLProgram()->getGLProgramHandle()); GL_CHECK_ERROR }
void GLSLESProgramPipeline::compileAndLink() { #if GL_EXT_separate_shader_objects && OGRE_PLATFORM != OGRE_PLATFORM_NACL GLint linkStatus = 0; OGRE_CHECK_GL_ERROR(glGenProgramPipelinesEXT(1, &mGLProgramPipelineHandle)); OGRE_CHECK_GL_ERROR(glBindProgramPipelineEXT(mGLProgramPipelineHandle)); // Compile and attach Vertex Program if(mVertexProgram && !mVertexProgram->isLinked()) { try { mVertexProgram->getGLSLProgram()->compile(true); } catch (Exception& e) { LogManager::getSingleton().stream() << e.getDescription(); mTriedToLinkAndFailed = true; return; } GLuint programHandle = mVertexProgram->getGLSLProgram()->getGLProgramHandle(); OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE)); mVertexProgram->getGLSLProgram()->attachToProgramObject(programHandle); OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); if(linkStatus) { mVertexProgram->setLinked(linkStatus); mLinked |= VERTEX_PROGRAM_LINKED; } mTriedToLinkAndFailed = !linkStatus; logObjectInfo( getCombinedName() + String("GLSL vertex program result : "), programHandle ); setSkeletalAnimationIncluded(mVertexProgram->isSkeletalAnimationIncluded()); } // Compile and attach Fragment Program if(mFragmentProgram && !mFragmentProgram->isLinked()) { try { mFragmentProgram->getGLSLProgram()->compile(true); } catch (Exception& e) { LogManager::getSingleton().stream() << e.getDescription(); mTriedToLinkAndFailed = true; return; } GLuint programHandle = mFragmentProgram->getGLSLProgram()->getGLProgramHandle(); OGRE_CHECK_GL_ERROR(glProgramParameteriEXT(programHandle, GL_PROGRAM_SEPARABLE_EXT, GL_TRUE)); mFragmentProgram->getGLSLProgram()->attachToProgramObject(programHandle); OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle)); OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus)); if(linkStatus) { mFragmentProgram->setLinked(linkStatus); mLinked |= FRAGMENT_PROGRAM_LINKED; } mTriedToLinkAndFailed = !linkStatus; logObjectInfo( getCombinedName() + String("GLSL fragment program result : "), programHandle ); } if(mLinked) { if(mVertexProgram && mVertexProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT_EXT, mVertexProgram->getGLSLProgram()->getGLProgramHandle())); } if(mFragmentProgram && mFragmentProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStagesEXT(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT_EXT, mFragmentProgram->getGLSLProgram()->getGLProgramHandle())); } // Validate pipeline logObjectInfo( getCombinedName() + String("GLSL program pipeline result : "), mGLProgramPipelineHandle ); #if GL_EXT_debug_label && OGRE_PLATFORM != OGRE_PLATFORM_NACL if(mVertexProgram && mFragmentProgram) OGRE_IF_IOS_VERSION_IS_GREATER_THAN(5.0) glLabelObjectEXT(GL_PROGRAM_PIPELINE_OBJECT_EXT, mGLProgramPipelineHandle, 0, (mVertexProgram->getName() + "/" + mFragmentProgram->getName()).c_str()); #endif } #endif }
//----------------------------------------------------------------------- void GLSLLinkProgram::compileAndLink() { mVertexArrayObject = new GL3PlusVertexArrayObject(); mVertexArrayObject->bind(); // Compile and attach Vertex Program if (mVertexProgram) { if (!mVertexProgram->getGLSLProgram()->compile(true)) { mTriedToLinkAndFailed = true; return; } mVertexProgram->getGLSLProgram()->attachToProgramObject(mGLProgramHandle); setSkeletalAnimationIncluded(mVertexProgram->isSkeletalAnimationIncluded()); } // Compile and attach Fragment Program if (mFragmentProgram) { if (!mFragmentProgram->getGLSLProgram()->compile(true)) { mTriedToLinkAndFailed = true; return; } mFragmentProgram->getGLSLProgram()->attachToProgramObject(mGLProgramHandle); } // Compile and attach Geometry Program if (mGeometryProgram) { if (!mGeometryProgram->getGLSLProgram()->compile(true)) { return; } mGeometryProgram->getGLSLProgram()->attachToProgramObject(mGLProgramHandle); } // Compile and attach Tessellation Control Program if (mHullProgram) { if (!mHullProgram->getGLSLProgram()->compile(true)) { return; } mHullProgram->getGLSLProgram()->attachToProgramObject(mGLProgramHandle); } // Compile and attach Tessellation Evaluation Program if (mDomainProgram) { if (!mDomainProgram->getGLSLProgram()->compile(true)) { return; } mDomainProgram->getGLSLProgram()->attachToProgramObject(mGLProgramHandle); } // Compile and attach Compute Program if (mComputeProgram) { if (!mComputeProgram->getGLSLProgram()->compile(true)) { return; } mComputeProgram->getGLSLProgram()->attachToProgramObject(mGLProgramHandle); } // the link OGRE_CHECK_GL_ERROR(glLinkProgram( mGLProgramHandle )); OGRE_CHECK_GL_ERROR(glGetProgramiv( mGLProgramHandle, GL_LINK_STATUS, &mLinked )); mTriedToLinkAndFailed = !mLinked; logObjectInfo( getCombinedName() + String(" GLSL link result : "), mGLProgramHandle ); if(glIsProgram(mGLProgramHandle)) { OGRE_CHECK_GL_ERROR(glValidateProgram(mGLProgramHandle)); } logObjectInfo( getCombinedName() + String(" GLSL validation result : "), mGLProgramHandle ); if(mLinked) { if ( GpuProgramManager::getSingleton().getSaveMicrocodesToCache() ) { // add to the microcode to the cache String name; name = getCombinedName(); // get buffer size GLint binaryLength = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(mGLProgramHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); // create microcode GpuProgramManager::Microcode newMicrocode = GpuProgramManager::getSingleton().createMicrocode(binaryLength + sizeof(GLenum)); // get binary OGRE_CHECK_GL_ERROR(glGetProgramBinary(mGLProgramHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(), newMicrocode->getPtr() + sizeof(GLenum))); // add to the microcode to the cache GpuProgramManager::getSingleton().addMicrocodeToCache(name, newMicrocode); } } }