mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 08:15:34 +00:00
Repost navmesh update jobs when failed because of out of memory
DT_OUT_OF_MEMORY error is returned when limit of tiles is reached.
This commit is contained in:
parent
82e2739bae
commit
ff47df4f2c
4 changed files with 59 additions and 15 deletions
|
@ -1,4 +1,4 @@
|
|||
#include "asyncnavmeshupdater.hpp"
|
||||
#include "asyncnavmeshupdater.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "makenavmesh.hpp"
|
||||
#include "settings.hpp"
|
||||
|
@ -30,6 +30,10 @@ namespace DetourNavigator
|
|||
return stream << "add";
|
||||
case UpdateNavMeshStatus::replaced:
|
||||
return stream << "replaced";
|
||||
case UpdateNavMeshStatus::failed:
|
||||
return stream << "failed";
|
||||
case UpdateNavMeshStatus::lost:
|
||||
return stream << "lost";
|
||||
}
|
||||
return stream << "unknown";
|
||||
}
|
||||
|
@ -77,6 +81,7 @@ namespace DetourNavigator
|
|||
job.mAgentHalfExtents = agentHalfExtents;
|
||||
job.mNavMeshCacheItem = navMeshCacheItem;
|
||||
job.mChangedTile = changedTile.first;
|
||||
job.mTryNumber = 0;
|
||||
job.mChangeType = changedTile.second;
|
||||
job.mDistanceToPlayer = getManhattanDistance(changedTile.first, playerTile);
|
||||
job.mDistanceToOrigin = getManhattanDistance(changedTile.first, TilePosition {0, 0});
|
||||
|
@ -104,8 +109,9 @@ namespace DetourNavigator
|
|||
{
|
||||
try
|
||||
{
|
||||
if (const auto job = getNextJob())
|
||||
processJob(*job);
|
||||
if (auto job = getNextJob())
|
||||
if (!processJob(*job))
|
||||
repost(std::move(*job));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
@ -115,7 +121,7 @@ namespace DetourNavigator
|
|||
log("stop process jobs");
|
||||
}
|
||||
|
||||
void AsyncNavMeshUpdater::processJob(const Job& job)
|
||||
bool AsyncNavMeshUpdater::processJob(const Job& job)
|
||||
{
|
||||
log("process job for agent=", job.mAgentHalfExtents);
|
||||
|
||||
|
@ -136,12 +142,16 @@ namespace DetourNavigator
|
|||
|
||||
using FloatMs = std::chrono::duration<float, std::milli>;
|
||||
|
||||
const auto locked = job.mNavMeshCacheItem.lockConst();
|
||||
log("cache updated for agent=", job.mAgentHalfExtents, " status=", status,
|
||||
" generation=", locked->getGeneration(),
|
||||
" revision=", locked->getNavMeshRevision(),
|
||||
" time=", std::chrono::duration_cast<FloatMs>(finish - start).count(), "ms",
|
||||
" total_time=", std::chrono::duration_cast<FloatMs>(finish - firstStart).count(), "ms");
|
||||
{
|
||||
const auto locked = job.mNavMeshCacheItem.lockConst();
|
||||
log("cache updated for agent=", job.mAgentHalfExtents, " status=", status,
|
||||
" generation=", locked->getGeneration(),
|
||||
" revision=", locked->getNavMeshRevision(),
|
||||
" time=", std::chrono::duration_cast<FloatMs>(finish - start).count(), "ms",
|
||||
" total_time=", std::chrono::duration_cast<FloatMs>(finish - firstStart).count(), "ms");
|
||||
}
|
||||
|
||||
return isSuccess(status);
|
||||
}
|
||||
|
||||
boost::optional<AsyncNavMeshUpdater::Job> AsyncNavMeshUpdater::getNextJob()
|
||||
|
@ -194,4 +204,19 @@ namespace DetourNavigator
|
|||
*locked = value;
|
||||
return *locked.get();
|
||||
}
|
||||
|
||||
void AsyncNavMeshUpdater::repost(Job&& job)
|
||||
{
|
||||
if (mShouldStop || job.mTryNumber > 2)
|
||||
return;
|
||||
|
||||
const std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
if (mPushed[job.mAgentHalfExtents].insert(job.mChangedTile).second)
|
||||
{
|
||||
++job.mTryNumber;
|
||||
mJobs.push(std::move(job));
|
||||
mHasJob.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,13 +50,14 @@ namespace DetourNavigator
|
|||
osg::Vec3f mAgentHalfExtents;
|
||||
SharedNavMeshCacheItem mNavMeshCacheItem;
|
||||
TilePosition mChangedTile;
|
||||
unsigned mTryNumber;
|
||||
ChangeType mChangeType;
|
||||
int mDistanceToPlayer;
|
||||
int mDistanceToOrigin;
|
||||
|
||||
std::tuple<ChangeType, int, int> getPriority() const
|
||||
std::tuple<unsigned, ChangeType, int, int> getPriority() const
|
||||
{
|
||||
return std::make_tuple(mChangeType, mDistanceToPlayer, mDistanceToOrigin);
|
||||
return std::make_tuple(mTryNumber, mChangeType, mDistanceToPlayer, mDistanceToOrigin);
|
||||
}
|
||||
|
||||
friend inline bool operator <(const Job& lhs, const Job& rhs)
|
||||
|
@ -83,13 +84,15 @@ namespace DetourNavigator
|
|||
|
||||
void process() throw();
|
||||
|
||||
void processJob(const Job& job);
|
||||
bool processJob(const Job& job);
|
||||
|
||||
boost::optional<Job> getNextJob();
|
||||
|
||||
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
|
||||
|
||||
std::chrono::steady_clock::time_point setFirstStart(const std::chrono::steady_clock::time_point& value);
|
||||
|
||||
void repost(Job&& job);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -464,6 +464,15 @@ namespace
|
|||
return *this;
|
||||
}
|
||||
|
||||
UpdateNavMeshStatusBuilder failed(bool value)
|
||||
{
|
||||
if (value)
|
||||
set(UpdateNavMeshStatus::failed);
|
||||
else
|
||||
unset(UpdateNavMeshStatus::failed);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UpdateNavMeshStatus getResult() const
|
||||
{
|
||||
return mResult;
|
||||
|
@ -531,7 +540,7 @@ namespace
|
|||
if (removed)
|
||||
locked->removeUsedTile(changedTile);
|
||||
log("failed to add tile with status=", WriteDtStatus {addStatus});
|
||||
return UpdateNavMeshStatusBuilder().removed(removed).getResult();
|
||||
return UpdateNavMeshStatusBuilder().removed(removed).failed((addStatus & DT_OUT_OF_MEMORY) != 0).getResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,15 @@ namespace DetourNavigator
|
|||
removed = 1 << 0,
|
||||
added = 1 << 1,
|
||||
replaced = removed | added,
|
||||
failed = 1 << 2,
|
||||
lost = removed | failed,
|
||||
};
|
||||
|
||||
inline bool isSuccess(UpdateNavMeshStatus value)
|
||||
{
|
||||
return (static_cast<unsigned>(value) & static_cast<unsigned>(UpdateNavMeshStatus::failed)) == 0;
|
||||
}
|
||||
|
||||
inline float getLength(const osg::Vec2i& value)
|
||||
{
|
||||
return std::sqrt(float(osg::square(value.x()) + osg::square(value.y())));
|
||||
|
@ -41,7 +48,7 @@ namespace DetourNavigator
|
|||
inline bool shouldAddTile(const TilePosition& changedTile, const TilePosition& playerTile, int maxTiles)
|
||||
{
|
||||
const auto expectedTilesCount = std::ceil(osg::PI * osg::square(getDistance(changedTile, playerTile)));
|
||||
return expectedTilesCount * 3 <= maxTiles;
|
||||
return expectedTilesCount <= maxTiles;
|
||||
}
|
||||
|
||||
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
||||
|
|
Loading…
Reference in a new issue