1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-15 23:09:42 +00:00

Restore UnrefQueue to destruct animation asynchronously

This commit is contained in:
elsid 2022-07-24 20:55:03 +02:00
parent 1e7989c5e5
commit 0614b82452
No known key found for this signature in database
GPG key ID: 4DE04C198CBA7625
12 changed files with 109 additions and 14 deletions

View file

@ -46,6 +46,7 @@
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/color.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/unrefqueue.hpp>
#include <components/settings/shadermanager.hpp>
@ -419,7 +420,14 @@ bool OMW::Engine::frame(float frametime)
mWindowManager->update(frametime);
}
if (stats->collectStats("resource"))
const bool reportResource = stats->collectStats("resource");
if (reportResource)
stats->setAttribute(frameNumber, "UnrefQueue", mUnrefQueue->getSize());
mUnrefQueue->flush(*mWorkQueue);
if (reportResource)
{
stats->setAttribute(frameNumber, "FrameNumber", frameNumber);
@ -492,6 +500,7 @@ OMW::Engine::~Engine()
mScriptContext = nullptr;
mUnrefQueue = nullptr;
mWorkQueue = nullptr;
mViewer = nullptr;
@ -751,6 +760,7 @@ void OMW::Engine::prepareEngine()
if (numThreads <= 0)
throw std::runtime_error("Invalid setting: 'preload num threads' must be >0");
mWorkQueue = new SceneUtil::WorkQueue(numThreads);
mUnrefQueue = std::make_unique<SceneUtil::UnrefQueue>();
mScreenCaptureOperation = new SceneUtil::AsyncScreenCaptureOperation(
mWorkQueue,
@ -842,7 +852,7 @@ void OMW::Engine::prepareEngine()
}
// Create the world
mWorld = std::make_unique<MWWorld::World>(mViewer, rootNode, mResourceSystem.get(), mWorkQueue.get(),
mWorld = std::make_unique<MWWorld::World>(mViewer, rootNode, mResourceSystem.get(), mWorkQueue.get(), *mUnrefQueue,
mFileCollections, mContentFiles, mGroundcoverFiles, mEncoder.get(), mActivationDistanceOverride, mCellName,
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string());
mWorld->setupPlayer();

View file

@ -22,6 +22,7 @@ namespace SceneUtil
{
class WorkQueue;
class AsyncScreenCaptureOperation;
class UnrefQueue;
}
namespace VFS
@ -120,6 +121,7 @@ namespace OMW
std::unique_ptr<VFS::Manager> mVFS;
std::unique_ptr<Resource::ResourceSystem> mResourceSystem;
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
std::unique_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
std::unique_ptr<MWWorld::World> mWorld;
std::unique_ptr<MWSound::SoundManager> mSoundManager;
std::unique_ptr<MWScript::ScriptManager> mScriptManager;

View file

@ -4,6 +4,7 @@
#include <osg/UserDataContainer>
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/unrefqueue.hpp>
#include "../mwworld/ptr.hpp"
#include "../mwworld/class.hpp"
@ -17,9 +18,11 @@
namespace MWRender
{
Objects::Objects(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> rootNode)
Objects::Objects(Resource::ResourceSystem* resourceSystem, const osg::ref_ptr<osg::Group>& rootNode,
SceneUtil::UnrefQueue& unrefQueue)
: mRootNode(rootNode)
, mResourceSystem(resourceSystem)
, mUnrefQueue(unrefQueue)
{
}
@ -116,6 +119,7 @@ bool Objects::removeObject (const MWWorld::Ptr& ptr)
if(iter != mObjects.end())
{
iter->second->removeFromScene();
mUnrefQueue.push(std::move(iter->second));
mObjects.erase(iter);
if (ptr.getClass().isActor())
@ -150,6 +154,7 @@ void Objects::removeCell(const MWWorld::CellStore* store)
}
iter->second->removeFromScene();
mUnrefQueue.push(std::move(iter->second));
iter = mObjects.erase(iter);
}
else

View file

@ -24,6 +24,11 @@ namespace MWWorld
class CellStore;
}
namespace SceneUtil
{
class UnrefQueue;
}
namespace MWRender{
class Animation;
@ -57,15 +62,15 @@ class Objects
typedef std::map<const MWWorld::CellStore*, osg::ref_ptr<osg::Group> > CellMap;
CellMap mCellSceneNodes;
PtrAnimationMap mObjects;
osg::ref_ptr<osg::Group> mRootNode;
Resource::ResourceSystem* mResourceSystem;
SceneUtil::UnrefQueue& mUnrefQueue;
void insertBegin(const MWWorld::Ptr& ptr);
public:
Objects(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> rootNode);
Objects(Resource::ResourceSystem* resourceSystem, const osg::ref_ptr<osg::Group>& rootNode,
SceneUtil::UnrefQueue& unrefQueue);
~Objects();
/// @param animated Attempt to load separate keyframes from a .kf file matching the model file?

View file

@ -367,8 +367,9 @@ namespace MWRender
};
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
const std::string& resourcePath, DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore)
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& resourcePath,
DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore,
SceneUtil::UnrefQueue& unrefQueue)
: mSkyBlending(Settings::Manager::getBool("sky blending", "Fog"))
, mViewer(viewer)
, mRootNode(rootNode)
@ -479,7 +480,7 @@ namespace MWRender
mRecastMesh = std::make_unique<RecastMesh>(mRootNode, Settings::Manager::getBool("enable recast mesh render", "Navigator"));
mPathgrid = std::make_unique<Pathgrid>(mRootNode);
mObjects = std::make_unique<Objects>(mResourceSystem, sceneRoot);
mObjects = std::make_unique<Objects>(mResourceSystem, sceneRoot, unrefQueue);
if (getenv("OPENMW_DONT_PRECOMPILE") == nullptr)
{

View file

@ -60,6 +60,7 @@ namespace SceneUtil
class ShadowManager;
class WorkQueue;
class LightManager;
class UnrefQueue;
}
namespace DetourNavigator
@ -100,9 +101,10 @@ namespace MWRender
class RenderingManager : public MWRender::RenderingInterface
{
public:
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
const std::string& resourcePath, DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore);
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& resourcePath,
DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore,
SceneUtil::UnrefQueue& unrefQueue);
~RenderingManager();
osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation();

