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