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 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 CgProgram::addMicrocodeToCache() { String name = String("CG_") + mName; size_t programStringSize = mProgramString.size(); uint32 sizeOfMicrocode = static_cast<uint32>( sizeof(size_t) + // size of mProgramString programStringSize + // microcode - mProgramString sizeof(size_t) + // size of param map mParametersMapSizeAsBuffer); // create microcode GpuProgramManager::Microcode newMicrocode = GpuProgramManager::getSingleton().createMicrocode(sizeOfMicrocode); newMicrocode->seek(0); // save size of string newMicrocode->write(&programStringSize, sizeof(size_t)); // save microcode newMicrocode->write(&mProgramString[0], programStringSize); // save size of param map size_t parametersMapSize = mParametersMap.size(); newMicrocode->write(¶metersMapSize, sizeof(size_t)); // save params GpuConstantDefinitionMap::const_iterator iter = mParametersMap.begin(); GpuConstantDefinitionMap::const_iterator iterE = mParametersMap.end(); for (; iter != iterE ; iter++) { const String & paramName = iter->first; const GpuConstantDefinition & def = iter->second; // save string size size_t stringSize = paramName.size(); newMicrocode->write(&stringSize, sizeof(size_t)); // save string newMicrocode->write(¶mName[0], stringSize); // save def newMicrocode->write(&def, sizeof(GpuConstantDefinition)); } if (mDelegate) { // save additional info required for delegating size_t samplerMapSize = mSamplerRegisterMap.size(); newMicrocode->write(&samplerMapSize, sizeof(size_t)); // save sampler register mapping map<String,int>::type::const_iterator sampRegister = mSamplerRegisterMap.begin(); map<String,int>::type::const_iterator sampRegisterE = mSamplerRegisterMap.end(); for (; sampRegister != sampRegisterE; ++sampRegister) { const String& paramName = sampRegister->first; int reg = sampRegister->second; size_t stringSize = paramName.size(); newMicrocode->write(&stringSize, sizeof(size_t)); newMicrocode->write(paramName.data(), stringSize); newMicrocode->write(®, sizeof(int)); } // save input/output operations type newMicrocode->write(&mInputOp, sizeof(CGenum)); newMicrocode->write(&mOutputOp, sizeof(CGenum)); } // add to the microcode to the cache GpuProgramManager::getSingleton().addMicrocodeToCache(name, newMicrocode); }
//----------------------------------------------------------------------- void CgProgram::getMicrocodeFromCache(void) { GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(String("CG_") + mName); cacheMicrocode->seek(0); // get size of string size_t programStringSize = 0; cacheMicrocode->read(&programStringSize, sizeof(size_t)); // get microcode mProgramString.resize(programStringSize); cacheMicrocode->read(&mProgramString[0], programStringSize); // get size of param map size_t parametersMapSize = 0; cacheMicrocode->read(¶metersMapSize, sizeof(size_t)); // get params for(size_t i = 0 ; i < parametersMapSize ; i++) { String paramName; size_t stringSize = 0; GpuConstantDefinition def; // get string size cacheMicrocode->read(&stringSize, sizeof(size_t)); // get string paramName.resize(stringSize); cacheMicrocode->read(¶mName[0], stringSize); // get def cacheMicrocode->read( &def, sizeof(GpuConstantDefinition)); mParametersMap.insert(GpuConstantDefinitionMap::value_type(paramName, def)); } if (mDelegate) { // get sampler register mapping size_t samplerMapSize = 0; cacheMicrocode->read(&samplerMapSize, sizeof(size_t)); for (size_t i = 0; i < samplerMapSize; ++i) { String paramName; size_t stringSize = 0; int reg = -1; cacheMicrocode->read(&stringSize, sizeof(size_t)); paramName.resize(stringSize); cacheMicrocode->read(¶mName[0], stringSize); cacheMicrocode->read(®, sizeof(int)); } // get input/output operations type cacheMicrocode->read(&mInputOp, sizeof(CGenum)); cacheMicrocode->read(&mOutputOp, sizeof(CGenum)); } }
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 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()); } }