mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-22 13:39:40 +00:00
Merge pull request #2021 from elsid/recast_global_allocator
Recast global allocator
This commit is contained in:
commit
28913758ce
6 changed files with 286 additions and 51 deletions
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <components/detournavigator/debug.hpp>
|
#include <components/detournavigator/debug.hpp>
|
||||||
#include <components/detournavigator/navigator.hpp>
|
#include <components/detournavigator/navigator.hpp>
|
||||||
#include <components/detournavigator/debug.hpp>
|
#include <components/detournavigator/recastglobalallocator.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/soundmanager.hpp"
|
#include "../mwbase/soundmanager.hpp"
|
||||||
|
@ -230,6 +230,7 @@ namespace MWWorld
|
||||||
if (Settings::Manager::getBool("enable log", "Navigator"))
|
if (Settings::Manager::getBool("enable log", "Navigator"))
|
||||||
DetourNavigator::Log::instance().setSink(std::unique_ptr<DetourNavigator::FileSink>(
|
DetourNavigator::Log::instance().setSink(std::unique_ptr<DetourNavigator::FileSink>(
|
||||||
new DetourNavigator::FileSink(Settings::Manager::getString("log path", "Navigator"))));
|
new DetourNavigator::FileSink(Settings::Manager::getString("log path", "Navigator"))));
|
||||||
|
DetourNavigator::RecastGlobalAllocator::init();
|
||||||
mNavigator.reset(new DetourNavigator::Navigator(navigatorSettings));
|
mNavigator.reset(new DetourNavigator::Navigator(navigatorSettings));
|
||||||
|
|
||||||
mRendering.reset(new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath, *mNavigator));
|
mRendering.reset(new MWRender::RenderingManager(viewer, rootNode, resourceSystem, workQueue, &mFallback, resourcePath, *mNavigator));
|
||||||
|
|
|
@ -50,8 +50,8 @@ namespace DetourNavigator
|
||||||
ChunkyTriMesh& operator=(const ChunkyTriMesh&) = delete;
|
ChunkyTriMesh& operator=(const ChunkyTriMesh&) = delete;
|
||||||
|
|
||||||
/// Returns the chunk indices which overlap the input rectable.
|
/// Returns the chunk indices which overlap the input rectable.
|
||||||
template <class OutputIterator>
|
template <class Function>
|
||||||
void getChunksOverlappingRect(const Rect& rect, OutputIterator out) const
|
void forEachChunksOverlappingRect(const Rect& rect, Function&& function) const
|
||||||
{
|
{
|
||||||
// Traverse tree
|
// Traverse tree
|
||||||
for (std::size_t i = 0; i < mNodes.size(); )
|
for (std::size_t i = 0; i < mNodes.size(); )
|
||||||
|
@ -61,7 +61,7 @@ namespace DetourNavigator
|
||||||
const bool isLeafNode = node->mOffset >= 0;
|
const bool isLeafNode = node->mOffset >= 0;
|
||||||
|
|
||||||
if (isLeafNode && overlap)
|
if (isLeafNode && overlap)
|
||||||
*out++ = i;
|
function(i);
|
||||||
|
|
||||||
if (overlap || isLeafNode)
|
if (overlap || isLeafNode)
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -149,13 +149,10 @@ namespace
|
||||||
std::vector<unsigned char> areas(chunkyMesh.getMaxTrisPerChunk(), AreaType_null);
|
std::vector<unsigned char> areas(chunkyMesh.getMaxTrisPerChunk(), AreaType_null);
|
||||||
const osg::Vec2f tileBoundsMin(config.bmin[0], config.bmin[2]);
|
const osg::Vec2f tileBoundsMin(config.bmin[0], config.bmin[2]);
|
||||||
const osg::Vec2f tileBoundsMax(config.bmax[0], config.bmax[2]);
|
const osg::Vec2f tileBoundsMax(config.bmax[0], config.bmax[2]);
|
||||||
std::vector<std::size_t> cids;
|
bool result = false;
|
||||||
chunkyMesh.getChunksOverlappingRect(Rect {tileBoundsMin, tileBoundsMax}, std::back_inserter(cids));
|
|
||||||
|
|
||||||
if (cids.empty())
|
chunkyMesh.forEachChunksOverlappingRect(Rect {tileBoundsMin, tileBoundsMax},
|
||||||
return false;
|
[&] (const std::size_t cid)
|
||||||
|
|
||||||
for (const auto cid : cids)
|
|
||||||
{
|
{
|
||||||
const auto chunk = chunkyMesh.getChunk(cid);
|
const auto chunk = chunkyMesh.getChunk(cid);
|
||||||
|
|
||||||
|
@ -202,9 +199,11 @@ namespace
|
||||||
|
|
||||||
if (!trianglesRasterized)
|
if (!trianglesRasterized)
|
||||||
throw NavigatorException("Failed to create rasterize triangles from recast mesh for navmesh");
|
throw NavigatorException("Failed to create rasterize triangles from recast mesh for navmesh");
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
result = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rasterizeWaterTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
void rasterizeWaterTriangles(rcContext& context, const osg::Vec3f& agentHalfExtents, const RecastMesh& recastMesh,
|
||||||
|
|
102
components/detournavigator/recastallocutils.hpp
Normal file
102
components/detournavigator/recastallocutils.hpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTALLOCUTILS_H
|
||||||
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTALLOCUTILS_H
|
||||||
|
|
||||||
|
#include <RecastAlloc.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace DetourNavigator
|
||||||
|
{
|
||||||
|
static_assert(sizeof(std::size_t) == sizeof(void*), "");
|
||||||
|
|
||||||
|
enum BufferType : std::size_t
|
||||||
|
{
|
||||||
|
BufferType_perm,
|
||||||
|
BufferType_temp,
|
||||||
|
BufferType_unused,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline BufferType* tempPtrBufferType(void* ptr)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<BufferType*>(static_cast<std::size_t*>(ptr) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BufferType getTempPtrBufferType(void* ptr)
|
||||||
|
{
|
||||||
|
return *tempPtrBufferType(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setTempPtrBufferType(void* ptr, BufferType value)
|
||||||
|
{
|
||||||
|
*tempPtrBufferType(ptr) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void** tempPtrPrev(void* ptr)
|
||||||
|
{
|
||||||
|
return static_cast<void**>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* getTempPtrPrev(void* ptr)
|
||||||
|
{
|
||||||
|
return *tempPtrPrev(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setTempPtrPrev(void* ptr, void* value)
|
||||||
|
{
|
||||||
|
*tempPtrPrev(ptr) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* getTempPtrDataPtr(void* ptr)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<void*>(static_cast<std::size_t*>(ptr) + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BufferType* dataPtrBufferType(void* dataPtr)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<BufferType*>(static_cast<std::size_t*>(dataPtr) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline BufferType getDataPtrBufferType(void* dataPtr)
|
||||||
|
{
|
||||||
|
return *dataPtrBufferType(dataPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setDataPtrBufferType(void* dataPtr, BufferType value)
|
||||||
|
{
|
||||||
|
*dataPtrBufferType(dataPtr) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* getTempDataPtrStackPtr(void* dataPtr)
|
||||||
|
{
|
||||||
|
return static_cast<std::size_t*>(dataPtr) - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* getPermDataPtrHeapPtr(void* dataPtr)
|
||||||
|
{
|
||||||
|
return static_cast<std::size_t*>(dataPtr) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setPermPtrBufferType(void* ptr, BufferType value)
|
||||||
|
{
|
||||||
|
*static_cast<BufferType*>(ptr) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* getPermPtrDataPtr(void* ptr)
|
||||||
|
{
|
||||||
|
return static_cast<std::size_t*>(ptr) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: use std::align
|
||||||
|
inline void* align(std::size_t align, std::size_t size, void*& ptr, std::size_t& space) noexcept
|
||||||
|
{
|
||||||
|
const auto intptr = reinterpret_cast<std::uintptr_t>(ptr);
|
||||||
|
const auto aligned = (intptr - 1u + align) & - align;
|
||||||
|
const auto diff = aligned - intptr;
|
||||||
|
if ((size + diff) > space)
|
||||||
|
return nullptr;
|
||||||
|
space -= diff;
|
||||||
|
return ptr = reinterpret_cast<void*>(aligned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
68
components/detournavigator/recastglobalallocator.hpp
Normal file
68
components/detournavigator/recastglobalallocator.hpp
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTGLOBALALLOCATOR_H
|
||||||
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTGLOBALALLOCATOR_H
|
||||||
|
|
||||||
|
#include "recasttempallocator.hpp"
|
||||||
|
|
||||||
|
namespace DetourNavigator
|
||||||
|
{
|
||||||
|
class RecastGlobalAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void init()
|
||||||
|
{
|
||||||
|
instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* alloc(size_t size, rcAllocHint hint)
|
||||||
|
{
|
||||||
|
void* result = nullptr;
|
||||||
|
if (rcLikely(hint == RC_ALLOC_TEMP))
|
||||||
|
result = tempAllocator().alloc(size);
|
||||||
|
if (rcUnlikely(!result))
|
||||||
|
result = allocPerm(size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free(void* ptr)
|
||||||
|
{
|
||||||
|
if (rcUnlikely(!ptr))
|
||||||
|
return;
|
||||||
|
if (rcLikely(BufferType_temp == getDataPtrBufferType(ptr)))
|
||||||
|
tempAllocator().free(ptr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(BufferType_perm == getDataPtrBufferType(ptr));
|
||||||
|
::free(getPermDataPtrHeapPtr(ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RecastGlobalAllocator()
|
||||||
|
{
|
||||||
|
rcAllocSetCustom(&RecastGlobalAllocator::alloc, &RecastGlobalAllocator::free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static RecastGlobalAllocator& instance()
|
||||||
|
{
|
||||||
|
static RecastGlobalAllocator value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RecastTempAllocator& tempAllocator()
|
||||||
|
{
|
||||||
|
static thread_local RecastTempAllocator value(1024ul * 1024ul);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* allocPerm(size_t size)
|
||||||
|
{
|
||||||
|
const auto ptr = ::malloc(size + sizeof(std::size_t));
|
||||||
|
if (rcUnlikely(!ptr))
|
||||||
|
return ptr;
|
||||||
|
setPermPtrBufferType(ptr, BufferType_perm);
|
||||||
|
return getPermPtrDataPtr(ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
65
components/detournavigator/recasttempallocator.hpp
Normal file
65
components/detournavigator/recasttempallocator.hpp
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTTEMPALLOCATOR_H
|
||||||
|
#define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTTEMPALLOCATOR_H
|
||||||
|
|
||||||
|
#include "recastallocutils.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace DetourNavigator
|
||||||
|
{
|
||||||
|
class RecastTempAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RecastTempAllocator(std::size_t capacity)
|
||||||
|
: mStack(capacity), mTop(mStack.data()), mPrev(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void* alloc(std::size_t size)
|
||||||
|
{
|
||||||
|
std::size_t space = mStack.size() - getUsedSize();
|
||||||
|
void* top = mTop;
|
||||||
|
const auto itemSize = 2 * sizeof(std::size_t) + size;
|
||||||
|
if (rcUnlikely(!align(sizeof(std::size_t), itemSize, top, space)))
|
||||||
|
return nullptr;
|
||||||
|
setTempPtrBufferType(top, BufferType_temp);
|
||||||
|
setTempPtrPrev(top, mPrev);
|
||||||
|
mTop = static_cast<char*>(top) + itemSize;
|
||||||
|
mPrev = static_cast<char*>(top);
|
||||||
|
return getTempPtrDataPtr(top);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void* ptr)
|
||||||
|
{
|
||||||
|
if (rcUnlikely(!ptr))
|
||||||
|
return;
|
||||||
|
assert(BufferType_temp == getDataPtrBufferType(ptr));
|
||||||
|
if (!mPrev || getTempDataPtrStackPtr(ptr) != mPrev)
|
||||||
|
{
|
||||||
|
setDataPtrBufferType(ptr, BufferType_unused);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mTop = getTempDataPtrStackPtr(ptr);
|
||||||
|
mPrev = getTempPtrPrev(mTop);
|
||||||
|
while (mPrev && BufferType_unused == getTempPtrBufferType(mPrev))
|
||||||
|
{
|
||||||
|
mTop = mPrev;
|
||||||
|
mPrev = getTempPtrPrev(mTop);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<char> mStack;
|
||||||
|
void* mTop;
|
||||||
|
void* mPrev;
|
||||||
|
|
||||||
|
std::size_t getUsedSize() const
|
||||||
|
{
|
||||||
|
return static_cast<std::size_t>(static_cast<char*>(mTop) - mStack.data());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue