Avoid the terrain sync completely in most cases (#3103)

We can take elsid's commit 605cb8d further by avoiding the terrain sync completely in most cases. Currently in changeCellGrid we wait for a new preloading task to ensure the getPagedRefnums for the new active cells have been filled in by object paging. This is usually not necessary because we have already completed a preload in the past containing these active cells. With this PR we remember what we preloaded and skip the terrain sync if it is not needed.
pull/3118/head
Bo Svensson 3 years ago committed by GitHub
parent c658acc2b3
commit f62adab43a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -21,6 +21,29 @@
#include "cellstore.hpp"
#include "class.hpp"
namespace
{
template <class Contained>
bool contains(const std::vector<MWWorld::CellPreloader::PositionCellGrid>& container,
const Contained& contained, float tolerance=1.f)
{
for (const auto& pos : contained)
{
bool found = false;
for (const auto& pos2 : container)
{
if ((pos.first-pos2.first).length2() < tolerance*tolerance && pos.second == pos2.second)
{
found = true;
break;
}
}
if (!found) return false;
}
return true;
}
}
namespace MWWorld
{
@ -224,6 +247,7 @@ namespace MWWorld
, mPreloadInstances(true)
, mLastResourceCacheUpdate(0.0)
, mStoreViewsFailCount(0)
, mLoadedTerrainTimestamp(0.0)
{
}
@ -369,7 +393,11 @@ namespace MWWorld
setTerrainPreloadPositions(std::vector<PositionCellGrid>());
}
else
{
mStoreViewsFailCount = 0;
mLoadedTerrainPositions = mTerrainPreloadPositions;
mLoadedTerrainTimestamp = timestamp;
}
mTerrainPreloadItem = nullptr;
}
}
@ -436,10 +464,8 @@ namespace MWWorld
void CellPreloader::abortTerrainPreloadExcept(const CellPreloader::PositionCellGrid *exceptPos)
{
const float resetThreshold = ESM::Land::REAL_SIZE;
for (const auto& pos : mTerrainPreloadPositions)
if (exceptPos && (pos.first-exceptPos->first).length2() < resetThreshold*resetThreshold && pos.second == exceptPos->second)
return;
if (exceptPos && contains(mTerrainPreloadPositions, std::array {*exceptPos}, ESM::Land::REAL_SIZE))
return;
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
{
mTerrainPreloadItem->abort();
@ -448,28 +474,13 @@ namespace MWWorld
setTerrainPreloadPositions(std::vector<CellPreloader::PositionCellGrid>());
}
bool contains(const std::vector<CellPreloader::PositionCellGrid>& container, const std::vector<CellPreloader::PositionCellGrid>& contained)
{
for (const auto& pos : contained)
{
bool found = false;
for (const auto& pos2 : container)
{
if ((pos.first-pos2.first).length2() < 1 && pos.second == pos2.second)
{
found = true;
break;
}
}
if (!found) return false;
}
return true;
}
void CellPreloader::setTerrainPreloadPositions(const std::vector<CellPreloader::PositionCellGrid> &positions)
{
if (positions.empty())
{
mTerrainPreloadPositions.clear();
mLoadedTerrainPositions.clear();
}
else if (contains(mTerrainPreloadPositions, positions))
return;
if (mTerrainPreloadItem && !mTerrainPreloadItem->isDone())
@ -496,5 +507,10 @@ namespace MWWorld
}
}
}
bool CellPreloader::isTerrainLoaded(const CellPreloader::PositionCellGrid &position, double referenceTime) const
{
return mLoadedTerrainTimestamp + mResourceSystem->getSceneManager()->getExpiryDelay() > referenceTime && contains(mLoadedTerrainPositions, std::array {position}, ESM::Land::REAL_SIZE);
}
}

@ -79,6 +79,7 @@ namespace MWWorld
bool syncTerrainLoad(const std::vector<CellPreloader::PositionCellGrid> &positions, double timestamp, Loading::Listener& listener);
void abortTerrainPreloadExcept(const PositionCellGrid *exceptPos);
bool isTerrainLoaded(const CellPreloader::PositionCellGrid &position, double referenceTime) const;
private:
Resource::ResourceSystem* mResourceSystem;
@ -119,6 +120,9 @@ namespace MWWorld
std::vector<PositionCellGrid> mTerrainPreloadPositions;
osg::ref_ptr<TerrainPreloadItem> mTerrainPreloadItem;
osg::ref_ptr<SceneUtil::WorkItem> mUpdateCacheItem;
std::vector<PositionCellGrid> mLoadedTerrainPositions;
double mLoadedTerrainTimestamp;
};
}

@ -628,7 +628,10 @@ namespace MWWorld
osg::Vec4i newGrid = gridCenterToBounds(mCurrentGridCenter);
mRendering.setActiveGrid(newGrid);
preloadTerrain(pos, true);
if (mRendering.pagingUnlockCache())
mPreloader->abortTerrainPreloadExcept(nullptr);
if (!mPreloader->isTerrainLoaded(std::make_pair(pos, newGrid), mRendering.getReferenceTime()))
preloadTerrain(pos, true);
mPagedRefs.clear();
mRendering.getPagedRefnums(newGrid, mPagedRefs);
@ -1241,10 +1244,7 @@ namespace MWWorld
{
std::vector<PositionCellGrid> vec;
vec.emplace_back(pos, gridCenterToBounds(getNewGridCenter(pos)));
if (sync && mRendering.pagingUnlockCache())
mPreloader->abortTerrainPreloadExcept(nullptr);
else
mPreloader->abortTerrainPreloadExcept(&vec[0]);
mPreloader->abortTerrainPreloadExcept(&vec[0]);
mPreloader->setTerrainPreloadPositions(vec);
if (!sync) return;

@ -59,6 +59,7 @@ namespace Resource
/// How long to keep objects in cache after no longer being referenced.
void setExpiryDelay (double expiryDelay) override { mExpiryDelay = expiryDelay; }
float getExpiryDelay() const { return mExpiryDelay; }
const VFS::Manager* getVFS() const { return mVFS; }

Loading…
Cancel
Save