mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-21 17:39:40 +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 "debug.hpp"
|
||||||
#include "makenavmesh.hpp"
|
#include "makenavmesh.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
@ -30,6 +30,10 @@ namespace DetourNavigator
|
||||||
return stream << "add";
|
return stream << "add";
|
||||||
case UpdateNavMeshStatus::replaced:
|
case UpdateNavMeshStatus::replaced:
|
||||||
return stream << "replaced";
|
return stream << "replaced";
|
||||||
|
case UpdateNavMeshStatus::failed:
|
||||||
|
return stream << "failed";
|
||||||
|
case UpdateNavMeshStatus::lost:
|
||||||
|
return stream << "lost";
|
||||||
}
|
}
|
||||||
return stream << "unknown";
|
return stream << "unknown";
|
||||||
}
|
}
|
||||||
|
@ -77,6 +81,7 @@ namespace DetourNavigator
|
||||||
job.mAgentHalfExtents = agentHalfExtents;
|
job.mAgentHalfExtents = agentHalfExtents;
|
||||||
job.mNavMeshCacheItem = navMeshCacheItem;
|
job.mNavMeshCacheItem = navMeshCacheItem;
|
||||||
job.mChangedTile = changedTile.first;
|
job.mChangedTile = changedTile.first;
|
||||||
|
job.mTryNumber = 0;
|
||||||
job.mChangeType = changedTile.second;
|
job.mChangeType = changedTile.second;
|
||||||
job.mDistanceToPlayer = getManhattanDistance(changedTile.first, playerTile);
|
job.mDistanceToPlayer = getManhattanDistance(changedTile.first, playerTile);
|
||||||
job.mDistanceToOrigin = getManhattanDistance(changedTile.first, TilePosition {0, 0});
|
job.mDistanceToOrigin = getManhattanDistance(changedTile.first, TilePosition {0, 0});
|
||||||
|
@ -104,8 +109,9 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (const auto job = getNextJob())
|
if (auto job = getNextJob())
|
||||||
processJob(*job);
|
if (!processJob(*job))
|
||||||
|
repost(std::move(*job));
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -115,7 +121,7 @@ namespace DetourNavigator
|
||||||
log("stop process jobs");
|
log("stop process jobs");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncNavMeshUpdater::processJob(const Job& job)
|
bool AsyncNavMeshUpdater::processJob(const Job& job)
|
||||||
{
|
{
|
||||||
log("process job for agent=", job.mAgentHalfExtents);
|
log("process job for agent=", job.mAgentHalfExtents);
|
||||||
|
|
||||||
|
@ -136,12 +142,16 @@ namespace DetourNavigator
|
||||||
|
|
||||||
using FloatMs = std::chrono::duration<float, std::milli>;
|
using FloatMs = std::chrono::duration<float, std::milli>;
|
||||||
|
|
||||||
const auto locked = job.mNavMeshCacheItem.lockConst();
|
{
|
||||||
log("cache updated for agent=", job.mAgentHalfExtents, " status=", status,
|
const auto locked = job.mNavMeshCacheItem.lockConst();
|
||||||
" generation=", locked->getGeneration(),
|
log("cache updated for agent=", job.mAgentHalfExtents, " status=", status,
|
||||||
" revision=", locked->getNavMeshRevision(),
|
" generation=", locked->getGeneration(),
|
||||||
" time=", std::chrono::duration_cast<FloatMs>(finish - start).count(), "ms",
|
" revision=", locked->getNavMeshRevision(),
|
||||||
" total_time=", std::chrono::duration_cast<FloatMs>(finish - firstStart).count(), "ms");
|
" 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()
|
boost::optional<AsyncNavMeshUpdater::Job> AsyncNavMeshUpdater::getNextJob()
|
||||||
|
@ -194,4 +204,19 @@ namespace DetourNavigator
|
||||||
*locked = value;
|
*locked = value;
|
||||||
return *locked.get();
|
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;
|
osg::Vec3f mAgentHalfExtents;
|
||||||
SharedNavMeshCacheItem mNavMeshCacheItem;
|
SharedNavMeshCacheItem mNavMeshCacheItem;
|
||||||
TilePosition mChangedTile;
|
TilePosition mChangedTile;
|
||||||
|
unsigned mTryNumber;
|
||||||
ChangeType mChangeType;
|
ChangeType mChangeType;
|
||||||
int mDistanceToPlayer;
|
int mDistanceToPlayer;
|
||||||
int mDistanceToOrigin;
|
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)
|
friend inline bool operator <(const Job& lhs, const Job& rhs)
|
||||||
|
@ -83,13 +84,15 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void process() throw();
|
void process() throw();
|
||||||
|
|
||||||
void processJob(const Job& job);
|
bool processJob(const Job& job);
|
||||||
|
|
||||||
boost::optional<Job> getNextJob();
|
boost::optional<Job> getNextJob();
|
||||||
|
|
||||||
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
|
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point setFirstStart(const std::chrono::steady_clock::time_point& value);
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateNavMeshStatusBuilder failed(bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
set(UpdateNavMeshStatus::failed);
|
||||||
|
else
|
||||||
|
unset(UpdateNavMeshStatus::failed);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
UpdateNavMeshStatus getResult() const
|
UpdateNavMeshStatus getResult() const
|
||||||
{
|
{
|
||||||
return mResult;
|
return mResult;
|
||||||
|
@ -531,7 +540,7 @@ namespace
|
||||||
if (removed)
|
if (removed)
|
||||||
locked->removeUsedTile(changedTile);
|
locked->removeUsedTile(changedTile);
|
||||||
log("failed to add tile with status=", WriteDtStatus {addStatus});
|
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,
|
removed = 1 << 0,
|
||||||
added = 1 << 1,
|
added = 1 << 1,
|
||||||
replaced = removed | added,
|
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)
|
inline float getLength(const osg::Vec2i& value)
|
||||||
{
|
{
|
||||||
return std::sqrt(float(osg::square(value.x()) + osg::square(value.y())));
|
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)
|
inline bool shouldAddTile(const TilePosition& changedTile, const TilePosition& playerTile, int maxTiles)
|
||||||
{
|
{
|
||||||
const auto expectedTilesCount = std::ceil(osg::PI * osg::square(getDistance(changedTile, playerTile)));
|
const auto expectedTilesCount = std::ceil(osg::PI * osg::square(getDistance(changedTile, playerTile)));
|
||||||
return expectedTilesCount * 3 <= maxTiles;
|
return expectedTilesCount <= maxTiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
NavMeshPtr makeEmptyNavMesh(const Settings& settings);
|
||||||
|
|
Loading…
Reference in a new issue