//----------------------------------------------------------------------- void GLSLESLinkProgram::activate(void) { if (!mLinked && !mTriedToLinkAndFailed) { glGetError(); // Clean up the error. Otherwise will flood log. mGLHandle = glCreateProgram(); GL_CHECK_ERROR if ( GpuProgramManager::getSingleton().canGetCompiledShaderBuffer() && GpuProgramManager::getSingleton().isMicrocodeAvailableInCache(getCombinedName()) ) { getMicrocodeFromCache(); } else { #ifdef OGRE_USE_GLES2_GLSL_OPTIMISER // check CmdParams for each shader type to see if we should optimize String paramStr = mVertexProgram->getGLSLProgram()->getParameter("use_optimiser"); if((paramStr == "true") || paramStr.empty()) { GLSLESLinkProgramManager::getSingleton().optimiseShaderSource(mVertexProgram); } paramStr = mFragmentProgram->getGLSLProgram()->getParameter("use_optimiser"); if((paramStr == "true") || paramStr.empty()) { GLSLESLinkProgramManager::getSingleton().optimiseShaderSource(mFragmentProgram); } #endif compileAndLink(); } buildGLUniformReferences(); }
void GLSLProgram::getMicrocodeFromCache(uint32 id) { GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(id); cacheMicrocode->seek(0); // Turns out we need this param when loading. GLenum binaryFormat = 0; cacheMicrocode->read(&binaryFormat, sizeof(GLenum)); // Get size of binary. GLint binaryLength = static_cast<GLint>(cacheMicrocode->size() - sizeof(GLenum)); // Load binary. OGRE_CHECK_GL_ERROR(glProgramBinary(mGLProgramHandle, binaryFormat, cacheMicrocode->getCurrentPtr(), binaryLength)); GLint success = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(mGLProgramHandle, GL_LINK_STATUS, &success)); if(success) { mLinked = true; return; } logObjectInfo("could not load from cache "+getCombinedName(), mGLProgramHandle); // Something must have changed since the program binaries // were cached away. Fallback to source shader loading path, // and then retrieve and cache new program binaries once again. compileAndLink(); }
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 GLSLESProgramCommon::getMicrocodeFromCache(void) { GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(getCombinedName()); // add to the microcode to the cache String name; name = getCombinedName(); // turns out we need this param when loading GLenum binaryFormat = 0; cacheMicrocode->seek(0); // get size of binary cacheMicrocode->read(&binaryFormat, sizeof(GLenum)); if(getGLES2SupportRef()->checkExtension("GL_OES_get_program_binary") || gleswIsSupported(3, 0)) { GLint binaryLength = static_cast<GLint>(cacheMicrocode->size() - sizeof(GLenum)); // load binary OGRE_CHECK_GL_ERROR(glProgramBinaryOES(mGLProgramHandle, binaryFormat, cacheMicrocode->getPtr(), binaryLength)); } GLint success = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv(mGLProgramHandle, GL_LINK_STATUS, &success)); if (!success) { // // Something must have changed since the program binaries // were cached away. Fallback to source shader loading path, // and then retrieve and cache new program binaries once again. // compileAndLink(); } }
//----------------------------------------------------------------------- void GLSLProgramPipeline::activate(void) { if (!mLinked && !mTriedToLinkAndFailed) { if ( GpuProgramManager::getSingleton().canGetCompiledShaderBuffer() && GpuProgramManager::getSingleton().isMicrocodeAvailableInCache(getCombinedName()) ) { getMicrocodeFromCache(); } else { compileAndLink(); } extractLayoutQualifiers(); buildGLUniformReferences(); } _useProgram(); }
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::compileAndLink() { // Ensure no monolithic programs are in use. OGRE_CHECK_GL_ERROR(glUseProgram(0)); OGRE_CHECK_GL_ERROR(glGenProgramPipelines(1, &mGLProgramPipelineHandle)); //OGRE_CHECK_GL_ERROR(glBindProgramPipeline(mGLProgramPipelineHandle)); mVertexArrayObject->bind(); loadIndividualProgram(mVertexShader); loadIndividualProgram(mDomainShader); loadIndividualProgram(mHullShader); loadIndividualProgram(mGeometryShader); loadIndividualProgram(mFragmentShader); loadIndividualProgram(mComputeShader); 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(mGLProgramPipelineHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); // OGRE_CHECK_GL_ERROR(glGetProgramiv(, 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(, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(), newMicrocode->getPtr() + sizeof(GLenum))); // // Add to the microcode to the cache // GpuProgramManager::getSingleton().addMicrocodeToCache(name, newMicrocode); // } if (mVertexShader && mVertexShader->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT, mVertexShader->getGLProgramHandle())); } if (mDomainShader && mDomainShader->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_TESS_EVALUATION_SHADER_BIT, mDomainShader->getGLProgramHandle())); } if (mHullShader && mHullShader->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_TESS_CONTROL_SHADER_BIT, mHullShader->getGLProgramHandle())); } if (mGeometryShader && mGeometryShader->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_GEOMETRY_SHADER_BIT, mGeometryShader->getGLProgramHandle())); } if (mFragmentShader && mFragmentShader->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT, mFragmentShader->getGLProgramHandle())); } if (mComputeShader && mComputeShader->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_COMPUTE_SHADER_BIT, mComputeShader->getGLProgramHandle())); } // Validate pipeline OGRE_CHECK_GL_ERROR(glValidateProgramPipeline(mGLProgramPipelineHandle)); logObjectInfo( getCombinedName() + String("GLSL program pipeline validation result: "), mGLProgramPipelineHandle ); // if (getGLSupport()->checkExtension("GL_KHR_debug") || gl3wIsSupported(4, 3)) // glObjectLabel(GL_PROGRAM_PIPELINE, mGLProgramPipelineHandle, 0, // (mVertexShader->getName() + "/" + mFragmentShader->getName()).c_str()); } }
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 }
// 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 } // Validate pipeline logObjectInfo( getCombinedName() + String("GLSL program pipeline result : "), mGLProgramPipelineHandle ); #if GL_EXT_debug_label glLabelObjectEXT(GL_PROGRAM_PIPELINE_OBJECT_EXT, mGLProgramPipelineHandle, 0, (mVertexProgram->getName() + "/" + mFragmentProgram->getName()).c_str()); #endif } #endif } void GLSLESProgramPipeline::_useProgram(void) { if (mLinked) { #if GL_EXT_separate_shader_objects GL_CHECK_ERROR glBindProgramPipelineEXT(mGLProgramPipelineHandle);
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); } } }
void GLSLProgramPipeline::compileAndLink() { OGRE_CHECK_GL_ERROR(glGenProgramPipelines(1, &mGLProgramPipelineHandle)); OGRE_CHECK_GL_ERROR(glBindProgramPipeline(mGLProgramPipelineHandle)); mVertexArrayObject = new GL3PlusVertexArrayObject(); mVertexArrayObject->bind(); compileIndividualProgram(mVertexProgram); compileIndividualProgram(mFragmentProgram); compileIndividualProgram(mGeometryProgram); compileIndividualProgram(mDomainProgram); compileIndividualProgram(mHullProgram); compileIndividualProgram(mComputeProgram); 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(mGLProgramPipelineHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength)); // Create microcode GpuProgramManager::Microcode newMicrocode = GpuProgramManager::getSingleton().createMicrocode(binaryLength + sizeof(GLenum)); // Get binary OGRE_CHECK_GL_ERROR(glGetProgramBinary(mGLProgramPipelineHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(), newMicrocode->getPtr() + sizeof(GLenum))); // Add to the microcode to the cache GpuProgramManager::getSingleton().addMicrocodeToCache(name, newMicrocode); } if(mVertexProgram && mVertexProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT, mVertexProgram->getGLSLProgram()->getGLProgramHandle())); } if(mFragmentProgram && mFragmentProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT, mFragmentProgram->getGLSLProgram()->getGLProgramHandle())); } if(mGeometryProgram && mGeometryProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_GEOMETRY_SHADER_BIT, mGeometryProgram->getGLSLProgram()->getGLProgramHandle())); } if(mDomainProgram && mDomainProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_TESS_EVALUATION_SHADER_BIT, mDomainProgram->getGLSLProgram()->getGLProgramHandle())); } if(mHullProgram && mHullProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_TESS_CONTROL_SHADER_BIT, mHullProgram->getGLSLProgram()->getGLProgramHandle())); } if(mComputeProgram && mComputeProgram->isLinked()) { OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_COMPUTE_SHADER_BIT, mComputeProgram->getGLSLProgram()->getGLProgramHandle())); } // Validate pipeline logObjectInfo( getCombinedName() + String("GLSL program pipeline result : "), mGLProgramPipelineHandle ); // if(getGLSupport()->checkExtension("GL_KHR_debug") || gl3wIsSupported(4, 3)) // glObjectLabel(GL_PROGRAM_PIPELINE, mGLProgramPipelineHandle, 0, // (mVertexProgram->getName() + "/" + mFragmentProgram->getName()).c_str()); } }