View file

@ -28,6 +28,7 @@
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/workqueue.hpp>
#include <components/detournavigator/navigator.hpp>
#include <components/detournavigator/settings.hpp>
@ -139,6 +140,7 @@ namespace MWWorld
osgViewer::Viewer* viewer,
osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
SceneUtil::UnrefQueue& unrefQueue,
const Files::Collections& fileCollections,
const std::vector<std::string>& contentFiles,
const std::vector<std::string>& groundcoverFiles,
@ -187,7 +189,8 @@ namespace MWWorld
mNavigator = DetourNavigator::makeNavigatorStub();
}
mRendering = std::make_unique<MWRender::RenderingManager>(viewer, rootNode, resourceSystem, workQueue, resourcePath, *mNavigator, mGroundcoverStore);
mRendering = std::make_unique<MWRender::RenderingManager>(viewer, rootNode, resourceSystem, workQueue,
resourcePath, *mNavigator, mGroundcoverStore, unrefQueue);
mProjectileManager = std::make_unique<ProjectileManager>(mRendering->getLightRoot()->asGroup(), resourceSystem, mRendering.get(), mPhysics.get());
mRendering->preloadCommonAssets();

View file

@ -38,6 +38,7 @@ namespace Resource
namespace SceneUtil
{
class WorkQueue;
class UnrefQueue;
}
namespace ESM
@ -192,6 +193,7 @@ namespace MWWorld
osgViewer::Viewer* viewer,
osg::ref_ptr<osg::Group> rootNode,
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
SceneUtil::UnrefQueue& unrefQueue,
const Files::Collections& fileCollections,
const std::vector<std::string>& contentFiles,
const std::vector<std::string>& groundcoverFiles,

View file

@ -61,7 +61,7 @@ add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt
screencapture depth color riggeometryosgaextension extradata
screencapture depth color riggeometryosgaextension extradata unrefqueue
)
add_component_dir (nif

View file

@ -417,6 +417,7 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
"Compiling",
"WorkQueue",
"WorkThread",
"UnrefQueue",
"",
"Texture",
"StateSet",

View file

@ -0,0 +1,28 @@
#include "unrefqueue.hpp"
namespace SceneUtil
{
namespace
{
struct ClearVector final : SceneUtil::WorkItem
{
std::vector<osg::ref_ptr<osg::Referenced>> mObjects;
explicit ClearVector(std::vector<osg::ref_ptr<osg::Referenced>>&& objects)
: mObjects(std::move(objects)) {}
void doWork() override { mObjects.clear(); }
};
}
void UnrefQueue::flush(SceneUtil::WorkQueue& workQueue)
{
if (mObjects.empty())
return;
// Move only objects to keep allocated storage in mObjects
workQueue.addWorkItem(new ClearVector(std::vector<osg::ref_ptr<osg::Referenced>>(
std::move_iterator(mObjects.begin()), std::move_iterator(mObjects.end()))));
mObjects.clear();
}
}

View file

@ -0,0 +1,36 @@
#ifndef OPENMW_COMPONENTS_UNREFQUEUE_H
#define OPENMW_COMPONENTS_UNREFQUEUE_H
#include "workqueue.hpp"
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <vector>
namespace SceneUtil
{
class WorkQueue;
/// @brief Handles unreferencing of objects through the WorkQueue. Typical use scenario
/// would be the main thread pushing objects that are no longer needed, and the background thread deleting them.
class UnrefQueue
{
public:
/// Adds an object to the list of objects to be unreferenced. Call from the main thread.
void push(osg::ref_ptr<osg::Referenced>&& obj) { mObjects.push_back(std::move(obj)); }
void push(const osg::ref_ptr<osg::Referenced>& obj) { mObjects.push_back(obj); }
/// Adds a WorkItem to the given WorkQueue that will clear the list of objects in a worker thread,
/// thus unreferencing them. Call from the main thread.
void flush(SceneUtil::WorkQueue& workQueue);
std::size_t getSize() const { return mObjects.size(); }
private:
std::vector<osg::ref_ptr<osg::Referenced>> mObjects;
};
}
#endif