From 6d120f92e00b6846d0a6ddb5779017d33cd7f5d1 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 28 Aug 2023 22:53:46 +0200 Subject: [PATCH] Lookup for terrain template using std::map::lower_bound instead of linear search --- components/resource/objectcache.hpp | 12 ++++++- components/terrain/chunkmanager.cpp | 46 ++++++++++--------------- components/terrain/chunkmanager.hpp | 47 ++++++++++++++++++++++++-- components/terrain/terraindrawable.hpp | 2 +- 4 files changed, 73 insertions(+), 34 deletions(-) diff --git a/components/resource/objectcache.hpp b/components/resource/objectcache.hpp index 3847129ed3..2895aaa3d2 100644 --- a/components/resource/objectcache.hpp +++ b/components/resource/objectcache.hpp @@ -195,11 +195,21 @@ namespace Resource return _objectCache.size(); } + template + std::optional>> lowerBound(K&& key) + { + const std::lock_guard lock(_objectCacheMutex); + const auto it = _objectCache.lower_bound(std::forward(key)); + if (it == _objectCache.end()) + return std::nullopt; + return std::pair(it->first, it->second.first); + } + protected: virtual ~GenericObjectCache() {} typedef std::pair, double> ObjectTimeStampPair; - typedef std::map ObjectCacheMap; + typedef std::map> ObjectCacheMap; ObjectCacheMap _objectCache; mutable std::mutex _objectCacheMutex; diff --git a/components/terrain/chunkmanager.cpp b/components/terrain/chunkmanager.cpp index 0364a0a4fd..6273041f72 100644 --- a/components/terrain/chunkmanager.cpp +++ b/components/terrain/chunkmanager.cpp @@ -21,7 +21,7 @@ namespace Terrain ChunkManager::ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer, ESM::RefId worldspace) - : GenericResourceManager(nullptr) + : GenericResourceManager(nullptr) , QuadTreeWorld::ChunkManager(worldspace) , mStorage(storage) , mSceneManager(sceneMgr) @@ -39,38 +39,26 @@ namespace Terrain mMultiPassRoot->setAttributeAndModes(material, osg::StateAttribute::ON); } - struct FindChunkTemplate - { - void operator()(ChunkId id, osg::Object* obj) - { - if (std::get<0>(id) == std::get<0>(mId) && std::get<1>(id) == std::get<1>(mId)) - mFoundTemplate = obj; - } - ChunkId mId; - osg::ref_ptr mFoundTemplate; - }; - osg::ref_ptr ChunkManager::getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags, bool activeGrid, const osg::Vec3f& viewPoint, bool compile) { // Override lod with the vertexLodMod adjusted value. // TODO: maybe we can refactor this code by moving all vertexLodMod code into this class. lod = static_cast(lodFlags >> (4 * 4)); - ChunkId id = std::make_tuple(center, lod, lodFlags); - osg::ref_ptr obj = mCache->getRefFromObjectCache(id); - if (obj) + + const ChunkKey key{ .mCenter = center, .mLod = lod, .mLodFlags = lodFlags }; + if (osg::ref_ptr obj = mCache->getRefFromObjectCache(key)) return static_cast(obj.get()); - else - { - FindChunkTemplate find; - find.mId = id; - mCache->call(find); - TerrainDrawable* templateGeometry - = find.mFoundTemplate ? static_cast(find.mFoundTemplate.get()) : nullptr; - osg::ref_ptr node = createChunk(size, center, lod, lodFlags, compile, templateGeometry); - mCache->addEntryToObjectCache(id, node.get()); - return node; - } + + const TerrainDrawable* templateGeometry = nullptr; + const TemplateKey templateKey{ .mCenter = center, .mLod = lod }; + const auto pair = mCache->lowerBound(templateKey); + if (pair.has_value() && templateKey == TemplateKey{ .mCenter = pair->first.mCenter, .mLod = pair->first.mLod }) + templateGeometry = static_cast(pair->second.get()); + + osg::ref_ptr node = createChunk(size, center, lod, lodFlags, compile, templateGeometry); + mCache->addEntryToObjectCache(key, node.get()); + return node; } void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const @@ -80,14 +68,14 @@ namespace Terrain void ChunkManager::clearCache() { - GenericResourceManager::clearCache(); + GenericResourceManager::clearCache(); mBufferCache.clearCache(); } void ChunkManager::releaseGLObjects(osg::State* state) { - GenericResourceManager::releaseGLObjects(state); + GenericResourceManager::releaseGLObjects(state); mBufferCache.releaseGLObjects(state); } @@ -202,7 +190,7 @@ namespace Terrain } osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Vec2f& chunkCenter, unsigned char lod, - unsigned int lodFlags, bool compile, TerrainDrawable* templateGeometry) + unsigned int lodFlags, bool compile, const TerrainDrawable* templateGeometry) { osg::ref_ptr geometry(new TerrainDrawable); diff --git a/components/terrain/chunkmanager.hpp b/components/terrain/chunkmanager.hpp index 4238f01c8b..a55dd15cc1 100644 --- a/components/terrain/chunkmanager.hpp +++ b/components/terrain/chunkmanager.hpp @@ -28,10 +28,51 @@ namespace Terrain class CompositeMap; class TerrainDrawable; - typedef std::tuple ChunkId; // Center, Lod, Lod Flags + struct TemplateKey + { + osg::Vec2f mCenter; + unsigned char mLod; + }; + + inline auto tie(const TemplateKey& v) + { + return std::tie(v.mCenter, v.mLod); + } + + inline bool operator<(const TemplateKey& l, const TemplateKey& r) + { + return tie(l) < tie(r); + } + + inline bool operator==(const TemplateKey& l, const TemplateKey& r) + { + return tie(l) == tie(r); + } + + struct ChunkKey + { + osg::Vec2f mCenter; + unsigned char mLod; + unsigned mLodFlags; + }; + + inline auto tie(const ChunkKey& v) + { + return std::tie(v.mCenter, v.mLod, v.mLodFlags); + } + + inline bool operator<(const ChunkKey& l, const ChunkKey& r) + { + return tie(l) < tie(r); + } + + inline bool operator<(const ChunkKey& l, const TemplateKey& r) + { + return TemplateKey{ .mCenter = l.mCenter, .mLod = l.mLod } < r; + } /// @brief Handles loading and caching of terrain chunks - class ChunkManager : public Resource::GenericResourceManager, public QuadTreeWorld::ChunkManager + class ChunkManager : public Resource::GenericResourceManager, public QuadTreeWorld::ChunkManager { public: ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, @@ -55,7 +96,7 @@ namespace Terrain private: osg::ref_ptr createChunk(float size, const osg::Vec2f& center, unsigned char lod, - unsigned int lodFlags, bool compile, TerrainDrawable* templateGeometry); + unsigned int lodFlags, bool compile, const TerrainDrawable* templateGeometry); osg::ref_ptr createCompositeMapRTT(); diff --git a/components/terrain/terraindrawable.hpp b/components/terrain/terraindrawable.hpp index b94f47df97..3ce846ad73 100644 --- a/components/terrain/terraindrawable.hpp +++ b/components/terrain/terraindrawable.hpp @@ -60,7 +60,7 @@ namespace Terrain const osg::BoundingBox& getWaterBoundingBox() const { return mWaterBoundingBox; } void setCompositeMap(CompositeMap* map) { mCompositeMap = map; } - CompositeMap* getCompositeMap() { return mCompositeMap; } + CompositeMap* getCompositeMap() const { return mCompositeMap; } void setCompositeMapRenderer(CompositeMapRenderer* renderer) { mCompositeMapRenderer = renderer; } private: