mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-03 19:15:40 +00:00
avoid pagerebuild when reloading a same save
Signed-off-by: Bret Curtis <psi29a@gmail.com>
This commit is contained in:
parent
6fa12a6eb8
commit
b27b76e325
8 changed files with 110 additions and 67 deletions
|
@ -339,6 +339,7 @@ namespace MWRender
|
|||
ObjectPaging::ObjectPaging(Resource::SceneManager* sceneManager)
|
||||
: GenericResourceManager<ChunkId>(nullptr)
|
||||
, mSceneManager(sceneManager)
|
||||
, mRefTrackerLocked(false)
|
||||
{
|
||||
mActiveGrid = Settings::Manager::getBool("object paging active grid", "Terrain");
|
||||
mDebugBatches = Settings::Manager::getBool("object paging debug batches", "Terrain");
|
||||
|
@ -403,9 +404,9 @@ namespace MWRender
|
|||
}
|
||||
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||
if (activeGrid)
|
||||
for (auto ref : mBlacklist)
|
||||
for (auto ref : getRefTracker().mBlacklist)
|
||||
refs.erase(ref);
|
||||
}
|
||||
|
||||
|
@ -489,8 +490,8 @@ namespace MWRender
|
|||
}
|
||||
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
||||
if (mDisabled.count(pair.first))
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||
if (getRefTracker().mDisabled.count(pair.first))
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -683,14 +684,16 @@ namespace MWRender
|
|||
return false;
|
||||
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
||||
if (enabled && !mDisabled.erase(refnum)) return false;
|
||||
if (!enabled && !mDisabled.insert(refnum).second) return false;
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||
if (enabled && !getWritableRefTracker().mDisabled.erase(refnum)) return false;
|
||||
if (!enabled && !getWritableRefTracker().mDisabled.insert(refnum).second) return false;
|
||||
if (mRefTrackerLocked) return false;
|
||||
}
|
||||
|
||||
ClearCacheFunctor ccf;
|
||||
ccf.mPosition = pos;
|
||||
mCache->call(ccf);
|
||||
if (ccf.mToClear.empty()) return false;
|
||||
for (auto chunk : ccf.mToClear)
|
||||
mCache->removeFromObjectCache(chunk);
|
||||
return true;
|
||||
|
@ -702,8 +705,9 @@ namespace MWRender
|
|||
return false;
|
||||
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
||||
if (!mBlacklist.insert(refnum).second) return false;
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||
if (!getWritableRefTracker().mBlacklist.insert(refnum).second) return false;
|
||||
if (mRefTrackerLocked) return false;
|
||||
}
|
||||
|
||||
ClearCacheFunctor ccf;
|
||||
|
@ -719,12 +723,25 @@ namespace MWRender
|
|||
|
||||
void ObjectPaging::clear()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||
mRefTrackerNew.mDisabled.clear();
|
||||
mRefTrackerNew.mBlacklist.clear();
|
||||
mRefTrackerLocked = true;
|
||||
}
|
||||
|
||||
bool ObjectPaging::unlockCache()
|
||||
{
|
||||
if (!mRefTrackerLocked) return false;
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mDisabledMutex);
|
||||
mDisabled.clear();
|
||||
mBlacklist.clear();
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mRefTrackerMutex);
|
||||
mRefTrackerLocked = false;
|
||||
if (mRefTracker == mRefTrackerNew)
|
||||
return false;
|
||||
else
|
||||
mRefTracker = mRefTrackerNew;
|
||||
}
|
||||
mCache->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
struct GetRefnumsFunctor
|
||||
|
|
|
@ -41,6 +41,10 @@ namespace MWRender
|
|||
|
||||
void clear();
|
||||
|
||||
/// Must be called after clear() before rendering starts.
|
||||
/// @return true if view needs rebuild
|
||||
bool unlockCache();
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats* stats) const override;
|
||||
|
||||
void getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out);
|
||||
|
@ -54,9 +58,19 @@ namespace MWRender
|
|||
float mMinSizeMergeFactor;
|
||||
float mMinSizeCostMultiplier;
|
||||
|
||||
OpenThreads::Mutex mDisabledMutex;
|
||||
std::set<ESM::RefNum> mDisabled;
|
||||
std::set<ESM::RefNum> mBlacklist;
|
||||
OpenThreads::Mutex mRefTrackerMutex;
|
||||
struct RefTracker
|
||||
{
|
||||
std::set<ESM::RefNum> mDisabled;
|
||||
std::set<ESM::RefNum> mBlacklist;
|
||||
bool operator==(const RefTracker&other) { return mDisabled == other.mDisabled && mBlacklist == other.mBlacklist; }
|
||||
};
|
||||
RefTracker mRefTracker;
|
||||
RefTracker mRefTrackerNew;
|
||||
bool mRefTrackerLocked;
|
||||
|
||||
const RefTracker& getRefTracker() const { return mRefTracker; }
|
||||
RefTracker& getWritableRefTracker() { return mRefTrackerLocked ? mRefTrackerNew : mRefTracker; }
|
||||
|
||||
OpenThreads::Mutex mSizeCacheMutex;
|
||||
typedef std::map<ESM::RefNum, float> SizeCache;
|
||||
|
|
|
@ -1511,6 +1511,15 @@ namespace MWRender
|
|||
if (mObjectPaging->blacklistObject(type, refnum, ptr.getCellRef().getPosition().asVec3()))
|
||||
mTerrain->rebuildViews();
|
||||
}
|
||||
bool RenderingManager::pagingUnlockCache()
|
||||
{
|
||||
if (mObjectPaging && mObjectPaging->unlockCache())
|
||||
{
|
||||
mTerrain->rebuildViews();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void RenderingManager::getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out)
|
||||
{
|
||||
if (mObjectPaging)
|
||||
|
|
|
@ -244,6 +244,7 @@ namespace MWRender
|
|||
|
||||
bool pagingEnableObject(int type, const MWWorld::ConstPtr& ptr, bool enabled);
|
||||
void pagingBlacklistObject(int type, const MWWorld::ConstPtr &ptr);
|
||||
bool pagingUnlockCache();
|
||||
void getPagedRefnums(const osg::Vec4i &activeGrid, std::set<ESM::RefNum> &out);
|
||||
|
||||
private:
|
||||
|
|
|
@ -419,36 +419,44 @@ namespace MWWorld
|
|||
mUnrefQueue = unrefQueue;
|
||||
}
|
||||
|
||||
bool CellPreloader::getTerrainPreloadInProgress(int& progress, int& progressRange, double timestamp)
|
||||
bool CellPreloader::syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, int& progress, int& progressRange, double timestamp)
|
||||
{
|
||||
if (!mTerrainPreloadItem)
|
||||
return false;
|
||||
return true;
|
||||
else if (mTerrainPreloadItem->isDone())
|
||||
{
|
||||
mTerrainPreloadItem->storeViews(timestamp);
|
||||
mTerrainPreloadItem = nullptr;
|
||||
return false;
|
||||
if (mTerrainPreloadItem->storeViews(timestamp))
|
||||
{
|
||||
mTerrainPreloadItem = nullptr;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
setTerrainPreloadPositions(std::vector<CellPreloader::PositionCellGrid>());
|
||||
setTerrainPreloadPositions(positions);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
progress = mTerrainPreloadItem->getProgress();
|
||||
progressRange = mTerrainPreloadItem->getProgressRange();
|
||||
return !progress || progress < progressRange;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid& exceptPos)
|
||||
void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid *exceptPos)
|
||||
{
|
||||
const float resetThreshold = ESM::Land::REAL_SIZE;
|
||||
for (auto pos : mTerrainPreloadPositions)
|
||||
if (exceptPos && (pos.first-exceptPos->first).length2() < resetThreshold*resetThreshold && pos.second == exceptPos->second)
|
||||
return;
|
||||
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
|
||||
{
|
||||
const float resetThreshold = ESM::Land::REAL_SIZE;
|
||||
for (auto pos : mTerrainPreloadPositions)
|
||||
if ((pos.first-exceptPos.first).length2() < resetThreshold*resetThreshold && pos.second == exceptPos.second)
|
||||
return;
|
||||
mTerrainPreloadItem->abort();
|
||||
mTerrainPreloadItem->waitTillDone();
|
||||
mTerrainPreloadItem = nullptr;
|
||||
}
|
||||
setTerrainPreloadPositions(std::vector<CellPreloader::PositionCellGrid>());
|
||||
}
|
||||
|
||||
bool contains(const std::vector<CellPreloader::PositionCellGrid>& container, const std::vector<CellPreloader::PositionCellGrid>& contained)
|
||||
|
|
|
@ -72,8 +72,8 @@ namespace MWWorld
|
|||
typedef std::pair<osg::Vec3f, osg::Vec4i> PositionCellGrid;
|
||||
void setTerrainPreloadPositions(const std::vector<PositionCellGrid>& positions);
|
||||
|
||||
bool getTerrainPreloadInProgress(int& progress, int& progressRange, double timestamp);
|
||||
void abortTerrainPreloadExcept(const PositionCellGrid &exceptPos);
|
||||
bool syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, int& progress, int& progressRange, double timestamp);
|
||||
void abortTerrainPreloadExcept(const PositionCellGrid *exceptPos);
|
||||
|
||||
private:
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
|
|
|
@ -510,13 +510,10 @@ namespace MWWorld
|
|||
|
||||
osg::Vec2i newCell = getNewGridCenter(pos, &mCurrentGridCenter);
|
||||
if (newCell != mCurrentGridCenter)
|
||||
{
|
||||
preloadTerrain(pos);
|
||||
changeCellGrid(newCell.x(), newCell.y());
|
||||
}
|
||||
changeCellGrid(pos, newCell.x(), newCell.y());
|
||||
}
|
||||
|
||||
void Scene::changeCellGrid (int playerCellX, int playerCellY, bool changeEvent)
|
||||
void Scene::changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent)
|
||||
{
|
||||
CellStoreCollection::iterator active = mActiveCells.begin();
|
||||
while (active!=mActiveCells.end())
|
||||
|
@ -538,8 +535,8 @@ namespace MWWorld
|
|||
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
|
||||
mRendering.setActiveGrid(newGrid);
|
||||
|
||||
preloadTerrain(pos, true);
|
||||
mPagedRefs.clear();
|
||||
checkTerrainLoaded();
|
||||
mRendering.getPagedRefnums(newGrid, mPagedRefs);
|
||||
|
||||
std::size_t refsToLoad = 0;
|
||||
|
@ -867,9 +864,7 @@ namespace MWWorld
|
|||
if (changeEvent)
|
||||
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
|
||||
|
||||
preloadTerrain(position.asVec3());
|
||||
checkTerrainLoaded();
|
||||
changeCellGrid(x, y, changeEvent);
|
||||
changeCellGrid(position.asVec3(), x, y, changeEvent);
|
||||
|
||||
CellStore* current = MWBase::Environment::get().getWorld()->getExterior(x, y);
|
||||
changePlayerCell(current, position, adjustPlayerPos);
|
||||
|
@ -878,29 +873,6 @@ namespace MWWorld
|
|||
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
|
||||
}
|
||||
|
||||
void Scene::checkTerrainLoaded()
|
||||
{
|
||||
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||
Loading::ScopedLoad load(loadingListener);
|
||||
int progress = 0, initialProgress = -1, progressRange = 0;
|
||||
while (mPreloader->getTerrainPreloadInProgress(progress, progressRange, mRendering.getReferenceTime()))
|
||||
{
|
||||
if (initialProgress == -1)
|
||||
{
|
||||
loadingListener->setLabel("#{sLoadingMessage4}");
|
||||
initialProgress = progress;
|
||||
}
|
||||
if (progress)
|
||||
{
|
||||
loadingListener->setProgressRange(std::max(0, progressRange-initialProgress));
|
||||
loadingListener->setProgress(progress-initialProgress);
|
||||
}
|
||||
else
|
||||
loadingListener->setProgress(0);
|
||||
OpenThreads::Thread::microSleep(5000);
|
||||
}
|
||||
}
|
||||
|
||||
CellStore* Scene::getCurrentCell ()
|
||||
{
|
||||
return mCurrentCell;
|
||||
|
@ -1145,12 +1117,36 @@ namespace MWWorld
|
|||
mPreloader->preload(cell, mRendering.getReferenceTime());
|
||||
}
|
||||
|
||||
void Scene::preloadTerrain(const osg::Vec3f &pos)
|
||||
void Scene::preloadTerrain(const osg::Vec3f &pos, bool sync)
|
||||
{
|
||||
std::vector<PositionCellGrid> vec;
|
||||
vec.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos)));
|
||||
mPreloader->abortTerrainPreloadExcept(vec[0]);
|
||||
if (sync && mRendering.pagingUnlockCache())
|
||||
mPreloader->abortTerrainPreloadExcept(nullptr);
|
||||
else
|
||||
mPreloader->abortTerrainPreloadExcept(&vec[0]);
|
||||
mPreloader->setTerrainPreloadPositions(vec);
|
||||
if (!sync) return;
|
||||
|
||||
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||
Loading::ScopedLoad load(loadingListener);
|
||||
int progress = 0, initialProgress = -1, progressRange = 0;
|
||||
while (!mPreloader->syncTerrainLoad(vec, progress, progressRange, mRendering.getReferenceTime()))
|
||||
{
|
||||
if (initialProgress == -1)
|
||||
{
|
||||
loadingListener->setLabel("#{sLoadingMessage4}");
|
||||
initialProgress = progress;
|
||||
}
|
||||
if (progress)
|
||||
{
|
||||
loadingListener->setProgressRange(std::max(0, progressRange-initialProgress));
|
||||
loadingListener->setProgress(progress-initialProgress);
|
||||
}
|
||||
else
|
||||
loadingListener->setProgress(0);
|
||||
OpenThreads::Thread::microSleep(5000);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::reloadTerrain()
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace MWWorld
|
|||
osg::Vec2i mCurrentGridCenter;
|
||||
|
||||
// Load and unload cells as necessary to create a cell grid with "X" and "Y" in the center
|
||||
void changeCellGrid (int playerCellX, int playerCellY, bool changeEvent = true);
|
||||
void changeCellGrid (const osg::Vec3f &pos, int playerCellX, int playerCellY, bool changeEvent = true);
|
||||
|
||||
typedef std::pair<osg::Vec3f, osg::Vec4i> PositionCellGrid;
|
||||
|
||||
|
@ -102,8 +102,6 @@ namespace MWWorld
|
|||
void preloadExteriorGrid(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos);
|
||||
void preloadFastTravelDestinations(const osg::Vec3f& playerPos, const osg::Vec3f& predictedPos, std::vector<PositionCellGrid>& exteriorPositions);
|
||||
|
||||
void checkTerrainLoaded();
|
||||
|
||||
osg::Vec4i gridCenterToBounds(const osg::Vec2i ¢erCell) const;
|
||||
osg::Vec2i getNewGridCenter(const osg::Vec3f &pos, const osg::Vec2i *currentGridCenter = nullptr) const;
|
||||
|
||||
|
@ -115,7 +113,7 @@ namespace MWWorld
|
|||
~Scene();
|
||||
|
||||
void preloadCell(MWWorld::CellStore* cell, bool preloadSurrounding=false);
|
||||
void preloadTerrain(const osg::Vec3f& pos);
|
||||
void preloadTerrain(const osg::Vec3f& pos, bool sync=false);
|
||||
void reloadTerrain();
|
||||
|
||||
void unloadCell (CellStoreCollection::iterator iter, bool test = false);
|
||||
|
|
Loading…
Reference in a new issue