1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-27 18:41:05 +00:00

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.
This commit is contained in:
Bo Svensson 2021-09-16 20:11:19 +00:00 committed by GitHub
parent c658acc2b3
commit f62adab43a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 27 deletions

View File

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

View File

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

View File

@ -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;

View File

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