avoid pagerebuild when reloading a same save

Signed-off-by: Bret Curtis <psi29a@gmail.com>
pull/578/head
bzzt lost a hitlab login 5 years ago committed by Bret Curtis
parent 6fa12a6eb8
commit b27b76e325

@ -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 &centerCell) 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…
Cancel
Save