1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 19:29:56 +00:00
openmw/components/detournavigator/asyncnavmeshupdater.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

215 lines
6.4 KiB
C++
Raw Normal View History

2018-03-13 22:49:08 +00:00
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_ASYNCNAVMESHUPDATER_H
#include "agentbounds.hpp"
#include "changetype.hpp"
2022-08-11 22:09:49 +00:00
#include "guardednavmeshcacheitem.hpp"
#include "navmeshcacheitem.hpp"
#include "navmeshdb.hpp"
#include "navmeshtilescache.hpp"
#include "offmeshconnectionsmanager.hpp"
2022-08-11 22:09:49 +00:00
#include "sharednavmeshcacheitem.hpp"
#include "stats.hpp"
2018-04-15 22:07:18 +00:00
#include "tilecachedrecastmeshmanager.hpp"
#include "tileposition.hpp"
#include "waitconditiontype.hpp"
2018-03-13 22:49:08 +00:00
#include <atomic>
#include <chrono>
2018-03-13 22:49:08 +00:00
#include <condition_variable>
#include <deque>
2022-06-26 17:36:03 +00:00
#include <iosfwd>
#include <list>
2018-03-13 22:49:08 +00:00
#include <memory>
#include <mutex>
#include <optional>
#include <set>
2018-03-13 22:49:08 +00:00
#include <thread>
#include <tuple>
2018-03-13 22:49:08 +00:00
class dtNavMesh;
namespace Loading
{
class Listener;
}
2018-03-13 22:49:08 +00:00
namespace DetourNavigator
{
enum class JobState
{
Initial,
WithDbResult,
};
struct Job
{
const std::size_t mId;
const AgentBounds mAgentBounds;
2021-08-07 00:23:43 +00:00
const std::weak_ptr<GuardedNavMeshCacheItem> mNavMeshCacheItem;
const std::string mWorldspace;
2021-08-07 00:23:43 +00:00
const TilePosition mChangedTile;
const std::chrono::steady_clock::time_point mProcessTime;
unsigned mTryNumber = 0;
ChangeType mChangeType;
int mDistanceToPlayer;
2021-08-07 00:23:43 +00:00
const int mDistanceToOrigin;
JobState mState = JobState::Initial;
std::vector<std::byte> mInput;
std::shared_ptr<RecastMesh> mRecastMesh;
std::optional<TileData> mCachedTileData;
std::unique_ptr<PreparedNavMeshData> mGeneratedNavMeshData;
2021-08-07 00:23:43 +00:00
Job(const AgentBounds& agentBounds, std::weak_ptr<GuardedNavMeshCacheItem> navMeshCacheItem,
std::string_view worldspace, const TilePosition& changedTile, ChangeType changeType, int distanceToPlayer,
2021-08-07 00:23:43 +00:00
std::chrono::steady_clock::time_point processTime);
};
using JobIt = std::list<Job>::iterator;
enum class JobStatus
{
Done,
Fail,
MemoryCacheMiss,
};
2022-06-26 17:36:03 +00:00
std::ostream& operator<<(std::ostream& stream, JobStatus value);
class DbJobQueue
{
public:
void push(JobIt job);
std::optional<JobIt> pop();
void update(TilePosition playerTile, int maxTiles);
void stop();
DbJobQueueStats getStats() const;
private:
mutable std::mutex mMutex;
std::condition_variable mHasJob;
std::deque<JobIt> mJobs;
bool mShouldStop = false;
std::size_t mWritingJobs = 0;
std::size_t mReadingJobs = 0;
};
class AsyncNavMeshUpdater;
class DbWorker
{
public:
DbWorker(AsyncNavMeshUpdater& updater, std::unique_ptr<NavMeshDb>&& db, TileVersion version,
const RecastSettings& recastSettings, bool writeToDb);
~DbWorker();
DbWorkerStats getStats() const;
void enqueueJob(JobIt job);
void updateJobs(TilePosition playerTile, int maxTiles) { mQueue.update(playerTile, maxTiles); }
void stop();
private:
AsyncNavMeshUpdater& mUpdater;
const RecastSettings& mRecastSettings;
const std::unique_ptr<NavMeshDb> mDb;
const TileVersion mVersion;
bool mWriteToDb;
TileId mNextTileId;
ShapeId mNextShapeId;
DbJobQueue mQueue;
std::atomic_bool mShouldStop{ false };
std::atomic_size_t mGetTileCount{ 0 };
std::thread mThread;
inline void run() noexcept;
inline void processJob(JobIt job);
inline void processReadingJob(JobIt job);
inline void processWritingJob(JobIt job);
};
2018-03-13 22:49:08 +00:00
class AsyncNavMeshUpdater
{
public:
AsyncNavMeshUpdater(const Settings& settings, TileCachedRecastMeshManager& recastMeshManager,
OffMeshConnectionsManager& offMeshConnectionsManager, std::unique_ptr<NavMeshDb>&& db);
2018-03-13 22:49:08 +00:00
~AsyncNavMeshUpdater();
void post(const AgentBounds& agentBounds, const SharedNavMeshCacheItem& navMeshCacheItem,
const TilePosition& playerTile, std::string_view worldspace,
const std::map<TilePosition, ChangeType>& changedTiles);
2018-03-13 22:49:08 +00:00
void wait(WaitConditionType waitConditionType, Loading::Listener* listener);
2018-03-13 22:49:08 +00:00
void stop();
AsyncNavMeshUpdaterStats getStats() const;
void enqueueJob(JobIt job);
void removeJob(JobIt job);
2019-03-17 17:18:53 +00:00
2018-03-13 22:49:08 +00:00
private:
std::reference_wrapper<const Settings> mSettings;
2018-04-15 22:07:18 +00:00
std::reference_wrapper<TileCachedRecastMeshManager> mRecastMeshManager;
std::reference_wrapper<OffMeshConnectionsManager> mOffMeshConnectionsManager;
2018-03-13 22:49:08 +00:00
std::atomic_bool mShouldStop;
2019-03-17 17:18:53 +00:00
mutable std::mutex mMutex;
2018-03-13 22:49:08 +00:00
std::condition_variable mHasJob;
std::condition_variable mDone;
std::condition_variable mProcessed;
std::list<Job> mJobs;
std::deque<JobIt> mWaiting;
std::set<std::tuple<AgentBounds, TilePosition>> mPushed;
2018-09-29 19:57:41 +00:00
Misc::ScopeGuarded<TilePosition> mPlayerTile;
NavMeshTilesCache mNavMeshTilesCache;
Misc::ScopeGuarded<std::set<std::tuple<AgentBounds, TilePosition>>> mProcessingTiles;
std::map<std::tuple<AgentBounds, TilePosition>, std::chrono::steady_clock::time_point> mLastUpdates;
std::set<std::tuple<AgentBounds, TilePosition>> mPresentTiles;
std::vector<std::thread> mThreads;
std::unique_ptr<DbWorker> mDbWorker;
std::atomic_size_t mDbGetTileHits{ 0 };
2018-03-13 22:49:08 +00:00
void process() noexcept;
2018-03-13 22:49:08 +00:00
JobStatus processJob(Job& job);
2018-03-13 22:49:08 +00:00
inline JobStatus processInitialJob(Job& job, GuardedNavMeshCacheItem& navMeshCacheItem);
inline JobStatus processJobWithDbResult(Job& job, GuardedNavMeshCacheItem& navMeshCacheItem);
inline JobStatus handleUpdateNavMeshStatus(UpdateNavMeshStatus status, const Job& job,
const GuardedNavMeshCacheItem& navMeshCacheItem, const RecastMesh& recastMesh);
2018-03-13 22:49:08 +00:00
JobIt getNextJob();
void postThreadJob(JobIt job, std::deque<JobIt>& queue);
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
2018-04-04 00:20:48 +00:00
bool lockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
void unlockTile(std::size_t jobId, const AgentBounds& agentBounds, const TilePosition& changedTile);
inline std::size_t getTotalJobs() const;
void cleanupLastUpdates();
inline void waitUntilJobsDoneForNotPresentTiles(Loading::Listener* listener);
inline void waitUntilAllJobsDone();
2018-03-13 22:49:08 +00:00
};
}
#endif