void Application::mainLoop() { DesiredFpsListener desiredFpsListener; Eris::EventService& eventService = mSession->getEventService(); Input& input(Input::getSingleton()); do { try { Log::sCurrentFrameStartMilliseconds = microsec_clock::local_time(); unsigned int frameActionMask = 0; TimeFrame timeFrame = TimeFrame(boost::posix_time::microseconds(desiredFpsListener.getMicrosecondsPerFrame())); bool updatedRendering = mOgreView->renderOneFrame(timeFrame); if (updatedRendering) { frameActionMask |= MainLoopController::FA_GRAPHICS; frameActionMask |= MainLoopController::FA_INPUT; } else { input.processInput(); frameActionMask |= MainLoopController::FA_INPUT; } if (mWorldView) { mWorldView->update(); } mServices->getSoundService().cycle(); frameActionMask |= MainLoopController::FA_SOUND; //Keep on running IO and handlers until we need to render again eventService.processEvents(timeFrame.getRemainingTime(), mShouldQuit); mMainLoopController.EventFrameProcessed(timeFrame, frameActionMask); } catch (const std::exception& ex) { S_LOG_CRITICAL("Got exception, shutting down." << ex); throw; } catch (...) { S_LOG_CRITICAL("Got unknown exception, shutting down."); throw; } } while (!mShouldQuit); }
void TaskQueue::pollProcessedTasks(TimeFrame timeFrame) { TaskUnitQueue processedCopy; { std::unique_lock<std::mutex> l(mProcessedQueueMutex); processedCopy = mProcessedTaskUnits; if (!mProcessedTaskUnits.empty()) { mProcessedTaskUnits = TaskUnitQueue(); } } while (!processedCopy.empty()) { TaskUnit* taskUnit = processedCopy.front(); processedCopy.pop(); try { taskUnit->executeInMainThread(); } catch (const std::exception& ex) { S_LOG_FAILURE("Error when executing task in main thread." << ex); } catch (...) { S_LOG_FAILURE("Unknown error when executing task in main thread."); } try { delete taskUnit; } catch (const std::exception& ex) { S_LOG_FAILURE("Error when deleting task in main thread." << ex); } catch (...) { S_LOG_FAILURE("Unknown error when deleting task in main thread."); } //Try to keep the time spent here each frame down, to keep the framerate up. if (!timeFrame.isTimeLeft()) { break; } } //If there are any unprocessed tasks, put them back at the front of the queue. if (!processedCopy.empty()) { std::unique_lock<std::mutex> l(mProcessedQueueMutex); TaskUnitQueue queueCopy(mProcessedTaskUnits); mProcessedTaskUnits = processedCopy; while (!queueCopy.empty()) { mProcessedTaskUnits.push(queueCopy.front()); queueCopy.pop(); } } }
void FrameTimeRecorder::frameCompleted(const TimeFrame& timeFrame, unsigned int frameActionMask) { if (frameActionMask & MainLoopController::FA_GRAPHICS) { mAccumulatedFrameTimes += timeFrame.getElapsedTime(); mAccumulatedFrames++; if (mAccumulatedFrameTimes >= mRequiredTimeSamples) { mTimePerFrameStore.push_back(mAccumulatedFrameTimes / mAccumulatedFrames); mAccumulatedFrameTimes = boost::posix_time::seconds(0); mAccumulatedFrames = 0; boost::posix_time::time_duration averageTimePerFrame = std::accumulate(mTimePerFrameStore.begin(), mTimePerFrameStore.end(), boost::posix_time::time_duration()) / mTimePerFrameStore.size(); EventAverageTimePerFrameUpdated(averageTimePerFrame); } } }
void ModelDefinitionManager::pollBackgroundLoaders(const TimeFrame& timeFrame) { if (mBackgroundLoaders.size()) { TimedLog timedLog("ModelDefinitionManager::pollBackgroundLoaders", true); for (BackgroundLoaderStore::iterator I = mBackgroundLoaders.begin(); I != mBackgroundLoaders.end();) { BackgroundLoaderStore::iterator I_copy = I; ModelBackgroundLoader* loader(*I); ++I; if (loader->poll(timeFrame)) { mBackgroundLoaders.erase(I_copy); loader->reloadModel(); timedLog.report(); } if (!timeFrame.isTimeLeft()) { break; } } } }
void Application::mainLoopStep(long minMicrosecondsPerFrame) { TimeFrame timeFrame = TimeFrame(boost::posix_time::microseconds(minMicrosecondsPerFrame)); Input& input(Input::getSingleton()); ptime currentTime; unsigned int frameActionMask = 0; try { if (mPollEris) { currentTime = microsec_clock::local_time(); mMainLoopController.EventStartErisPoll.emit((currentTime - mLastTimeErisPollStart).total_microseconds() / 1000000.0f); mLastTimeErisPollStart = currentTime; Eris::PollDefault::poll(0); if (mWorldView) { mWorldView->update(); } currentTime = microsec_clock::local_time(); mMainLoopController.EventEndErisPoll.emit((currentTime - mLastTimeErisPollEnd).total_microseconds() / 1000000.0f); mLastTimeErisPollEnd = currentTime; frameActionMask |= MainLoopController::FA_ERIS; } currentTime = microsec_clock::local_time(); mMainLoopController.EventBeforeInputProcessing.emit((currentTime - mLastTimeInputProcessingStart).total_microseconds() / 1000000.0f); mLastTimeInputProcessingStart = currentTime; input.processInput(); frameActionMask |= MainLoopController::FA_INPUT; currentTime = microsec_clock::local_time(); mMainLoopController.EventAfterInputProcessing.emit((currentTime - mLastTimeInputProcessingEnd).total_microseconds() / 1000000.0f); mLastTimeInputProcessingEnd = currentTime; bool updatedRendering = mOgreView->renderOneFrame(timeFrame); if (updatedRendering) { frameActionMask |= MainLoopController::FA_GRAPHICS; } mServices->getSoundService().cycle(); frameActionMask |= MainLoopController::FA_SOUND; mMainLoopController.EventFrameProcessed(timeFrame, frameActionMask); //If we should cap the fps so that each frame should take a minimum amount of time, //we need to see if we should sleep a little. if (minMicrosecondsPerFrame > 0) { if (timeFrame.isTimeLeft()) { try { boost::this_thread::sleep(timeFrame.getRemainingTime()); } catch (const boost::thread_interrupted& ex) { } } } mLastTimeMainLoopStepEnded = microsec_clock::local_time(); } catch (const std::exception& ex) { S_LOG_CRITICAL("Got exception, shutting down." << ex); throw; } catch (const std::string& ex) { S_LOG_CRITICAL("Got exception, shutting down. " << ex); throw; } catch (...) { S_LOG_CRITICAL("Got unknown exception."); throw; } }
bool ModelBackgroundLoader::poll(const TimeFrame& timeFrame) { #if OGRE_THREAD_SUPPORT if (mState == LS_UNINITIALIZED) { //Start to load the meshes for (SubModelDefinitionsStore::const_iterator I_subModels = mModel.getDefinition()->getSubModelDefinitions().begin(); I_subModels != mModel.getDefinition()->getSubModelDefinitions().end(); ++I_subModels) { Ogre::MeshPtr meshPtr = static_cast<Ogre::MeshPtr> (Ogre::MeshManager::getSingleton().getByName((*I_subModels)->getMeshName())); if (meshPtr.isNull() || !meshPtr->isPrepared()) { try { Ogre::BackgroundProcessTicket ticket = Ogre::ResourceBackgroundQueue::getSingleton().prepare(Ogre::MeshManager::getSingleton().getResourceType(), (*I_subModels)->getMeshName(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, false, 0, 0, createListener()); if (ticket) { addTicket(ticket); } } catch (const std::exception& ex) { S_LOG_FAILURE("Could not load the mesh " << (*I_subModels)->getMeshName() << " when loading model " << mModel.getName() << "." << ex); continue; } } } mState = LS_MESH_PREPARING; return poll(timeFrame); } else if (mState == LS_MESH_PREPARING) { if (areAllTicketsProcessed()) { mState = LS_MESH_PREPARED; return poll(timeFrame); } } else if (mState == LS_MESH_PREPARED) { for (SubModelDefinitionsStore::const_iterator I_subModels = mModel.getDefinition()->getSubModelDefinitions().begin(); I_subModels != mModel.getDefinition()->getSubModelDefinitions().end(); ++I_subModels) { Ogre::MeshPtr meshPtr = static_cast<Ogre::MeshPtr> (Ogre::MeshManager::getSingleton().getByName((*I_subModels)->getMeshName())); if (!meshPtr.isNull()) { if (!meshPtr->isLoaded()) { #if OGRE_THREAD_SUPPORT == 1 Ogre::BackgroundProcessTicket ticket = Ogre::ResourceBackgroundQueue::getSingleton().load(Ogre::MeshManager::getSingleton().getResourceType(), meshPtr->getName(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, false, 0, 0, createListener()); if (ticket) { // meshPtr->setBackgroundLoaded(true); addTicket(ticket); } #else if (!timeFrame.isTimeLeft()) { return false; } try { meshPtr->load(); } catch (const std::exception& ex) { S_LOG_FAILURE("Could not load the mesh " << meshPtr->getName() << " when loading model " << mModel.getName() << "." << ex); continue; } #endif } } } mState = LS_MESH_LOADING; return poll(timeFrame); } else if (mState == LS_MESH_LOADING) { if (areAllTicketsProcessed()) { mState = LS_MESH_LOADED; return poll(timeFrame); } } else if (mState == LS_MESH_LOADED) { for (SubModelDefinitionsStore::const_iterator I_subModels = mModel.getDefinition()->getSubModelDefinitions().begin(); I_subModels != mModel.getDefinition()->getSubModelDefinitions().end(); ++I_subModels) { Ogre::MeshPtr meshPtr = static_cast<Ogre::MeshPtr> (Ogre::MeshManager::getSingleton().getByName((*I_subModels)->getMeshName())); if (!meshPtr.isNull()) { if (meshPtr->isLoaded()) { Ogre::Mesh::SubMeshIterator subMeshI = meshPtr->getSubMeshIterator(); while (subMeshI.hasMoreElements()) { Ogre::SubMesh* submesh(subMeshI.getNext()); Ogre::MaterialPtr materialPtr = static_cast<Ogre::MaterialPtr> (Ogre::MaterialManager::getSingleton().getByName(submesh->getMaterialName())); if (materialPtr.isNull() || !materialPtr->isPrepared()) { // S_LOG_VERBOSE("Preparing material " << materialPtr->getName()); Ogre::BackgroundProcessTicket ticket = Ogre::ResourceBackgroundQueue::getSingleton().prepare(Ogre::MaterialManager::getSingleton().getResourceType(),submesh->getMaterialName(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, false, 0, 0, createListener()); if (ticket) { addTicket(ticket); } } } } } for (PartDefinitionsStore::const_iterator I_parts = (*I_subModels)->getPartDefinitions().begin(); I_parts != (*I_subModels)->getPartDefinitions().end(); ++I_parts) { if ((*I_parts)->getSubEntityDefinitions().size() > 0) { for (SubEntityDefinitionsStore::const_iterator I_subEntities = (*I_parts)->getSubEntityDefinitions().begin(); I_subEntities != (*I_parts)->getSubEntityDefinitions().end(); ++I_subEntities) { const std::string& materialName = (*I_subEntities)->getMaterialName(); if (materialName != "") { Ogre::MaterialPtr materialPtr = static_cast<Ogre::MaterialPtr> (Ogre::MaterialManager::getSingleton().getByName(materialName)); if (materialPtr.isNull() || !materialPtr->isPrepared()) { // S_LOG_VERBOSE("Preparing material " << materialName); Ogre::BackgroundProcessTicket ticket = Ogre::ResourceBackgroundQueue::getSingleton().prepare(Ogre::MaterialManager::getSingleton().getResourceType(), materialName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, false, 0, 0, createListener()); if (ticket) { addTicket(ticket); } } } } } } } mState = LS_MATERIAL_PREPARING; return poll(timeFrame); } else if (mState == LS_MATERIAL_PREPARING) { if (areAllTicketsProcessed()) { mState = LS_MATERIAL_PREPARED; return poll(timeFrame); } } else if (mState == LS_MATERIAL_PREPARED) { for (SubModelDefinitionsStore::const_iterator I_subModels = mModel.getDefinition()->getSubModelDefinitions().begin(); I_subModels != mModel.getDefinition()->getSubModelDefinitions().end(); ++I_subModels) { Ogre::MeshPtr meshPtr = static_cast<Ogre::MeshPtr> (Ogre::MeshManager::getSingleton().getByName((*I_subModels)->getMeshName())); Ogre::Mesh::SubMeshIterator subMeshI = meshPtr->getSubMeshIterator(); while (subMeshI.hasMoreElements()) { Ogre::SubMesh* submesh(subMeshI.getNext()); Ogre::MaterialPtr materialPtr = static_cast<Ogre::MaterialPtr> (Ogre::MaterialManager::getSingleton().getByName(submesh->getMaterialName())); if (!materialPtr.isNull() && !materialPtr->isLoaded()) { #if OGRE_THREAD_SUPPORT == 1 Ogre::BackgroundProcessTicket ticket = Ogre::ResourceBackgroundQueue::getSingleton().load(Ogre::MaterialManager::getSingleton().getResourceType(), materialPtr->getName(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, false, 0, 0, createListener()); if (ticket) { // materialPtr->setBackgroundLoaded(true); addTicket(ticket); } #else Ogre::Material::TechniqueIterator techIter = materialPtr->getSupportedTechniqueIterator(); while (techIter.hasMoreElements()) { Ogre::Technique* tech = techIter.getNext(); Ogre::Technique::PassIterator passIter = tech->getPassIterator(); while (passIter.hasMoreElements()) { Ogre::Pass* pass = passIter.getNext(); Ogre::Pass::TextureUnitStateIterator tusIter = pass->getTextureUnitStateIterator(); while (tusIter.hasMoreElements()) { Ogre::TextureUnitState* tus = tusIter.getNext(); unsigned int frames = tus->getNumFrames(); for (unsigned int i = 0; i < frames; ++i) { if (!timeFrame.isTimeLeft()) { return false; } //This will automatically load the texture. // S_LOG_VERBOSE("Loading texture " << tus->getTextureName()); Ogre::TexturePtr texturePtr = tus->_getTexturePtr(i); } } } } if (!timeFrame.isTimeLeft()) { return false; } // S_LOG_VERBOSE("Loading material " << materialPtr->getName()); materialPtr->load(); #endif } } for (PartDefinitionsStore::const_iterator I_parts = (*I_subModels)->getPartDefinitions().begin(); I_parts != (*I_subModels)->getPartDefinitions().end(); ++I_parts) { if ((*I_parts)->getSubEntityDefinitions().size() > 0) { for (SubEntityDefinitionsStore::const_iterator I_subEntities = (*I_parts)->getSubEntityDefinitions().begin(); I_subEntities != (*I_parts)->getSubEntityDefinitions().end(); ++I_subEntities) { const std::string& materialName = (*I_subEntities)->getMaterialName(); if (materialName != "") { Ogre::MaterialPtr materialPtr = static_cast<Ogre::MaterialPtr> (Ogre::MaterialManager::getSingleton().getByName(materialName)); if (!materialPtr.isNull() && !materialPtr->isLoaded()) { #if OGRE_THREAD_SUPPORT == 1 Ogre::BackgroundProcessTicket ticket = Ogre::ResourceBackgroundQueue::getSingleton().load(Ogre::MaterialManager::getSingleton().getResourceType(), materialPtr->getName(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, false, 0, 0, createListener()); if (ticket) { addTicket(ticket); } #else Ogre::Material::TechniqueIterator techIter = materialPtr->getSupportedTechniqueIterator(); while (techIter.hasMoreElements()) { Ogre::Technique* tech = techIter.getNext(); Ogre::Technique::PassIterator passIter = tech->getPassIterator(); while (passIter.hasMoreElements()) { Ogre::Pass* pass = passIter.getNext(); Ogre::Pass::TextureUnitStateIterator tusIter = pass->getTextureUnitStateIterator(); while (tusIter.hasMoreElements()) { Ogre::TextureUnitState* tus = tusIter.getNext(); unsigned int frames = tus->getNumFrames(); for (unsigned int i = 0; i < frames; ++i) { if (!timeFrame.isTimeLeft()) { return false; } //This will automatically load the texture. // S_LOG_VERBOSE("Loading texture " << tus->getTextureName()); Ogre::TexturePtr texturePtr = tus->_getTexturePtr(i); } } } } if (!timeFrame.isTimeLeft()) { return false; } // S_LOG_VERBOSE("Loading material " << materialPtr->getName()); materialPtr->load(); #endif } } } } } } mState = LS_MATERIAL_LOADING; return poll(timeFrame); } else if (mState == LS_MATERIAL_LOADING) { if (areAllTicketsProcessed()) { mState = LS_DONE; return true; } } else { return true; } return false; #else //If there's no threading support, just return here. return true; #endif }