//----------------------------------------------------------------------- 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 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 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 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 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()); } }