mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-19 10:09:43 +00:00
Restore UnrefQueue to destruct animation asynchronously
This commit is contained in:
parent
1e7989c5e5
commit
0614b82452
12 changed files with 109 additions and 14 deletions
|
@ -46,6 +46,7 @@
|
||||||
#include <components/sceneutil/depth.hpp>
|
#include <components/sceneutil/depth.hpp>
|
||||||
#include <components/sceneutil/color.hpp>
|
#include <components/sceneutil/color.hpp>
|
||||||
#include <components/sceneutil/util.hpp>
|
#include <components/sceneutil/util.hpp>
|
||||||
|
#include <components/sceneutil/unrefqueue.hpp>
|
||||||
|
|
||||||
#include <components/settings/shadermanager.hpp>
|
#include <components/settings/shadermanager.hpp>
|
||||||
|
|
||||||
|
@ -419,7 +420,14 @@ bool OMW::Engine::frame(float frametime)
|
||||||
mWindowManager->update(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);
|
stats->setAttribute(frameNumber, "FrameNumber", frameNumber);
|
||||||
|
|
||||||
|
@ -492,6 +500,7 @@ OMW::Engine::~Engine()
|
||||||
|
|
||||||
mScriptContext = nullptr;
|
mScriptContext = nullptr;
|
||||||
|
|
||||||
|
mUnrefQueue = nullptr;
|
||||||
mWorkQueue = nullptr;
|
mWorkQueue = nullptr;
|
||||||
|
|
||||||
mViewer = nullptr;
|
mViewer = nullptr;
|
||||||
|
@ -751,6 +760,7 @@ void OMW::Engine::prepareEngine()
|
||||||
if (numThreads <= 0)
|
if (numThreads <= 0)
|
||||||
throw std::runtime_error("Invalid setting: 'preload num threads' must be >0");
|
throw std::runtime_error("Invalid setting: 'preload num threads' must be >0");
|
||||||
mWorkQueue = new SceneUtil::WorkQueue(numThreads);
|
mWorkQueue = new SceneUtil::WorkQueue(numThreads);
|
||||||
|
mUnrefQueue = std::make_unique<SceneUtil::UnrefQueue>();
|
||||||
|
|
||||||
mScreenCaptureOperation = new SceneUtil::AsyncScreenCaptureOperation(
|
mScreenCaptureOperation = new SceneUtil::AsyncScreenCaptureOperation(
|
||||||
mWorkQueue,
|
mWorkQueue,
|
||||||
|
@ -842,7 +852,7 @@ void OMW::Engine::prepareEngine()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the world
|
// 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,
|
mFileCollections, mContentFiles, mGroundcoverFiles, mEncoder.get(), mActivationDistanceOverride, mCellName,
|
||||||
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string());
|
mStartupScript, mResDir.string(), mCfgMgr.getUserDataPath().string());
|
||||||
mWorld->setupPlayer();
|
mWorld->setupPlayer();
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace SceneUtil
|
||||||
{
|
{
|
||||||
class WorkQueue;
|
class WorkQueue;
|
||||||
class AsyncScreenCaptureOperation;
|
class AsyncScreenCaptureOperation;
|
||||||
|
class UnrefQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
|
@ -120,6 +121,7 @@ namespace OMW
|
||||||
std::unique_ptr<VFS::Manager> mVFS;
|
std::unique_ptr<VFS::Manager> mVFS;
|
||||||
std::unique_ptr<Resource::ResourceSystem> mResourceSystem;
|
std::unique_ptr<Resource::ResourceSystem> mResourceSystem;
|
||||||
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
|
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
|
||||||
|
std::unique_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||||
std::unique_ptr<MWWorld::World> mWorld;
|
std::unique_ptr<MWWorld::World> mWorld;
|
||||||
std::unique_ptr<MWSound::SoundManager> mSoundManager;
|
std::unique_ptr<MWSound::SoundManager> mSoundManager;
|
||||||
std::unique_ptr<MWScript::ScriptManager> mScriptManager;
|
std::unique_ptr<MWScript::ScriptManager> mScriptManager;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <osg/UserDataContainer>
|
#include <osg/UserDataContainer>
|
||||||
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
#include <components/sceneutil/unrefqueue.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -17,9 +18,11 @@
|
||||||
namespace MWRender
|
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)
|
: mRootNode(rootNode)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
|
, mUnrefQueue(unrefQueue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +119,7 @@ bool Objects::removeObject (const MWWorld::Ptr& ptr)
|
||||||
if(iter != mObjects.end())
|
if(iter != mObjects.end())
|
||||||
{
|
{
|
||||||
iter->second->removeFromScene();
|
iter->second->removeFromScene();
|
||||||
|
mUnrefQueue.push(std::move(iter->second));
|
||||||
mObjects.erase(iter);
|
mObjects.erase(iter);
|
||||||
|
|
||||||
if (ptr.getClass().isActor())
|
if (ptr.getClass().isActor())
|
||||||
|
@ -150,6 +154,7 @@ void Objects::removeCell(const MWWorld::CellStore* store)
|
||||||
}
|
}
|
||||||
|
|
||||||
iter->second->removeFromScene();
|
iter->second->removeFromScene();
|
||||||
|
mUnrefQueue.push(std::move(iter->second));
|
||||||
iter = mObjects.erase(iter);
|
iter = mObjects.erase(iter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -24,6 +24,11 @@ namespace MWWorld
|
||||||
class CellStore;
|
class CellStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace SceneUtil
|
||||||
|
{
|
||||||
|
class UnrefQueue;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender{
|
namespace MWRender{
|
||||||
|
|
||||||
class Animation;
|
class Animation;
|
||||||
|
@ -57,15 +62,15 @@ class Objects
|
||||||
typedef std::map<const MWWorld::CellStore*, osg::ref_ptr<osg::Group> > CellMap;
|
typedef std::map<const MWWorld::CellStore*, osg::ref_ptr<osg::Group> > CellMap;
|
||||||
CellMap mCellSceneNodes;
|
CellMap mCellSceneNodes;
|
||||||
PtrAnimationMap mObjects;
|
PtrAnimationMap mObjects;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Group> mRootNode;
|
osg::ref_ptr<osg::Group> mRootNode;
|
||||||
|
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
SceneUtil::UnrefQueue& mUnrefQueue;
|
||||||
|
|
||||||
void insertBegin(const MWWorld::Ptr& ptr);
|
void insertBegin(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
public:
|
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();
|
~Objects();
|
||||||
|
|
||||||
/// @param animated Attempt to load separate keyframes from a .kf file matching the model file?
|
/// @param animated Attempt to load separate keyframes from a .kf file matching the model file?
|
||||||
|
|
|
@ -367,8 +367,9 @@ namespace MWRender
|
||||||
};
|
};
|
||||||
|
|
||||||
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
|
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
|
||||||
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& resourcePath,
|
||||||
const std::string& resourcePath, DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore)
|
DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore,
|
||||||
|
SceneUtil::UnrefQueue& unrefQueue)
|
||||||
: mSkyBlending(Settings::Manager::getBool("sky blending", "Fog"))
|
: mSkyBlending(Settings::Manager::getBool("sky blending", "Fog"))
|
||||||
, mViewer(viewer)
|
, mViewer(viewer)
|
||||||
, mRootNode(rootNode)
|
, mRootNode(rootNode)
|
||||||
|
@ -479,7 +480,7 @@ namespace MWRender
|
||||||
mRecastMesh = std::make_unique<RecastMesh>(mRootNode, Settings::Manager::getBool("enable recast mesh render", "Navigator"));
|
mRecastMesh = std::make_unique<RecastMesh>(mRootNode, Settings::Manager::getBool("enable recast mesh render", "Navigator"));
|
||||||
mPathgrid = std::make_unique<Pathgrid>(mRootNode);
|
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)
|
if (getenv("OPENMW_DONT_PRECOMPILE") == nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace SceneUtil
|
||||||
class ShadowManager;
|
class ShadowManager;
|
||||||
class WorkQueue;
|
class WorkQueue;
|
||||||
class LightManager;
|
class LightManager;
|
||||||
|
class UnrefQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
|
@ -100,9 +101,10 @@ namespace MWRender
|
||||||
class RenderingManager : public MWRender::RenderingInterface
|
class RenderingManager : public MWRender::RenderingInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
|
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
|
||||||
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& resourcePath,
|
||||||
const std::string& resourcePath, DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore);
|
DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore,
|
||||||
|
SceneUtil::UnrefQueue& unrefQueue);
|
||||||
~RenderingManager();
|
~RenderingManager();
|
||||||
|
|
||||||
osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation();
|
osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation();
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
#include <components/sceneutil/lightmanager.hpp>
|
#include <components/sceneutil/lightmanager.hpp>
|
||||||
|
#include <components/sceneutil/workqueue.hpp>
|
||||||
|
|
||||||
#include <components/detournavigator/navigator.hpp>
|
#include <components/detournavigator/navigator.hpp>
|
||||||
#include <components/detournavigator/settings.hpp>
|
#include <components/detournavigator/settings.hpp>
|
||||||
|
@ -139,6 +140,7 @@ namespace MWWorld
|
||||||
osgViewer::Viewer* viewer,
|
osgViewer::Viewer* viewer,
|
||||||
osg::ref_ptr<osg::Group> rootNode,
|
osg::ref_ptr<osg::Group> rootNode,
|
||||||
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||||
|
SceneUtil::UnrefQueue& unrefQueue,
|
||||||
const Files::Collections& fileCollections,
|
const Files::Collections& fileCollections,
|
||||||
const std::vector<std::string>& contentFiles,
|
const std::vector<std::string>& contentFiles,
|
||||||
const std::vector<std::string>& groundcoverFiles,
|
const std::vector<std::string>& groundcoverFiles,
|
||||||
|
@ -187,7 +189,8 @@ namespace MWWorld
|
||||||
mNavigator = DetourNavigator::makeNavigatorStub();
|
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());
|
mProjectileManager = std::make_unique<ProjectileManager>(mRendering->getLightRoot()->asGroup(), resourceSystem, mRendering.get(), mPhysics.get());
|
||||||
mRendering->preloadCommonAssets();
|
mRendering->preloadCommonAssets();
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ namespace Resource
|
||||||
namespace SceneUtil
|
namespace SceneUtil
|
||||||
{
|
{
|
||||||
class WorkQueue;
|
class WorkQueue;
|
||||||
|
class UnrefQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -192,6 +193,7 @@ namespace MWWorld
|
||||||
osgViewer::Viewer* viewer,
|
osgViewer::Viewer* viewer,
|
||||||
osg::ref_ptr<osg::Group> rootNode,
|
osg::ref_ptr<osg::Group> rootNode,
|
||||||
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
||||||
|
SceneUtil::UnrefQueue& unrefQueue,
|
||||||
const Files::Collections& fileCollections,
|
const Files::Collections& fileCollections,
|
||||||
const std::vector<std::string>& contentFiles,
|
const std::vector<std::string>& contentFiles,
|
||||||
const std::vector<std::string>& groundcoverFiles,
|
const std::vector<std::string>& groundcoverFiles,
|
||||||
|
|
|
@ -61,7 +61,7 @@ add_component_dir (sceneutil
|
||||||
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
|
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
|
||||||
lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer
|
lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer
|
||||||
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt
|
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
|
add_component_dir (nif
|
||||||
|
|
|
@ -417,6 +417,7 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
|
||||||
"Compiling",
|
"Compiling",
|
||||||
"WorkQueue",
|
"WorkQueue",
|
||||||
"WorkThread",
|
"WorkThread",
|
||||||
|
"UnrefQueue",
|
||||||
"",
|
"",
|
||||||
"Texture",
|
"Texture",
|
||||||
"StateSet",
|
"StateSet",
|
||||||
|
|
28
components/sceneutil/unrefqueue.cpp
Normal file
28
components/sceneutil/unrefqueue.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
36
components/sceneutil/unrefqueue.hpp
Normal file
36
components/sceneutil/unrefqueue.hpp
Normal 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
|
Loading…
Reference in a new issue